agents/contracts/inbox/inbox.contractinfo.json
{"solidity/Inbox.sol:AddressUpgradeable":{"code":"0x60566037600b82828239805160001a607314602a57634e487b7160e01b600052600060045260246000fd5b30600052607381538281f3fe73000000000000000000000000000000000000000030146080604052600080fdfea2646970667358221220b9aa9bc27e7eb8f8a6663b73a4d290ef616fdff4c76c5187820fdbdc666326e864736f6c63430008110033","runtime-code":"0x73000000000000000000000000000000000000000030146080604052600080fdfea2646970667358221220b9aa9bc27e7eb8f8a6663b73a4d290ef616fdff4c76c5187820fdbdc666326e864736f6c63430008110033","info":{"source":"// SPDX-License-Identifier: MIT\npragma solidity =0.8.17 ^0.8.0 ^0.8.1 ^0.8.2;\n\n// contracts/events/InboxEvents.sol\n\nabstract contract InboxEvents {\n /**\n * @notice Emitted when a snapshot is accepted by the Summit contract.\n * @param domain Domain where the signed Agent is active (ZERO for Guards)\n * @param agent Agent who signed the snapshot\n * @param snapPayload Raw payload with snapshot data\n * @param snapSignature Agent signature for the snapshot\n */\n event SnapshotAccepted(uint32 indexed domain, address indexed agent, bytes snapPayload, bytes snapSignature);\n\n /**\n * @notice Emitted when a snapshot is accepted by the Summit contract.\n * @param domain Domain where the signed Notary is active\n * @param notary Notary who signed the attestation\n * @param rcptPayload Raw payload with receipt data\n * @param rcptSignature Notary signature for the receipt\n */\n event ReceiptAccepted(uint32 domain, address notary, bytes rcptPayload, bytes rcptSignature);\n\n /**\n * @notice Emitted when a proof of invalid attestation is submitted.\n * @param attPayload Raw payload with Attestation data\n * @param attSignature Notary signature for the attestation\n */\n event InvalidAttestation(bytes attPayload, bytes attSignature);\n\n /**\n * @notice Emitted when a proof of invalid attestation report is submitted.\n * @param arPayload Raw payload with report data\n * @param arSignature Guard signature for the report\n */\n event InvalidAttestationReport(bytes arPayload, bytes arSignature);\n}\n\n// contracts/events/StatementInboxEvents.sol\n\nabstract contract StatementInboxEvents {\n // ════════════════════════════════════════════ STATEMENT ACCEPTED ═════════════════════════════════════════════════\n\n /**\n * @notice Emitted when a snapshot is accepted by the Destination contract.\n * @param domain Domain where the signed Notary is active\n * @param notary Notary who signed the attestation\n * @param attPayload Raw payload with attestation data\n * @param attSignature Notary signature for the attestation\n */\n event AttestationAccepted(uint32 domain, address notary, bytes attPayload, bytes attSignature);\n\n // ═════════════════════════════════════════ INVALID STATEMENT PROVED ══════════════════════════════════════════════\n\n /**\n * @notice Emitted when a proof of invalid receipt statement is submitted.\n * @param rcptPayload Raw payload with the receipt statement\n * @param rcptSignature Notary signature for the receipt statement\n */\n event InvalidReceipt(bytes rcptPayload, bytes rcptSignature);\n\n /**\n * @notice Emitted when a proof of invalid receipt report is submitted.\n * @param rrPayload Raw payload with report data\n * @param rrSignature Guard signature for the report\n */\n event InvalidReceiptReport(bytes rrPayload, bytes rrSignature);\n\n /**\n * @notice Emitted when a proof of invalid state in the signed attestation is submitted.\n * @param stateIndex Index of invalid state in the snapshot\n * @param statePayload Raw payload with state data\n * @param attPayload Raw payload with Attestation data for snapshot\n * @param attSignature Notary signature for the attestation\n */\n event InvalidStateWithAttestation(uint8 stateIndex, bytes statePayload, bytes attPayload, bytes attSignature);\n\n /**\n * @notice Emitted when a proof of invalid state in the signed snapshot is submitted.\n * @param stateIndex Index of invalid state in the snapshot\n * @param snapPayload Raw payload with snapshot data\n * @param snapSignature Agent signature for the snapshot\n */\n event InvalidStateWithSnapshot(uint8 stateIndex, bytes snapPayload, bytes snapSignature);\n\n /**\n * @notice Emitted when a proof of invalid state report is submitted.\n * @param srPayload Raw payload with report data\n * @param srSignature Guard signature for the report\n */\n event InvalidStateReport(bytes srPayload, bytes srSignature);\n}\n\n// contracts/interfaces/ISnapshotHub.sol\n\ninterface ISnapshotHub {\n /**\n * @notice Check that a given attestation is valid: matches the historical attestation\n * derived from an accepted Notary snapshot.\n * @dev Will revert if any of these is true:\n * - Attestation payload is not properly formatted.\n * @param attPayload Raw payload with attestation data\n * @return isValid Whether the provided attestation is valid\n */\n function isValidAttestation(bytes memory attPayload) external view returns (bool isValid);\n\n /**\n * @notice Returns saved attestation with the given nonce.\n * @dev Reverts if attestation with given nonce hasn't been created yet.\n * @param attNonce Nonce for the attestation\n * @return attPayload Raw payload with formatted Attestation data\n * @return agentRoot Agent root hash used for the attestation\n * @return snapGas Snapshot gas data used for the attestation\n */\n function getAttestation(uint32 attNonce)\n external\n view\n returns (bytes memory attPayload, bytes32 agentRoot, uint256[] memory snapGas);\n\n /**\n * @notice Returns the state with the highest known nonce submitted by a given Agent.\n * @param origin Domain of origin chain\n * @param agent Agent address\n * @return statePayload Raw payload with agent's latest state for origin\n */\n function getLatestAgentState(uint32 origin, address agent) external view returns (bytes memory statePayload);\n\n /**\n * @notice Returns latest saved attestation for a Notary.\n * @param notary Notary address\n * @return attPayload Raw payload with formatted Attestation data\n * @return agentRoot Agent root hash used for the attestation\n * @return snapGas Snapshot gas data used for the attestation\n */\n function getLatestNotaryAttestation(address notary)\n external\n view\n returns (bytes memory attPayload, bytes32 agentRoot, uint256[] memory snapGas);\n\n /**\n * @notice Returns Guard snapshot from the list of all accepted Guard snapshots.\n * @dev Reverts if snapshot with given index hasn't been accepted yet.\n * @param index Snapshot index in the list of all Guard snapshots\n * @return snapPayload Raw payload with Guard snapshot\n * @return snapSignature Raw payload with Guard signature for snapshot\n */\n function getGuardSnapshot(uint256 index)\n external\n view\n returns (bytes memory snapPayload, bytes memory snapSignature);\n\n /**\n * @notice Returns Notary snapshot from the list of all accepted Guard snapshots.\n * @dev Reverts if snapshot with given index hasn't been accepted yet.\n * @param index Snapshot index in the list of all Notary snapshots\n * @return snapPayload Raw payload with Notary snapshot\n * @return snapSignature Raw payload with Notary signature for snapshot\n */\n function getNotarySnapshot(uint256 index)\n external\n view\n returns (bytes memory snapPayload, bytes memory snapSignature);\n\n /**\n * @notice Returns Notary snapshot that was used for creating a given attestation.\n * @dev Reverts if any of these is true:\n * - Attestation payload is not properly formatted.\n * - Attestation is invalid (doesn't have a matching Notary snapshot).\n * @param attPayload Raw payload with attestation data\n * @return snapPayload Raw payload with Notary snapshot\n * @return snapSignature Raw payload with Notary signature for snapshot\n */\n function getNotarySnapshot(bytes memory attPayload)\n external\n view\n returns (bytes memory snapPayload, bytes memory snapSignature);\n\n /**\n * @notice Returns proof of inclusion of (root, origin) fields of a given snapshot's state\n * into the Snapshot Merkle Tree for a given attestation.\n * @dev Reverts if any of these is true:\n * - Attestation with given nonce hasn't been created yet.\n * - State index is out of range of snapshot list.\n * @param attNonce Nonce for the attestation\n * @param stateIndex Index of state in the attestation's snapshot\n * @return snapProof The snapshot proof\n */\n function getSnapshotProof(uint32 attNonce, uint8 stateIndex) external view returns (bytes32[] memory snapProof);\n}\n\n// contracts/interfaces/IStateHub.sol\n\ninterface IStateHub {\n /**\n * @notice Check that a given state is valid: matches the historical state of Origin contract.\n * Note: any Agent including an invalid state in their snapshot will be slashed\n * upon providing the snapshot and agent signature for it to Origin contract.\n * @dev Will revert if any of these is true:\n * - State payload is not properly formatted.\n * @param statePayload Raw payload with state data\n * @return isValid Whether the provided state is valid\n */\n function isValidState(bytes memory statePayload) external view returns (bool isValid);\n\n /**\n * @notice Returns the amount of saved states so far.\n * @dev This includes the initial state of \"empty Origin Merkle Tree\".\n */\n function statesAmount() external view returns (uint256);\n\n /**\n * @notice Suggest the data (state after latest sent message) to sign for an Agent.\n * Note: signing the suggested state data will will never lead to slashing of the actor,\n * assuming they have confirmed that the block, which number is included in the data,\n * is not subject to reorganization (which is different for every observed chain).\n * @return statePayload Raw payload with the latest state data\n */\n function suggestLatestState() external view returns (bytes memory statePayload);\n\n /**\n * @notice Given the historical nonce, suggest the state data to sign for an Agent.\n * Note: signing the suggested state data will will never lead to slashing of the actor,\n * assuming they have confirmed that the block, which number is included in the data,\n * is not subject to reorganization (which is different for every observed chain).\n * @param nonce Historical nonce to form a state\n * @return statePayload Raw payload with historical state data\n */\n function suggestState(uint32 nonce) external view returns (bytes memory statePayload);\n}\n\n// contracts/interfaces/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/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// node_modules/@openzeppelin/contracts/utils/math/Math.sol\n\n// OpenZeppelin Contracts (last updated v4.9.0) (utils/math/Math.sol)\n\n/**\n * @dev Standard math utilities missing in the Solidity language.\n */\nlibrary Math {\n enum Rounding {\n Down, // Toward negative infinity\n Up, // Toward infinity\n Zero // Toward zero\n }\n\n /**\n * @dev Returns the largest of two numbers.\n */\n function max(uint256 a, uint256 b) internal pure returns (uint256) {\n return a \u003e b ? a : b;\n }\n\n /**\n * @dev Returns the smallest of two numbers.\n */\n function min(uint256 a, uint256 b) internal pure returns (uint256) {\n return a \u003c b ? a : b;\n }\n\n /**\n * @dev Returns the average of two numbers. The result is rounded towards\n * zero.\n */\n function average(uint256 a, uint256 b) internal pure returns (uint256) {\n // (a + b) / 2 can overflow.\n return (a \u0026 b) + (a ^ b) / 2;\n }\n\n /**\n * @dev Returns the ceiling of the division of two numbers.\n *\n * This differs from standard division with `/` in that it rounds up instead\n * of rounding down.\n */\n function ceilDiv(uint256 a, uint256 b) internal pure returns (uint256) {\n // (a + b - 1) / b can overflow on addition, so we distribute.\n return a == 0 ? 0 : (a - 1) / b + 1;\n }\n\n /**\n * @notice Calculates floor(x * y / denominator) with full precision. Throws if result overflows a uint256 or denominator == 0\n * @dev Original credit to Remco Bloemen under MIT license (https://xn--2-umb.com/21/muldiv)\n * with further edits by Uniswap Labs also under MIT license.\n */\n function mulDiv(uint256 x, uint256 y, uint256 denominator) internal pure returns (uint256 result) {\n unchecked {\n // 512-bit multiply [prod1 prod0] = x * y. Compute the product mod 2^256 and mod 2^256 - 1, then use\n // use the Chinese Remainder Theorem to reconstruct the 512 bit result. The result is stored in two 256\n // variables such that product = prod1 * 2^256 + prod0.\n uint256 prod0; // Least significant 256 bits of the product\n uint256 prod1; // Most significant 256 bits of the product\n assembly {\n let mm := mulmod(x, y, not(0))\n prod0 := mul(x, y)\n prod1 := sub(sub(mm, prod0), lt(mm, prod0))\n }\n\n // Handle non-overflow cases, 256 by 256 division.\n if (prod1 == 0) {\n // Solidity will revert if denominator == 0, unlike the div opcode on its own.\n // The surrounding unchecked block does not change this fact.\n // See https://docs.soliditylang.org/en/latest/control-structures.html#checked-or-unchecked-arithmetic.\n return prod0 / denominator;\n }\n\n // Make sure the result is less than 2^256. Also prevents denominator == 0.\n require(denominator \u003e prod1, \"Math: mulDiv overflow\");\n\n ///////////////////////////////////////////////\n // 512 by 256 division.\n ///////////////////////////////////////////////\n\n // Make division exact by subtracting the remainder from [prod1 prod0].\n uint256 remainder;\n assembly {\n // Compute remainder using mulmod.\n remainder := mulmod(x, y, denominator)\n\n // Subtract 256 bit number from 512 bit number.\n prod1 := sub(prod1, gt(remainder, prod0))\n prod0 := sub(prod0, remainder)\n }\n\n // Factor powers of two out of denominator and compute largest power of two divisor of denominator. Always \u003e= 1.\n // See https://cs.stackexchange.com/q/138556/92363.\n\n // Does not overflow because the denominator cannot be zero at this stage in the function.\n uint256 twos = denominator \u0026 (~denominator + 1);\n assembly {\n // Divide denominator by twos.\n denominator := div(denominator, twos)\n\n // Divide [prod1 prod0] by twos.\n prod0 := div(prod0, twos)\n\n // Flip twos such that it is 2^256 / twos. If twos is zero, then it becomes one.\n twos := add(div(sub(0, twos), twos), 1)\n }\n\n // Shift in bits from prod1 into prod0.\n prod0 |= prod1 * twos;\n\n // Invert denominator mod 2^256. Now that denominator is an odd number, it has an inverse modulo 2^256 such\n // that denominator * inv = 1 mod 2^256. Compute the inverse by starting with a seed that is correct for\n // four bits. That is, denominator * inv = 1 mod 2^4.\n uint256 inverse = (3 * denominator) ^ 2;\n\n // Use the Newton-Raphson iteration to improve the precision. Thanks to Hensel's lifting lemma, this also works\n // in modular arithmetic, doubling the correct bits in each step.\n inverse *= 2 - denominator * inverse; // inverse mod 2^8\n inverse *= 2 - denominator * inverse; // inverse mod 2^16\n inverse *= 2 - denominator * inverse; // inverse mod 2^32\n inverse *= 2 - denominator * inverse; // inverse mod 2^64\n inverse *= 2 - denominator * inverse; // inverse mod 2^128\n inverse *= 2 - denominator * inverse; // inverse mod 2^256\n\n // Because the division is now exact we can divide by multiplying with the modular inverse of denominator.\n // This will give us the correct result modulo 2^256. Since the preconditions guarantee that the outcome is\n // less than 2^256, this is the final result. We don't need to compute the high bits of the result and prod1\n // is no longer required.\n result = prod0 * inverse;\n return result;\n }\n }\n\n /**\n * @notice Calculates x * y / denominator with full precision, following the selected rounding direction.\n */\n function mulDiv(uint256 x, uint256 y, uint256 denominator, Rounding rounding) internal pure returns (uint256) {\n uint256 result = mulDiv(x, y, denominator);\n if (rounding == Rounding.Up \u0026\u0026 mulmod(x, y, denominator) \u003e 0) {\n result += 1;\n }\n return result;\n }\n\n /**\n * @dev Returns the square root of a number. If the number is not a perfect square, the value is rounded down.\n *\n * Inspired by Henry S. Warren, Jr.'s \"Hacker's Delight\" (Chapter 11).\n */\n function sqrt(uint256 a) internal pure returns (uint256) {\n if (a == 0) {\n return 0;\n }\n\n // For our first guess, we get the biggest power of 2 which is smaller than the square root of the target.\n //\n // We know that the \"msb\" (most significant bit) of our target number `a` is a power of 2 such that we have\n // `msb(a) \u003c= a \u003c 2*msb(a)`. This value can be written `msb(a)=2**k` with `k=log2(a)`.\n //\n // This can be rewritten `2**log2(a) \u003c= a \u003c 2**(log2(a) + 1)`\n // → `sqrt(2**k) \u003c= sqrt(a) \u003c sqrt(2**(k+1))`\n // → `2**(k/2) \u003c= sqrt(a) \u003c 2**((k+1)/2) \u003c= 2**(k/2 + 1)`\n //\n // Consequently, `2**(log2(a) / 2)` is a good first approximation of `sqrt(a)` with at least 1 correct bit.\n uint256 result = 1 \u003c\u003c (log2(a) \u003e\u003e 1);\n\n // At this point `result` is an estimation with one bit of precision. We know the true value is a uint128,\n // since it is the square root of a uint256. Newton's method converges quadratically (precision doubles at\n // every iteration). We thus need at most 7 iteration to turn our partial result with one bit of precision\n // into the expected uint128 result.\n unchecked {\n result = (result + a / result) \u003e\u003e 1;\n result = (result + a / result) \u003e\u003e 1;\n result = (result + a / result) \u003e\u003e 1;\n result = (result + a / result) \u003e\u003e 1;\n result = (result + a / result) \u003e\u003e 1;\n result = (result + a / result) \u003e\u003e 1;\n result = (result + a / result) \u003e\u003e 1;\n return min(result, a / result);\n }\n }\n\n /**\n * @notice Calculates sqrt(a), following the selected rounding direction.\n */\n function sqrt(uint256 a, Rounding rounding) internal pure returns (uint256) {\n unchecked {\n uint256 result = sqrt(a);\n return result + (rounding == Rounding.Up \u0026\u0026 result * result \u003c a ? 1 : 0);\n }\n }\n\n /**\n * @dev Return the log in base 2, rounded down, of a positive value.\n * Returns 0 if given 0.\n */\n function log2(uint256 value) internal pure returns (uint256) {\n uint256 result = 0;\n unchecked {\n if (value \u003e\u003e 128 \u003e 0) {\n value \u003e\u003e= 128;\n result += 128;\n }\n if (value \u003e\u003e 64 \u003e 0) {\n value \u003e\u003e= 64;\n result += 64;\n }\n if (value \u003e\u003e 32 \u003e 0) {\n value \u003e\u003e= 32;\n result += 32;\n }\n if (value \u003e\u003e 16 \u003e 0) {\n value \u003e\u003e= 16;\n result += 16;\n }\n if (value \u003e\u003e 8 \u003e 0) {\n value \u003e\u003e= 8;\n result += 8;\n }\n if (value \u003e\u003e 4 \u003e 0) {\n value \u003e\u003e= 4;\n result += 4;\n }\n if (value \u003e\u003e 2 \u003e 0) {\n value \u003e\u003e= 2;\n result += 2;\n }\n if (value \u003e\u003e 1 \u003e 0) {\n result += 1;\n }\n }\n return result;\n }\n\n /**\n * @dev Return the log in base 2, following the selected rounding direction, of a positive value.\n * Returns 0 if given 0.\n */\n function log2(uint256 value, Rounding rounding) internal pure returns (uint256) {\n unchecked {\n uint256 result = log2(value);\n return result + (rounding == Rounding.Up \u0026\u0026 1 \u003c\u003c result \u003c value ? 1 : 0);\n }\n }\n\n /**\n * @dev Return the log in base 10, rounded down, of a positive value.\n * Returns 0 if given 0.\n */\n function log10(uint256 value) internal pure returns (uint256) {\n uint256 result = 0;\n unchecked {\n if (value \u003e= 10 ** 64) {\n value /= 10 ** 64;\n result += 64;\n }\n if (value \u003e= 10 ** 32) {\n value /= 10 ** 32;\n result += 32;\n }\n if (value \u003e= 10 ** 16) {\n value /= 10 ** 16;\n result += 16;\n }\n if (value \u003e= 10 ** 8) {\n value /= 10 ** 8;\n result += 8;\n }\n if (value \u003e= 10 ** 4) {\n value /= 10 ** 4;\n result += 4;\n }\n if (value \u003e= 10 ** 2) {\n value /= 10 ** 2;\n result += 2;\n }\n if (value \u003e= 10 ** 1) {\n result += 1;\n }\n }\n return result;\n }\n\n /**\n * @dev Return the log in base 10, following the selected rounding direction, of a positive value.\n * Returns 0 if given 0.\n */\n function log10(uint256 value, Rounding rounding) internal pure returns (uint256) {\n unchecked {\n uint256 result = log10(value);\n return result + (rounding == Rounding.Up \u0026\u0026 10 ** result \u003c value ? 1 : 0);\n }\n }\n\n /**\n * @dev Return the log in base 256, rounded down, of a positive value.\n * Returns 0 if given 0.\n *\n * Adding one to the result gives the number of pairs of hex symbols needed to represent `value` as a hex string.\n */\n function log256(uint256 value) internal pure returns (uint256) {\n uint256 result = 0;\n unchecked {\n if (value \u003e\u003e 128 \u003e 0) {\n value \u003e\u003e= 128;\n result += 16;\n }\n if (value \u003e\u003e 64 \u003e 0) {\n value \u003e\u003e= 64;\n result += 8;\n }\n if (value \u003e\u003e 32 \u003e 0) {\n value \u003e\u003e= 32;\n result += 4;\n }\n if (value \u003e\u003e 16 \u003e 0) {\n value \u003e\u003e= 16;\n result += 2;\n }\n if (value \u003e\u003e 8 \u003e 0) {\n result += 1;\n }\n }\n return result;\n }\n\n /**\n * @dev Return the log in base 256, following the selected rounding direction, of a positive value.\n * Returns 0 if given 0.\n */\n function log256(uint256 value, Rounding rounding) internal pure returns (uint256) {\n unchecked {\n uint256 result = log256(value);\n return result + (rounding == Rounding.Up \u0026\u0026 1 \u003c\u003c (result \u003c\u003c 3) \u003c value ? 1 : 0);\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/utils/math/SignedMath.sol\n\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/math/SignedMath.sol)\n\n/**\n * @dev Standard signed math utilities missing in the Solidity language.\n */\nlibrary SignedMath {\n /**\n * @dev Returns the largest of two signed numbers.\n */\n function max(int256 a, int256 b) internal pure returns (int256) {\n return a \u003e b ? a : b;\n }\n\n /**\n * @dev Returns the smallest of two signed numbers.\n */\n function min(int256 a, int256 b) internal pure returns (int256) {\n return a \u003c b ? a : b;\n }\n\n /**\n * @dev Returns the average of two signed numbers without overflow.\n * The result is rounded towards zero.\n */\n function average(int256 a, int256 b) internal pure returns (int256) {\n // Formula from the book \"Hacker's Delight\"\n int256 x = (a \u0026 b) + ((a ^ b) \u003e\u003e 1);\n return x + (int256(uint256(x) \u003e\u003e 255) \u0026 (a ^ b));\n }\n\n /**\n * @dev Returns the absolute unsigned value of a signed value.\n */\n function abs(int256 n) internal pure returns (uint256) {\n unchecked {\n // must be unchecked in order to support `n = type(int256).min`\n return uint256(n \u003e= 0 ? n : -n);\n }\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// 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/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/InterfaceSummit.sol\n\ninterface InterfaceSummit {\n // ══════════════════════════════════════════ ACCEPT AGENT STATEMENTS ══════════════════════════════════════════════\n\n /**\n * @notice Accepts a receipt, which local `AgentManager` verified to have been signed by an active Notary.\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 * - Notary who signed the receipt is referenced as the \"Receipt Notary\".\n * - Notary who signed the attestation on destination chain is referenced as the \"Attestation Notary\".\n * \u003e Will revert if any of these is true:\n * \u003e - Called by anyone other than local `AgentManager`.\n * \u003e - Receipt body payload is not properly formatted.\n * \u003e - Receipt signer is in Dispute.\n * \u003e - Receipt's snapshot root is unknown.\n * @param rcptNotaryIndex Index of Receipt Notary in Agent Merkle Tree\n * @param attNotaryIndex Index of Attestation Notary in Agent Merkle Tree\n * @param sigIndex Index of stored Notary signature\n * @param attNonce Nonce of the attestation used for proving the executed message\n * @param paddedTips Padded encoded paid tips information\n * @param rcptPayload Raw payload with message execution receipt\n * @return wasAccepted Whether the receipt was accepted\n */\n function acceptReceipt(\n uint32 rcptNotaryIndex,\n uint32 attNotaryIndex,\n uint256 sigIndex,\n uint32 attNonce,\n uint256 paddedTips,\n bytes memory rcptPayload\n ) external returns (bool wasAccepted);\n\n /**\n * @notice Accepts a snapshot, which local `AgentManager` verified to have been signed by an active Guard.\n * \u003e Snapshot is a list of states for a set of Origin contracts residing on any of the chains.\n * All the states in the Guard-signed snapshot become available for Notary signing.\n * \u003e Will revert if any of these is true:\n * \u003e - Called by anyone other than local `AgentManager`.\n * \u003e - Snapshot payload is not properly formatted.\n * \u003e - Snapshot contains a state older then the Guard has previously submitted.\n * @param guardIndex Index of Guard in Agent Merkle Tree\n * @param sigIndex Index of stored Agent signature\n * @param snapPayload Raw payload with snapshot data\n */\n function acceptGuardSnapshot(uint32 guardIndex, uint256 sigIndex, bytes memory snapPayload) external;\n\n /**\n * @notice Accepts a snapshot, which local `AgentManager` verified to have been signed by an active Notary.\n * \u003e Snapshot is a list of states for a set of Origin contracts residing on any of the chains.\n * Snapshot Merkle Root is calculated and saved for valid snapshots, i.e.\n * snapshots which are only using states previously submitted by any of the Guards.\n * - Notary could use states singed by the same of different Guards 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 - Called by anyone other than local `AgentManager`.\n * \u003e - Snapshot payload is not properly formatted.\n * \u003e - Snapshot contains a state older then the Notary has previously submitted.\n * \u003e - Snapshot contains a state that no Guard has previously submitted.\n * @param notaryIndex Index of Notary in Agent Merkle Tree\n * @param sigIndex Index of stored Agent signature\n * @param agentRoot Current root of the Agent Merkle Tree\n * @param snapPayload Raw payload with snapshot data\n * @return attPayload Raw payload with data for attestation derived from Notary snapshot.\n */\n function acceptNotarySnapshot(uint32 notaryIndex, uint256 sigIndex, bytes32 agentRoot, bytes memory snapPayload)\n external\n returns (bytes memory attPayload);\n\n // ════════════════════════════════════════════════ TIPS LOGIC ═════════════════════════════════════════════════════\n\n /**\n * @notice Distributes tips using the first Receipt from the \"receipt quarantine queue\".\n * Possible scenarios:\n * - Receipt queue is empty =\u003e does nothing\n * - Receipt optimistic period is not over =\u003e does nothing\n * - Either of Notaries present in Receipt was slashed =\u003e receipt is deleted from the queue\n * - Either of Notaries present in Receipt in Dispute =\u003e receipt is moved to the end of queue\n * - None of the above =\u003e receipt tips are distributed\n * @dev Returned value makes it possible to do the following: `while (distributeTips()) {}`\n * @return queuePopped Whether the first element was popped from the queue\n */\n function distributeTips() external returns (bool queuePopped);\n\n /**\n * @notice Withdraws locked base message tips from requested domain Origin to the recipient.\n * This is done by a call to a local Origin contract, or by a manager message to the remote chain.\n * @dev This will revert, if the pending balance of origin tips (earned-claimed) is lower than requested.\n * @param origin Domain of chain to withdraw tips on\n * @param amount Amount of tips to withdraw\n */\n function withdrawTips(uint32 origin, uint256 amount) external;\n\n // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════\n\n /**\n * @notice Returns earned and claimed tips for the actor.\n * Note: Tips for address(0) belong to the Treasury.\n * @param actor Address of the actor\n * @param origin Domain where the tips were initially paid\n * @return earned Total amount of origin tips the actor has earned so far\n * @return claimed Total amount of origin tips the actor has claimed so far\n */\n function actorTips(address actor, uint32 origin) external view returns (uint128 earned, uint128 claimed);\n\n /**\n * @notice Returns the amount of receipts in the \"Receipt Quarantine Queue\".\n */\n function receiptQueueLength() external view returns (uint256);\n\n /**\n * @notice Returns the state with the highest known nonce\n * submitted by any of the currently active Guards.\n * @param origin Domain of origin chain\n * @return statePayload Raw payload with latest active Guard state for origin\n */\n function getLatestState(uint32 origin) external view returns (bytes memory statePayload);\n}\n\n// node_modules/@openzeppelin/contracts/utils/Strings.sol\n\n// OpenZeppelin Contracts (last updated v4.9.0) (utils/Strings.sol)\n\n/**\n * @dev String operations.\n */\nlibrary Strings {\n bytes16 private constant _SYMBOLS = \"0123456789abcdef\";\n uint8 private constant _ADDRESS_LENGTH = 20;\n\n /**\n * @dev Converts a `uint256` to its ASCII `string` decimal representation.\n */\n function toString(uint256 value) internal pure returns (string memory) {\n unchecked {\n uint256 length = Math.log10(value) + 1;\n string memory buffer = new string(length);\n uint256 ptr;\n /// @solidity memory-safe-assembly\n assembly {\n ptr := add(buffer, add(32, length))\n }\n while (true) {\n ptr--;\n /// @solidity memory-safe-assembly\n assembly {\n mstore8(ptr, byte(mod(value, 10), _SYMBOLS))\n }\n value /= 10;\n if (value == 0) break;\n }\n return buffer;\n }\n }\n\n /**\n * @dev Converts a `int256` to its ASCII `string` decimal representation.\n */\n function toString(int256 value) internal pure returns (string memory) {\n return string(abi.encodePacked(value \u003c 0 ? \"-\" : \"\", toString(SignedMath.abs(value))));\n }\n\n /**\n * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation.\n */\n function toHexString(uint256 value) internal pure returns (string memory) {\n unchecked {\n return toHexString(value, Math.log256(value) + 1);\n }\n }\n\n /**\n * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length.\n */\n function toHexString(uint256 value, uint256 length) internal pure returns (string memory) {\n bytes memory buffer = new bytes(2 * length + 2);\n buffer[0] = \"0\";\n buffer[1] = \"x\";\n for (uint256 i = 2 * length + 1; i \u003e 1; --i) {\n buffer[i] = _SYMBOLS[value \u0026 0xf];\n value \u003e\u003e= 4;\n }\n require(value == 0, \"Strings: hex length insufficient\");\n return string(buffer);\n }\n\n /**\n * @dev Converts an `address` with fixed length of 20 bytes to its not checksummed ASCII `string` hexadecimal representation.\n */\n function toHexString(address addr) internal pure returns (string memory) {\n return toHexString(uint256(uint160(addr)), _ADDRESS_LENGTH);\n }\n\n /**\n * @dev Returns true if the two strings are equal.\n */\n function equal(string memory a, string memory b) internal pure returns (bool) {\n return keccak256(bytes(a)) == keccak256(bytes(b));\n }\n}\n\n// node_modules/@openzeppelin/contracts-upgradeable/utils/ContextUpgradeable.sol\n\n// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)\n\n/**\n * @dev Provides information about the current execution context, including the\n * sender of the transaction and its data. While these are generally available\n * via msg.sender and msg.data, they should not be accessed in such a direct\n * manner, since when dealing with meta-transactions the account sending and\n * paying for execution may not be the actual sender (as far as an application\n * is concerned).\n *\n * This contract is only required for intermediate, library-like contracts.\n */\nabstract contract ContextUpgradeable is Initializable {\n function __Context_init() internal onlyInitializing {\n }\n\n function __Context_init_unchained() internal onlyInitializing {\n }\n function _msgSender() internal view virtual returns (address) {\n return msg.sender;\n }\n\n function _msgData() internal view virtual returns (bytes calldata) {\n return msg.data;\n }\n\n /**\n * @dev This empty reserved space is put in place to allow future versions to add new\n * variables without shifting down storage in the inheritance chain.\n * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\n */\n uint256[50] private __gap;\n}\n\n// contracts/libs/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/utils/cryptography/ECDSA.sol\n\n// OpenZeppelin Contracts (last updated v4.9.0) (utils/cryptography/ECDSA.sol)\n\n/**\n * @dev Elliptic Curve Digital Signature Algorithm (ECDSA) operations.\n *\n * These functions can be used to verify that a message was signed by the holder\n * of the private keys of a given address.\n */\nlibrary ECDSA {\n enum RecoverError {\n NoError,\n InvalidSignature,\n InvalidSignatureLength,\n InvalidSignatureS,\n InvalidSignatureV // Deprecated in v4.8\n }\n\n function _throwError(RecoverError error) private pure {\n if (error == RecoverError.NoError) {\n return; // no error: do nothing\n } else if (error == RecoverError.InvalidSignature) {\n revert(\"ECDSA: invalid signature\");\n } else if (error == RecoverError.InvalidSignatureLength) {\n revert(\"ECDSA: invalid signature length\");\n } else if (error == RecoverError.InvalidSignatureS) {\n revert(\"ECDSA: invalid signature 's' value\");\n }\n }\n\n /**\n * @dev Returns the address that signed a hashed message (`hash`) with\n * `signature` or error string. This address can then be used for verification purposes.\n *\n * The `ecrecover` EVM opcode allows for malleable (non-unique) signatures:\n * this function rejects them by requiring the `s` value to be in the lower\n * half order, and the `v` value to be either 27 or 28.\n *\n * IMPORTANT: `hash` _must_ be the result of a hash operation for the\n * verification to be secure: it is possible to craft signatures that\n * recover to arbitrary addresses for non-hashed data. A safe way to ensure\n * this is by receiving a hash of the original message (which may otherwise\n * be too long), and then calling {toEthSignedMessageHash} on it.\n *\n * Documentation for signature generation:\n * - with https://web3js.readthedocs.io/en/v1.3.4/web3-eth-accounts.html#sign[Web3.js]\n * - with https://docs.ethers.io/v5/api/signer/#Signer-signMessage[ethers]\n *\n * _Available since v4.3._\n */\n function tryRecover(bytes32 hash, bytes memory signature) internal pure returns (address, RecoverError) {\n if (signature.length == 65) {\n bytes32 r;\n bytes32 s;\n uint8 v;\n // ecrecover takes the signature parameters, and the only way to get them\n // currently is to use assembly.\n /// @solidity memory-safe-assembly\n assembly {\n r := mload(add(signature, 0x20))\n s := mload(add(signature, 0x40))\n v := byte(0, mload(add(signature, 0x60)))\n }\n return tryRecover(hash, v, r, s);\n } else {\n return (address(0), RecoverError.InvalidSignatureLength);\n }\n }\n\n /**\n * @dev Returns the address that signed a hashed message (`hash`) with\n * `signature`. This address can then be used for verification purposes.\n *\n * The `ecrecover` EVM opcode allows for malleable (non-unique) signatures:\n * this function rejects them by requiring the `s` value to be in the lower\n * half order, and the `v` value to be either 27 or 28.\n *\n * IMPORTANT: `hash` _must_ be the result of a hash operation for the\n * verification to be secure: it is possible to craft signatures that\n * recover to arbitrary addresses for non-hashed data. A safe way to ensure\n * this is by receiving a hash of the original message (which may otherwise\n * be too long), and then calling {toEthSignedMessageHash} on it.\n */\n function recover(bytes32 hash, bytes memory signature) internal pure returns (address) {\n (address recovered, RecoverError error) = tryRecover(hash, signature);\n _throwError(error);\n return recovered;\n }\n\n /**\n * @dev Overload of {ECDSA-tryRecover} that receives the `r` and `vs` short-signature fields separately.\n *\n * See https://eips.ethereum.org/EIPS/eip-2098[EIP-2098 short signatures]\n *\n * _Available since v4.3._\n */\n function tryRecover(bytes32 hash, bytes32 r, bytes32 vs) internal pure returns (address, RecoverError) {\n bytes32 s = vs \u0026 bytes32(0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff);\n uint8 v = uint8((uint256(vs) \u003e\u003e 255) + 27);\n return tryRecover(hash, v, r, s);\n }\n\n /**\n * @dev Overload of {ECDSA-recover} that receives the `r and `vs` short-signature fields separately.\n *\n * _Available since v4.2._\n */\n function recover(bytes32 hash, bytes32 r, bytes32 vs) internal pure returns (address) {\n (address recovered, RecoverError error) = tryRecover(hash, r, vs);\n _throwError(error);\n return recovered;\n }\n\n /**\n * @dev Overload of {ECDSA-tryRecover} that receives the `v`,\n * `r` and `s` signature fields separately.\n *\n * _Available since v4.3._\n */\n function tryRecover(bytes32 hash, uint8 v, bytes32 r, bytes32 s) internal pure returns (address, RecoverError) {\n // EIP-2 still allows signature malleability for ecrecover(). Remove this possibility and make the signature\n // unique. Appendix F in the Ethereum Yellow paper (https://ethereum.github.io/yellowpaper/paper.pdf), defines\n // the valid range for s in (301): 0 \u003c s \u003c secp256k1n ÷ 2 + 1, and for v in (302): v ∈ {27, 28}. Most\n // signatures from current libraries generate a unique signature with an s-value in the lower half order.\n //\n // If your library generates malleable signatures, such as s-values in the upper range, calculate a new s-value\n // with 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141 - s1 and flip v from 27 to 28 or\n // vice versa. If your library also generates signatures with 0/1 for v instead 27/28, add 27 to v to accept\n // these malleable signatures as well.\n if (uint256(s) \u003e 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0) {\n return (address(0), RecoverError.InvalidSignatureS);\n }\n\n // If the signature is valid (and not malleable), return the signer address\n address signer = ecrecover(hash, v, r, s);\n if (signer == address(0)) {\n return (address(0), RecoverError.InvalidSignature);\n }\n\n return (signer, RecoverError.NoError);\n }\n\n /**\n * @dev Overload of {ECDSA-recover} that receives the `v`,\n * `r` and `s` signature fields separately.\n */\n function recover(bytes32 hash, uint8 v, bytes32 r, bytes32 s) internal pure returns (address) {\n (address recovered, RecoverError error) = tryRecover(hash, v, r, s);\n _throwError(error);\n return recovered;\n }\n\n /**\n * @dev Returns an Ethereum Signed Message, created from a `hash`. This\n * produces hash corresponding to the one signed with the\n * https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`]\n * JSON-RPC method as part of EIP-191.\n *\n * See {recover}.\n */\n function toEthSignedMessageHash(bytes32 hash) internal pure returns (bytes32 message) {\n // 32 is the length in bytes of hash,\n // enforced by the type signature above\n /// @solidity memory-safe-assembly\n assembly {\n mstore(0x00, \"\\x19Ethereum Signed Message:\\n32\")\n mstore(0x1c, hash)\n message := keccak256(0x00, 0x3c)\n }\n }\n\n /**\n * @dev Returns an Ethereum Signed Message, created from `s`. This\n * produces hash corresponding to the one signed with the\n * https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`]\n * JSON-RPC method as part of EIP-191.\n *\n * See {recover}.\n */\n function toEthSignedMessageHash(bytes memory s) internal pure returns (bytes32) {\n return keccak256(abi.encodePacked(\"\\x19Ethereum Signed Message:\\n\", Strings.toString(s.length), s));\n }\n\n /**\n * @dev Returns an Ethereum Signed Typed Data, created from a\n * `domainSeparator` and a `structHash`. This produces hash corresponding\n * to the one signed with the\n * https://eips.ethereum.org/EIPS/eip-712[`eth_signTypedData`]\n * JSON-RPC method as part of EIP-712.\n *\n * See {recover}.\n */\n function toTypedDataHash(bytes32 domainSeparator, bytes32 structHash) internal pure returns (bytes32 data) {\n /// @solidity memory-safe-assembly\n assembly {\n let ptr := mload(0x40)\n mstore(ptr, \"\\x19\\x01\")\n mstore(add(ptr, 0x02), domainSeparator)\n mstore(add(ptr, 0x22), structHash)\n data := keccak256(ptr, 0x42)\n }\n }\n\n /**\n * @dev Returns an Ethereum Signed Data with intended validator, created from a\n * `validator` and `data` according to the version 0 of EIP-191.\n *\n * See {recover}.\n */\n function toDataWithIntendedValidatorHash(address validator, bytes memory data) internal pure returns (bytes32) {\n return keccak256(abi.encodePacked(\"\\x19\\x00\", validator, data));\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/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/inbox/StatementInbox.sol\n\n// ══════════════════════════════ LIBRARY IMPORTS ══════════════════════════════\n\n// ═════════════════════════════ INTERNAL IMPORTS ══════════════════════════════\n\n// ═════════════════════════════ EXTERNAL IMPORTS ══════════════════════════════\n\n/// @notice `StatementInbox` is the entry point for all agent-signed statements. It verifies the\n/// agent signatures, and passes the unsigned statements to the contract to consume it via `acceptX` functions. Is is\n/// also used to verify the agent-signed statements and initiate the agent slashing, should the statement be invalid.\n/// `StatementInbox` is responsible for the following:\n/// - Accepting State and Receipt Reports to initiate a dispute between Guard and Notary.\n/// - Storing all the Guard Reports with the Guard signature leading to a dispute.\n/// - Verifying State/State Reports referencing the local chain and slashing the signer if statement is invalid.\n/// - Verifying Receipt/Receipt Reports referencing the local chain and slashing the signer if statement is invalid.\nabstract contract StatementInbox is MessagingBase, StatementInboxEvents, IStatementInbox {\n using AttestationLib for bytes;\n using ReceiptLib for bytes;\n using StateLib for bytes;\n using SnapshotLib for bytes;\n\n struct StoredReport {\n uint256 sigIndex;\n bytes statementPayload;\n }\n\n // ══════════════════════════════════════════════════ STORAGE ══════════════════════════════════════════════════════\n\n address public agentManager;\n address public origin;\n address public destination;\n\n // TODO: optimize this\n bytes[] internal _storedSignatures;\n StoredReport[] internal _storedReports;\n\n /// @dev gap for upgrade safety\n uint256[45] private __GAP; // solhint-disable-line var-name-mixedcase\n\n // ════════════════════════════════════════════════ INITIALIZER ════════════════════════════════════════════════════\n\n /// @dev Initializes the contract:\n /// - Sets up `msg.sender` as the owner of the contract.\n /// - Sets up `agentManager`, `origin`, and `destination`.\n // solhint-disable-next-line func-name-mixedcase\n function __StatementInbox_init(address agentManager_, address origin_, address destination_)\n internal\n onlyInitializing\n {\n agentManager = agentManager_;\n origin = origin_;\n destination = destination_;\n __Ownable2Step_init();\n }\n\n // ══════════════════════════════════════════ SUBMIT AGENT STATEMENTS ══════════════════════════════════════════════\n\n /// @inheritdoc IStatementInbox\n // solhint-disable-next-line ordering\n function submitStateReportWithSnapshot(\n uint8 stateIndex,\n bytes memory srSignature,\n bytes memory snapPayload,\n bytes memory snapSignature\n ) external returns (bool wasAccepted) {\n // This will revert if payload is not a snapshot\n Snapshot snapshot = snapPayload.castToSnapshot();\n // This will revert if the snapshot signer is not a known Notary\n (AgentStatus memory notaryStatus,) =\n _verifySnapshot({snapshot: snapshot, snapSignature: snapSignature, verifyNotary: true});\n // Notary needs to be Active/Unstaking\n notaryStatus.verifyActiveUnstaking();\n // Check if Notary is active on this chain\n _verifyNotaryDomain(notaryStatus.domain);\n // This will revert if state index is out of range\n State state = snapshot.state(stateIndex);\n // This will revert if the report signer is not an known Guard\n (AgentStatus memory guardStatus,) = _verifyStateReport(state, srSignature);\n // Check that Guard is active\n guardStatus.verifyActive();\n _saveReport(state.unwrap().clone(), srSignature);\n // This will revert if either actor is already in dispute\n IAgentManager(agentManager).openDispute(guardStatus.index, notaryStatus.index);\n return true;\n }\n\n /// @inheritdoc IStatementInbox\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 // This will revert if payload is not a snapshot\n Snapshot snapshot = snapPayload.castToSnapshot();\n // This will revert if state index is out of range\n State state = snapshot.state(stateIndex);\n // This will revert if the report signer is not an known Guard\n (AgentStatus memory guardStatus,) = _verifyStateReport(state, srSignature);\n // Check that Guard is active\n guardStatus.verifyActive();\n // This will revert if payload is not an attestation\n Attestation att = attPayload.castToAttestation();\n // This will revert if signer is not an known Notary\n (AgentStatus memory notaryStatus,) = _verifyAttestation(att, attSignature);\n // Notary needs to be Active/Unstaking\n notaryStatus.verifyActiveUnstaking();\n // Check if Notary is active on this chain\n _verifyNotaryDomain(notaryStatus.domain);\n if (snapshot.calculateRoot() != att.snapRoot()) revert IncorrectSnapshotRoot();\n _saveReport(state.unwrap().clone(), srSignature);\n // This will revert if either actor is already in dispute\n IAgentManager(agentManager).openDispute(guardStatus.index, notaryStatus.index);\n return true;\n }\n\n /// @inheritdoc IStatementInbox\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 // This will revert if payload is not a state\n State state = statePayload.castToState();\n // This will revert if the report signer is not an known Guard\n (AgentStatus memory guardStatus,) = _verifyStateReport(state, srSignature);\n // Check that Guard is active\n guardStatus.verifyActive();\n // This will revert if payload is not an attestation\n Attestation att = attPayload.castToAttestation();\n // This will revert if signer is not a known Notary\n (AgentStatus memory notaryStatus,) = _verifyAttestation(att, attSignature);\n // Notary needs to be Active/Unstaking\n notaryStatus.verifyActiveUnstaking();\n // Check if Notary is active on this chain\n _verifyNotaryDomain(notaryStatus.domain);\n // This will revert if any of these is true:\n // - Attestation root is not equal to Merkle Root derived from State and Snapshot Proof.\n // - Snapshot Proof's first element does not match the State metadata.\n // - Snapshot Proof length exceeds Snapshot tree Height.\n // - State index is out of range.\n _verifySnapshotMerkle(att, stateIndex, state, snapProof);\n _saveReport(statePayload, srSignature);\n // This will revert if either actor is already in dispute\n IAgentManager(agentManager).openDispute(guardStatus.index, notaryStatus.index);\n return true;\n }\n\n // ══════════════════════════════════════════ VERIFY AGENT STATEMENTS ══════════════════════════════════════════════\n\n /// @inheritdoc IStatementInbox\n function verifyReceipt(bytes memory rcptPayload, bytes memory rcptSignature)\n external\n returns (bool isValidReceipt)\n {\n // This will revert if payload is not a receipt\n Receipt rcpt = rcptPayload.castToReceipt();\n // This will revert if the attestation signer is not a known Notary\n (AgentStatus memory status, address notary) = _verifyReceipt(rcpt, rcptSignature);\n // Notary needs to be Active/Unstaking\n status.verifyActiveUnstaking();\n isValidReceipt = IExecutionHub(destination).isValidReceipt(rcptPayload);\n if (!isValidReceipt) {\n emit InvalidReceipt(rcptPayload, rcptSignature);\n IAgentManager(agentManager).slashAgent(status.domain, notary, msg.sender);\n }\n }\n\n /// @inheritdoc IStatementInbox\n function verifyReceiptReport(bytes memory rcptPayload, bytes memory rrSignature)\n external\n returns (bool isValidReport)\n {\n // This will revert if payload is not a receipt\n Receipt rcpt = rcptPayload.castToReceipt();\n // This will revert if the report signer is not a known Guard\n (AgentStatus memory status, address guard) = _verifyReceiptReport(rcpt, rrSignature);\n // Guard needs to be Active/Unstaking\n status.verifyActiveUnstaking();\n // Report is valid IF AND ONLY IF the reported receipt in invalid\n isValidReport = !IExecutionHub(destination).isValidReceipt(rcptPayload);\n if (!isValidReport) {\n emit InvalidReceiptReport(rcptPayload, rrSignature);\n IAgentManager(agentManager).slashAgent(status.domain, guard, msg.sender);\n }\n }\n\n /// @inheritdoc IStatementInbox\n function verifyStateWithAttestation(\n uint8 stateIndex,\n bytes memory snapPayload,\n bytes memory attPayload,\n bytes memory attSignature\n ) external returns (bool isValidState) {\n // This will revert if payload is not an attestation\n Attestation att = attPayload.castToAttestation();\n // This will revert if the attestation signer is not a known Notary\n (AgentStatus memory status, address notary) = _verifyAttestation(att, attSignature);\n // Notary needs to be Active/Unstaking\n status.verifyActiveUnstaking();\n // This will revert if payload is not a snapshot\n Snapshot snapshot = snapPayload.castToSnapshot();\n if (snapshot.calculateRoot() != att.snapRoot()) revert IncorrectSnapshotRoot();\n // This will revert if state does not refer to this chain\n bytes memory statePayload = snapshot.state(stateIndex).unwrap().clone();\n isValidState = IStateHub(origin).isValidState(statePayload);\n if (!isValidState) {\n emit InvalidStateWithAttestation(stateIndex, statePayload, attPayload, attSignature);\n IAgentManager(agentManager).slashAgent(status.domain, notary, msg.sender);\n }\n }\n\n /// @inheritdoc IStatementInbox\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 // This will revert if payload is not an attestation\n Attestation att = attPayload.castToAttestation();\n // This will revert if the attestation signer is not a known Notary\n (AgentStatus memory status, address notary) = _verifyAttestation(att, attSignature);\n // Notary needs to be Active/Unstaking\n status.verifyActiveUnstaking();\n // This will revert if payload is not a state\n State state = statePayload.castToState();\n // This will revert if any of these is true:\n // - Attestation root is not equal to Merkle Root derived from State and Snapshot Proof.\n // - Snapshot Proof's first element does not match the State metadata.\n // - Snapshot Proof length exceeds Snapshot tree Height.\n // - State index is out of range.\n _verifySnapshotMerkle(att, stateIndex, state, snapProof);\n // This will revert if state does not refer to this chain\n isValidState = IStateHub(origin).isValidState(statePayload);\n if (!isValidState) {\n emit InvalidStateWithAttestation(stateIndex, statePayload, attPayload, attSignature);\n IAgentManager(agentManager).slashAgent(status.domain, notary, msg.sender);\n }\n }\n\n /// @inheritdoc IStatementInbox\n function verifyStateWithSnapshot(uint8 stateIndex, bytes memory snapPayload, bytes memory snapSignature)\n external\n returns (bool isValidState)\n {\n // This will revert if payload is not a snapshot\n Snapshot snapshot = snapPayload.castToSnapshot();\n // This will revert if the snapshot signer is not a known Guard/Notary\n (AgentStatus memory status, address agent) =\n _verifySnapshot({snapshot: snapshot, snapSignature: snapSignature, verifyNotary: false});\n // Agent needs to be Active/Unstaking\n status.verifyActiveUnstaking();\n // This will revert if state does not refer to this chain\n isValidState = IStateHub(origin).isValidState(snapshot.state(stateIndex).unwrap().clone());\n if (!isValidState) {\n emit InvalidStateWithSnapshot(stateIndex, snapPayload, snapSignature);\n IAgentManager(agentManager).slashAgent(status.domain, agent, msg.sender);\n }\n }\n\n /// @inheritdoc IStatementInbox\n function verifyStateReport(bytes memory statePayload, bytes memory srSignature)\n external\n returns (bool isValidReport)\n {\n // This will revert if payload is not a state\n State state = statePayload.castToState();\n // This will revert if the report signer is not a known Guard\n (AgentStatus memory status, address guard) = _verifyStateReport(state, srSignature);\n // Guard needs to be Active/Unstaking\n status.verifyActiveUnstaking();\n // Report is valid IF AND ONLY IF the reported state in invalid\n // This will revert if the reported state does not refer to this chain\n isValidReport = !IStateHub(origin).isValidState(statePayload);\n if (!isValidReport) {\n emit InvalidStateReport(statePayload, srSignature);\n IAgentManager(agentManager).slashAgent(status.domain, guard, msg.sender);\n }\n }\n\n // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════\n\n /// @inheritdoc IStatementInbox\n function getReportsAmount() external view returns (uint256) {\n return _storedReports.length;\n }\n\n /// @inheritdoc IStatementInbox\n function getGuardReport(uint256 index)\n external\n view\n returns (bytes memory statementPayload, bytes memory reportSignature)\n {\n if (index \u003e= _storedReports.length) revert IndexOutOfRange();\n StoredReport memory storedReport = _storedReports[index];\n statementPayload = storedReport.statementPayload;\n reportSignature = _storedSignatures[storedReport.sigIndex];\n }\n\n /// @inheritdoc IStatementInbox\n function getStoredSignature(uint256 index) external view returns (bytes memory) {\n return _storedSignatures[index];\n }\n\n // ══════════════════════════════════════════════ INTERNAL LOGIC ═══════════════════════════════════════════════════\n\n /// @dev Saves the statement reported by Guard as invalid and the Guard Report signature.\n function _saveReport(bytes memory statementPayload, bytes memory reportSignature) internal {\n uint256 sigIndex = _saveSignature(reportSignature);\n _storedReports.push(StoredReport(sigIndex, statementPayload));\n }\n\n /// @dev Saves the signature and returns its index.\n function _saveSignature(bytes memory signature) internal returns (uint256 sigIndex) {\n sigIndex = _storedSignatures.length;\n _storedSignatures.push(signature);\n }\n\n // ═══════════════════════════════════════════════ AGENT CHECKS ════════════════════════════════════════════════════\n\n /**\n * @dev Recovers a signer from a hashed message, and a EIP-191 signature for it.\n * Will revert, if the signer is not a known agent.\n * @dev Agent flag could be any of these: Active/Unstaking/Resting/Fraudulent/Slashed\n * Further checks need to be performed in a caller function.\n * @param hashedStatement Hash of the statement that was signed by an Agent\n * @param signature Agent signature for the hashed statement\n * @return status Struct representing agent status:\n * - flag Unknown/Active/Unstaking/Resting/Fraudulent/Slashed\n * - domain Domain where agent is/was active\n * - index Index of agent in the Agent Merkle Tree\n * @return agent Agent that signed the statement\n */\n function _recoverAgent(bytes32 hashedStatement, bytes memory signature)\n internal\n view\n returns (AgentStatus memory status, address agent)\n {\n bytes32 ethSignedMsg = ECDSA.toEthSignedMessageHash(hashedStatement);\n agent = ECDSA.recover(ethSignedMsg, signature);\n status = IAgentManager(agentManager).agentStatus(agent);\n // Discard signature of unknown agents.\n // Further flag checks are supposed to be performed in a caller function.\n status.verifyKnown();\n }\n\n /// @dev Verifies that Notary signature is active on local domain.\n function _verifyNotaryDomain(uint32 notaryDomain) internal view {\n // Notary needs to be from the local domain (if contract is not deployed on Synapse Chain).\n // Or Notary could be from any domain (if contract is deployed on Synapse Chain).\n if (notaryDomain != localDomain \u0026\u0026 localDomain != synapseDomain) revert IncorrectAgentDomain();\n }\n\n // ════════════════════════════════════════ ATTESTATION RELATED CHECKS ═════════════════════════════════════════════\n\n /**\n * @dev Internal function to verify the signed attestation payload.\n * Reverts if any of these is true:\n * - Attestation signer is not a known Notary.\n * @param att Typed memory view over attestation payload\n * @param attSignature Notary signature for the attestation\n * @return status Struct representing agent status, see {_recoverAgent}\n * @return notary Notary that signed the snapshot\n */\n function _verifyAttestation(Attestation att, bytes memory attSignature)\n internal\n view\n returns (AgentStatus memory status, address notary)\n {\n // This will revert if signer is not a known agent\n (status, notary) = _recoverAgent(att.hashValid(), attSignature);\n // Attestation signer needs to be a Notary, not a Guard\n if (status.domain == 0) revert AgentNotNotary();\n }\n\n /**\n * @dev Internal function to verify the signed attestation report payload.\n * Reverts if any of these is true:\n * - Report signer is not a known Guard.\n * @param att Typed memory view over attestation payload that Guard reports as invalid\n * @param arSignature Guard signature for the \"invalid attestation\" report\n * @return status Struct representing guard status, see {_recoverAgent}\n * @return guard Guard that signed the report\n */\n function _verifyAttestationReport(Attestation att, bytes memory arSignature)\n internal\n view\n returns (AgentStatus memory status, address guard)\n {\n // This will revert if signer is not a known agent\n (status, guard) = _recoverAgent(att.hashInvalid(), arSignature);\n // Report signer needs to be a Guard, not a Notary\n if (status.domain != 0) revert AgentNotGuard();\n }\n\n // ══════════════════════════════════════════ RECEIPT RELATED CHECKS ═══════════════════════════════════════════════\n\n /**\n * @dev Internal function to verify the signed receipt payload.\n * Reverts if any of these is true:\n * - Receipt signer is not a known Notary.\n * @param rcpt Typed memory view over receipt payload\n * @param rcptSignature Notary signature for the receipt\n * @return status Struct representing agent status, see {_recoverAgent}\n * @return notary Notary that signed the snapshot\n */\n function _verifyReceipt(Receipt rcpt, bytes memory rcptSignature)\n internal\n view\n returns (AgentStatus memory status, address notary)\n {\n // This will revert if signer is not a known agent\n (status, notary) = _recoverAgent(rcpt.hashValid(), rcptSignature);\n // Receipt signer needs to be a Notary, not a Guard\n if (status.domain == 0) revert AgentNotNotary();\n }\n\n /**\n * @dev Internal function to verify the signed receipt report payload.\n * Reverts if any of these is true:\n * - Report signer is not a known Guard.\n * @param rcpt Typed memory view over receipt payload that Guard reports as invalid\n * @param rrSignature Guard signature for the \"invalid receipt\" report\n * @return status Struct representing guard status, see {_recoverAgent}\n * @return guard Guard that signed the report\n */\n function _verifyReceiptReport(Receipt rcpt, bytes memory rrSignature)\n internal\n view\n returns (AgentStatus memory status, address guard)\n {\n // This will revert if signer is not a known agent\n (status, guard) = _recoverAgent(rcpt.hashInvalid(), rrSignature);\n // Report signer needs to be a Guard, not a Notary\n if (status.domain != 0) revert AgentNotGuard();\n }\n\n // ═══════════════════════════════════════ STATE/SNAPSHOT RELATED CHECKS ═══════════════════════════════════════════\n\n /**\n * @dev Internal function to verify the signed snapshot report payload.\n * Reverts if any of these is true:\n * - Report signer is not a known Guard.\n * @param state Typed memory view over state payload that Guard reports as invalid\n * @param srSignature Guard signature for the report\n * @return status Struct representing guard status, see {_recoverAgent}\n * @return guard Guard that signed the report\n */\n function _verifyStateReport(State state, bytes memory srSignature)\n internal\n view\n returns (AgentStatus memory status, address guard)\n {\n // This will revert if signer is not a known agent\n (status, guard) = _recoverAgent(state.hashInvalid(), srSignature);\n // Report signer needs to be a Guard, not a Notary\n if (status.domain != 0) revert AgentNotGuard();\n }\n\n /**\n * @dev Internal function to verify the signed snapshot payload.\n * Reverts if any of these is true:\n * - Snapshot signer is not a known Agent.\n * - Snapshot signer is not a Notary (if verifyNotary is true).\n * @param snapshot Typed memory view over snapshot payload\n * @param snapSignature Agent signature for the snapshot\n * @param verifyNotary If true, snapshot signer needs to be a Notary, not a Guard\n * @return status Struct representing agent status, see {_recoverAgent}\n * @return agent Agent that signed the snapshot\n */\n function _verifySnapshot(Snapshot snapshot, bytes memory snapSignature, bool verifyNotary)\n internal\n view\n returns (AgentStatus memory status, address agent)\n {\n // This will revert if signer is not a known agent\n (status, agent) = _recoverAgent(snapshot.hashValid(), snapSignature);\n // If requested, snapshot signer needs to be a Notary, not a Guard\n if (verifyNotary \u0026\u0026 status.domain == 0) revert AgentNotNotary();\n }\n\n // ═══════════════════════════════════════════ MERKLE RELATED CHECKS ═══════════════════════════════════════════════\n\n /**\n * @dev Internal function to verify that snapshot roots match.\n * Reverts if any of these is true:\n * - Attestation root is not equal to Merkle Root derived from State and Snapshot Proof.\n * - Snapshot Proof's first element does not match the State metadata.\n * - Snapshot Proof length exceeds Snapshot tree Height.\n * - State index is out of range.\n * @param att Typed memory view over Attestation\n * @param stateIndex Index of state in the snapshot\n * @param state Typed memory view over the provided state payload\n * @param snapProof Raw payload with snapshot data\n */\n function _verifySnapshotMerkle(Attestation att, uint8 stateIndex, State state, bytes32[] memory snapProof)\n internal\n pure\n {\n // Snapshot proof first element should match State metadata (aka \"right sub-leaf\")\n (, bytes32 rightSubLeaf) = state.subLeafs();\n if (snapProof[0] != rightSubLeaf) revert IncorrectSnapshotProof();\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(state.root(), state.origin(), snapProof, stateIndex);\n // Snapshot root should match the attestation root\n if (att.snapRoot() != snapshotRoot) revert IncorrectSnapshotRoot();\n }\n}\n\n// contracts/inbox/Inbox.sol\n\n// ══════════════════════════════ LIBRARY IMPORTS ══════════════════════════════\n\n// ═════════════════════════════ INTERNAL IMPORTS ══════════════════════════════\n\n/// @notice `Inbox` is the child of `StatementInbox` contract, that is used on Synapse Chain.\n/// In addition to the functionality of `StatementInbox`, it also:\n/// - Accepts Guard and Notary Snapshots and passes them to `Summit` contract.\n/// - Accepts Notary-signed Receipts and passes them to `Summit` contract.\n/// - Accepts Receipt Reports to initiate a dispute between Guard and Notary.\n/// - Verifies Attestations and Attestation Reports, and slashes the signer if they are invalid.\ncontract Inbox is StatementInbox, InboxEvents, InterfaceInbox {\n using AttestationLib for bytes;\n using ReceiptLib for bytes;\n using SnapshotLib for bytes;\n\n // Struct to get around stack too deep error. TODO: revisit this\n struct ReceiptInfo {\n AgentStatus rcptNotaryStatus;\n address notary;\n uint32 attNonce;\n AgentStatus attNotaryStatus;\n }\n\n // ══════════════════════════════════════════════════ STORAGE ══════════════════════════════════════════════════════\n\n // The address of the Summit contract.\n address public summit;\n\n // ═════════════════════════════════════════ CONSTRUCTOR \u0026 INITIALIZER ═════════════════════════════════════════════\n\n constructor(uint32 synapseDomain_) MessagingBase(\"0.0.3\", synapseDomain_) {\n if (localDomain != synapseDomain) revert MustBeSynapseDomain();\n }\n\n /// @notice Initializes `Inbox` contract:\n /// - Sets `msg.sender` as the owner of the contract\n /// - Sets `agentManager`, `origin`, `destination` and `summit` addresses\n function initialize(address agentManager_, address origin_, address destination_, address summit_)\n external\n initializer\n {\n __StatementInbox_init(agentManager_, origin_, destination_);\n summit = summit_;\n }\n\n // ══════════════════════════════════════════ SUBMIT AGENT STATEMENTS ══════════════════════════════════════════════\n\n /// @inheritdoc InterfaceInbox\n function submitSnapshot(bytes memory snapPayload, bytes memory snapSignature)\n external\n returns (bytes memory attPayload, bytes32 agentRoot_, uint256[] memory snapGas)\n {\n // This will revert if payload is not a snapshot\n Snapshot snapshot = snapPayload.castToSnapshot();\n // This will revert if the signer is not a known Guard/Notary\n (AgentStatus memory status, address agent) =\n _verifySnapshot({snapshot: snapshot, snapSignature: snapSignature, verifyNotary: false});\n // Check that Agent is active\n status.verifyActive();\n // Store Agent signature for the Snapshot\n uint256 sigIndex = _saveSignature(snapSignature);\n if (status.domain == 0) {\n // Guard that is in Dispute could still submit new snapshots, so we don't check that\n InterfaceSummit(summit).acceptGuardSnapshot({\n guardIndex: status.index,\n sigIndex: sigIndex,\n snapPayload: snapPayload\n });\n } else {\n // Get current agentRoot from AgentManager\n agentRoot_ = IAgentManager(agentManager).agentRoot();\n // This will revert if Notary is in Dispute\n attPayload = InterfaceSummit(summit).acceptNotarySnapshot({\n notaryIndex: status.index,\n sigIndex: sigIndex,\n agentRoot: agentRoot_,\n snapPayload: snapPayload\n });\n ChainGas[] memory snapGas_ = snapshot.snapGas();\n // Pass created attestation to Destination to enable executing messages coming to Synapse Chain\n InterfaceDestination(destination).acceptAttestation(\n status.index, type(uint256).max, attPayload, agentRoot_, snapGas_\n );\n // Use assembly to cast ChainGas[] to uint256[] without copying. Highest bits are left zeroed.\n // solhint-disable-next-line no-inline-assembly\n assembly {\n snapGas := snapGas_\n }\n }\n emit SnapshotAccepted(status.domain, agent, snapPayload, snapSignature);\n }\n\n /// @inheritdoc InterfaceInbox\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 // Struct to get around stack too deep error.\n ReceiptInfo memory info;\n // This will revert if payload is not a receipt\n Receipt rcpt = rcptPayload.castToReceipt();\n // This will revert if the receipt signer is not a known Notary\n (info.rcptNotaryStatus, info.notary) = _verifyReceipt(rcpt, rcptSignature);\n // Receipt Notary needs to be Active\n info.rcptNotaryStatus.verifyActive();\n info.attNonce = IExecutionHub(destination).getAttestationNonce(rcpt.snapshotRoot());\n if (info.attNonce == 0) revert IncorrectSnapshotRoot();\n // Attestation Notary domain needs to match the destination domain\n info.attNotaryStatus = IAgentManager(agentManager).agentStatus(rcpt.attNotary());\n if (info.attNotaryStatus.domain != rcpt.destination()) revert IncorrectAgentDomain();\n // Check that the correct tip values for the message were provided\n _verifyReceiptTips(rcpt.messageHash(), paddedTips, headerHash, bodyHash);\n // Store Notary signature for the Receipt\n uint256 sigIndex = _saveSignature(rcptSignature);\n // This will revert if Receipt Notary is in Dispute\n wasAccepted = InterfaceSummit(summit).acceptReceipt({\n rcptNotaryIndex: info.rcptNotaryStatus.index,\n attNotaryIndex: info.attNotaryStatus.index,\n sigIndex: sigIndex,\n attNonce: info.attNonce,\n paddedTips: paddedTips,\n rcptPayload: rcptPayload\n });\n if (wasAccepted) {\n emit ReceiptAccepted(info.rcptNotaryStatus.domain, info.notary, rcptPayload, rcptSignature);\n }\n }\n\n /// @inheritdoc InterfaceInbox\n function submitReceiptReport(bytes memory rcptPayload, bytes memory rcptSignature, bytes memory rrSignature)\n external\n returns (bool wasAccepted)\n {\n // This will revert if payload is not a receipt\n Receipt rcpt = rcptPayload.castToReceipt();\n // This will revert if the receipt signer is not a known Guard\n (AgentStatus memory guardStatus,) = _verifyReceiptReport(rcpt, rrSignature);\n // Guard needs to be Active\n guardStatus.verifyActive();\n // This will revert if report signer is not a known Notary\n (AgentStatus memory notaryStatus,) = _verifyReceipt(rcpt, rcptSignature);\n // Notary needs to be Active/Unstaking\n notaryStatus.verifyActiveUnstaking();\n _saveReport(rcptPayload, rrSignature);\n // This will revert if either actor is already in dispute\n IAgentManager(agentManager).openDispute(guardStatus.index, notaryStatus.index);\n return true;\n }\n\n /// @inheritdoc InterfaceInbox\n function passReceipt(uint32 attNotaryIndex, uint32 attNonce, uint256 paddedTips, bytes memory rcptPayload)\n external\n returns (bool wasAccepted)\n {\n // Only Destination can pass receipts\n if (msg.sender != destination) revert CallerNotDestination();\n return InterfaceSummit(summit).acceptReceipt({\n rcptNotaryIndex: attNotaryIndex,\n attNotaryIndex: attNotaryIndex,\n sigIndex: type(uint256).max,\n attNonce: attNonce,\n paddedTips: paddedTips,\n rcptPayload: rcptPayload\n });\n }\n\n // ══════════════════════════════════════════ VERIFY AGENT STATEMENTS ══════════════════════════════════════════════\n\n /// @inheritdoc InterfaceInbox\n function verifyAttestation(bytes memory attPayload, bytes memory attSignature)\n external\n returns (bool isValidAttestation)\n {\n // This will revert if payload is not an attestation\n Attestation att = attPayload.castToAttestation();\n // This will revert if the attestation signer is not a known Notary\n (AgentStatus memory status, address notary) = _verifyAttestation(att, attSignature);\n // Notary needs to be Active/Unstaking\n status.verifyActiveUnstaking();\n isValidAttestation = ISnapshotHub(summit).isValidAttestation(attPayload);\n if (!isValidAttestation) {\n emit InvalidAttestation(attPayload, attSignature);\n IAgentManager(agentManager).slashAgent(status.domain, notary, msg.sender);\n }\n }\n\n /// @inheritdoc InterfaceInbox\n function verifyAttestationReport(bytes memory attPayload, bytes memory arSignature)\n external\n returns (bool isValidReport)\n {\n // This will revert if payload is not an attestation\n Attestation att = attPayload.castToAttestation();\n // This will revert if the report signer is not a known Guard\n (AgentStatus memory status, address guard) = _verifyAttestationReport(att, arSignature);\n // Guard needs to be Active/Unstaking\n status.verifyActiveUnstaking();\n // Report is valid IF AND ONLY IF the reported attestation in invalid\n isValidReport = !ISnapshotHub(summit).isValidAttestation(attPayload);\n if (!isValidReport) {\n emit InvalidAttestationReport(attPayload, arSignature);\n IAgentManager(agentManager).slashAgent(status.domain, guard, msg.sender);\n }\n }\n\n // ══════════════════════════════════════════════ INTERNAL VIEWS ═══════════════════════════════════════════════════\n\n /// @dev Verifies that tips proof matches the message hash.\n function _verifyReceiptTips(bytes32 msgHash, uint256 paddedTips, bytes32 headerHash, bytes32 bodyHash)\n internal\n pure\n {\n Tips tips = TipsLib.wrapPadded(paddedTips);\n // full message leaf is (header, baseMessage), while base message leaf is (tips, remainingBody).\n if (MerkleMath.getParent(headerHash, MerkleMath.getParent(tips.leaf(), bodyHash)) != msgHash) {\n revert IncorrectTipsProof();\n }\n }\n}\n","language":"Solidity","languageVersion":"0.8.17","compilerVersion":"0.8.17","compilerOptions":"--combined-json bin,bin-runtime,srcmap,srcmap-runtime,abi,userdoc,devdoc,metadata,hashes --optimize --optimize-runs 10000 --allow-paths ., ./, ../","srcMap":"96645:9180:0:-:0;;;;;;;;;;;;;;;-1:-1:-1;;;96645:9180:0;;;;;;;;;;;;;;;;;","srcMapRuntime":"96645: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/Inbox.sol\":\"AddressUpgradeable\"},\"evmVersion\":\"london\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\"},\"optimizer\":{\"enabled\":true,\"runs\":10000},\"remappings\":[]},\"sources\":{\"solidity/Inbox.sol\":{\"keccak256\":\"0x9b516081a036814c0169e20e484d4a5499066b7a6f48fada952b5e844a1ca3e5\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://32bde393b3f24ef4307d9626d4143f337b3c0bd34e17bb969fd5a15221d96987\",\"dweb:/ipfs/QmTkt2XZRtgsbSpmsVQUM3c4ebETQoDVYbmEV9yheBghnr\"]}},\"version\":1}"},"hashes":{}},"solidity/Inbox.sol:AttestationLib":{"code":"0x60566037600b82828239805160001a607314602a57634e487b7160e01b600052600060045260246000fd5b30600052607381538281f3fe73000000000000000000000000000000000000000030146080604052600080fdfea2646970667358221220c8c0a6f04bfc5cc97bd8039cea734aad522377e870dda5e1d59d8e81a77111b864736f6c63430008110033","runtime-code":"0x73000000000000000000000000000000000000000030146080604052600080fdfea2646970667358221220c8c0a6f04bfc5cc97bd8039cea734aad522377e870dda5e1d59d8e81a77111b864736f6c63430008110033","info":{"source":"// SPDX-License-Identifier: MIT\npragma solidity =0.8.17 ^0.8.0 ^0.8.1 ^0.8.2;\n\n// contracts/events/InboxEvents.sol\n\nabstract contract InboxEvents {\n /**\n * @notice Emitted when a snapshot is accepted by the Summit contract.\n * @param domain Domain where the signed Agent is active (ZERO for Guards)\n * @param agent Agent who signed the snapshot\n * @param snapPayload Raw payload with snapshot data\n * @param snapSignature Agent signature for the snapshot\n */\n event SnapshotAccepted(uint32 indexed domain, address indexed agent, bytes snapPayload, bytes snapSignature);\n\n /**\n * @notice Emitted when a snapshot is accepted by the Summit contract.\n * @param domain Domain where the signed Notary is active\n * @param notary Notary who signed the attestation\n * @param rcptPayload Raw payload with receipt data\n * @param rcptSignature Notary signature for the receipt\n */\n event ReceiptAccepted(uint32 domain, address notary, bytes rcptPayload, bytes rcptSignature);\n\n /**\n * @notice Emitted when a proof of invalid attestation is submitted.\n * @param attPayload Raw payload with Attestation data\n * @param attSignature Notary signature for the attestation\n */\n event InvalidAttestation(bytes attPayload, bytes attSignature);\n\n /**\n * @notice Emitted when a proof of invalid attestation report is submitted.\n * @param arPayload Raw payload with report data\n * @param arSignature Guard signature for the report\n */\n event InvalidAttestationReport(bytes arPayload, bytes arSignature);\n}\n\n// contracts/events/StatementInboxEvents.sol\n\nabstract contract StatementInboxEvents {\n // ════════════════════════════════════════════ STATEMENT ACCEPTED ═════════════════════════════════════════════════\n\n /**\n * @notice Emitted when a snapshot is accepted by the Destination contract.\n * @param domain Domain where the signed Notary is active\n * @param notary Notary who signed the attestation\n * @param attPayload Raw payload with attestation data\n * @param attSignature Notary signature for the attestation\n */\n event AttestationAccepted(uint32 domain, address notary, bytes attPayload, bytes attSignature);\n\n // ═════════════════════════════════════════ INVALID STATEMENT PROVED ══════════════════════════════════════════════\n\n /**\n * @notice Emitted when a proof of invalid receipt statement is submitted.\n * @param rcptPayload Raw payload with the receipt statement\n * @param rcptSignature Notary signature for the receipt statement\n */\n event InvalidReceipt(bytes rcptPayload, bytes rcptSignature);\n\n /**\n * @notice Emitted when a proof of invalid receipt report is submitted.\n * @param rrPayload Raw payload with report data\n * @param rrSignature Guard signature for the report\n */\n event InvalidReceiptReport(bytes rrPayload, bytes rrSignature);\n\n /**\n * @notice Emitted when a proof of invalid state in the signed attestation is submitted.\n * @param stateIndex Index of invalid state in the snapshot\n * @param statePayload Raw payload with state data\n * @param attPayload Raw payload with Attestation data for snapshot\n * @param attSignature Notary signature for the attestation\n */\n event InvalidStateWithAttestation(uint8 stateIndex, bytes statePayload, bytes attPayload, bytes attSignature);\n\n /**\n * @notice Emitted when a proof of invalid state in the signed snapshot is submitted.\n * @param stateIndex Index of invalid state in the snapshot\n * @param snapPayload Raw payload with snapshot data\n * @param snapSignature Agent signature for the snapshot\n */\n event InvalidStateWithSnapshot(uint8 stateIndex, bytes snapPayload, bytes snapSignature);\n\n /**\n * @notice Emitted when a proof of invalid state report is submitted.\n * @param srPayload Raw payload with report data\n * @param srSignature Guard signature for the report\n */\n event InvalidStateReport(bytes srPayload, bytes srSignature);\n}\n\n// contracts/interfaces/ISnapshotHub.sol\n\ninterface ISnapshotHub {\n /**\n * @notice Check that a given attestation is valid: matches the historical attestation\n * derived from an accepted Notary snapshot.\n * @dev Will revert if any of these is true:\n * - Attestation payload is not properly formatted.\n * @param attPayload Raw payload with attestation data\n * @return isValid Whether the provided attestation is valid\n */\n function isValidAttestation(bytes memory attPayload) external view returns (bool isValid);\n\n /**\n * @notice Returns saved attestation with the given nonce.\n * @dev Reverts if attestation with given nonce hasn't been created yet.\n * @param attNonce Nonce for the attestation\n * @return attPayload Raw payload with formatted Attestation data\n * @return agentRoot Agent root hash used for the attestation\n * @return snapGas Snapshot gas data used for the attestation\n */\n function getAttestation(uint32 attNonce)\n external\n view\n returns (bytes memory attPayload, bytes32 agentRoot, uint256[] memory snapGas);\n\n /**\n * @notice Returns the state with the highest known nonce submitted by a given Agent.\n * @param origin Domain of origin chain\n * @param agent Agent address\n * @return statePayload Raw payload with agent's latest state for origin\n */\n function getLatestAgentState(uint32 origin, address agent) external view returns (bytes memory statePayload);\n\n /**\n * @notice Returns latest saved attestation for a Notary.\n * @param notary Notary address\n * @return attPayload Raw payload with formatted Attestation data\n * @return agentRoot Agent root hash used for the attestation\n * @return snapGas Snapshot gas data used for the attestation\n */\n function getLatestNotaryAttestation(address notary)\n external\n view\n returns (bytes memory attPayload, bytes32 agentRoot, uint256[] memory snapGas);\n\n /**\n * @notice Returns Guard snapshot from the list of all accepted Guard snapshots.\n * @dev Reverts if snapshot with given index hasn't been accepted yet.\n * @param index Snapshot index in the list of all Guard snapshots\n * @return snapPayload Raw payload with Guard snapshot\n * @return snapSignature Raw payload with Guard signature for snapshot\n */\n function getGuardSnapshot(uint256 index)\n external\n view\n returns (bytes memory snapPayload, bytes memory snapSignature);\n\n /**\n * @notice Returns Notary snapshot from the list of all accepted Guard snapshots.\n * @dev Reverts if snapshot with given index hasn't been accepted yet.\n * @param index Snapshot index in the list of all Notary snapshots\n * @return snapPayload Raw payload with Notary snapshot\n * @return snapSignature Raw payload with Notary signature for snapshot\n */\n function getNotarySnapshot(uint256 index)\n external\n view\n returns (bytes memory snapPayload, bytes memory snapSignature);\n\n /**\n * @notice Returns Notary snapshot that was used for creating a given attestation.\n * @dev Reverts if any of these is true:\n * - Attestation payload is not properly formatted.\n * - Attestation is invalid (doesn't have a matching Notary snapshot).\n * @param attPayload Raw payload with attestation data\n * @return snapPayload Raw payload with Notary snapshot\n * @return snapSignature Raw payload with Notary signature for snapshot\n */\n function getNotarySnapshot(bytes memory attPayload)\n external\n view\n returns (bytes memory snapPayload, bytes memory snapSignature);\n\n /**\n * @notice Returns proof of inclusion of (root, origin) fields of a given snapshot's state\n * into the Snapshot Merkle Tree for a given attestation.\n * @dev Reverts if any of these is true:\n * - Attestation with given nonce hasn't been created yet.\n * - State index is out of range of snapshot list.\n * @param attNonce Nonce for the attestation\n * @param stateIndex Index of state in the attestation's snapshot\n * @return snapProof The snapshot proof\n */\n function getSnapshotProof(uint32 attNonce, uint8 stateIndex) external view returns (bytes32[] memory snapProof);\n}\n\n// contracts/interfaces/IStateHub.sol\n\ninterface IStateHub {\n /**\n * @notice Check that a given state is valid: matches the historical state of Origin contract.\n * Note: any Agent including an invalid state in their snapshot will be slashed\n * upon providing the snapshot and agent signature for it to Origin contract.\n * @dev Will revert if any of these is true:\n * - State payload is not properly formatted.\n * @param statePayload Raw payload with state data\n * @return isValid Whether the provided state is valid\n */\n function isValidState(bytes memory statePayload) external view returns (bool isValid);\n\n /**\n * @notice Returns the amount of saved states so far.\n * @dev This includes the initial state of \"empty Origin Merkle Tree\".\n */\n function statesAmount() external view returns (uint256);\n\n /**\n * @notice Suggest the data (state after latest sent message) to sign for an Agent.\n * Note: signing the suggested state data will will never lead to slashing of the actor,\n * assuming they have confirmed that the block, which number is included in the data,\n * is not subject to reorganization (which is different for every observed chain).\n * @return statePayload Raw payload with the latest state data\n */\n function suggestLatestState() external view returns (bytes memory statePayload);\n\n /**\n * @notice Given the historical nonce, suggest the state data to sign for an Agent.\n * Note: signing the suggested state data will will never lead to slashing of the actor,\n * assuming they have confirmed that the block, which number is included in the data,\n * is not subject to reorganization (which is different for every observed chain).\n * @param nonce Historical nonce to form a state\n * @return statePayload Raw payload with historical state data\n */\n function suggestState(uint32 nonce) external view returns (bytes memory statePayload);\n}\n\n// contracts/interfaces/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/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// node_modules/@openzeppelin/contracts/utils/math/Math.sol\n\n// OpenZeppelin Contracts (last updated v4.9.0) (utils/math/Math.sol)\n\n/**\n * @dev Standard math utilities missing in the Solidity language.\n */\nlibrary Math {\n enum Rounding {\n Down, // Toward negative infinity\n Up, // Toward infinity\n Zero // Toward zero\n }\n\n /**\n * @dev Returns the largest of two numbers.\n */\n function max(uint256 a, uint256 b) internal pure returns (uint256) {\n return a \u003e b ? a : b;\n }\n\n /**\n * @dev Returns the smallest of two numbers.\n */\n function min(uint256 a, uint256 b) internal pure returns (uint256) {\n return a \u003c b ? a : b;\n }\n\n /**\n * @dev Returns the average of two numbers. The result is rounded towards\n * zero.\n */\n function average(uint256 a, uint256 b) internal pure returns (uint256) {\n // (a + b) / 2 can overflow.\n return (a \u0026 b) + (a ^ b) / 2;\n }\n\n /**\n * @dev Returns the ceiling of the division of two numbers.\n *\n * This differs from standard division with `/` in that it rounds up instead\n * of rounding down.\n */\n function ceilDiv(uint256 a, uint256 b) internal pure returns (uint256) {\n // (a + b - 1) / b can overflow on addition, so we distribute.\n return a == 0 ? 0 : (a - 1) / b + 1;\n }\n\n /**\n * @notice Calculates floor(x * y / denominator) with full precision. Throws if result overflows a uint256 or denominator == 0\n * @dev Original credit to Remco Bloemen under MIT license (https://xn--2-umb.com/21/muldiv)\n * with further edits by Uniswap Labs also under MIT license.\n */\n function mulDiv(uint256 x, uint256 y, uint256 denominator) internal pure returns (uint256 result) {\n unchecked {\n // 512-bit multiply [prod1 prod0] = x * y. Compute the product mod 2^256 and mod 2^256 - 1, then use\n // use the Chinese Remainder Theorem to reconstruct the 512 bit result. The result is stored in two 256\n // variables such that product = prod1 * 2^256 + prod0.\n uint256 prod0; // Least significant 256 bits of the product\n uint256 prod1; // Most significant 256 bits of the product\n assembly {\n let mm := mulmod(x, y, not(0))\n prod0 := mul(x, y)\n prod1 := sub(sub(mm, prod0), lt(mm, prod0))\n }\n\n // Handle non-overflow cases, 256 by 256 division.\n if (prod1 == 0) {\n // Solidity will revert if denominator == 0, unlike the div opcode on its own.\n // The surrounding unchecked block does not change this fact.\n // See https://docs.soliditylang.org/en/latest/control-structures.html#checked-or-unchecked-arithmetic.\n return prod0 / denominator;\n }\n\n // Make sure the result is less than 2^256. Also prevents denominator == 0.\n require(denominator \u003e prod1, \"Math: mulDiv overflow\");\n\n ///////////////////////////////////////////////\n // 512 by 256 division.\n ///////////////////////////////////////////////\n\n // Make division exact by subtracting the remainder from [prod1 prod0].\n uint256 remainder;\n assembly {\n // Compute remainder using mulmod.\n remainder := mulmod(x, y, denominator)\n\n // Subtract 256 bit number from 512 bit number.\n prod1 := sub(prod1, gt(remainder, prod0))\n prod0 := sub(prod0, remainder)\n }\n\n // Factor powers of two out of denominator and compute largest power of two divisor of denominator. Always \u003e= 1.\n // See https://cs.stackexchange.com/q/138556/92363.\n\n // Does not overflow because the denominator cannot be zero at this stage in the function.\n uint256 twos = denominator \u0026 (~denominator + 1);\n assembly {\n // Divide denominator by twos.\n denominator := div(denominator, twos)\n\n // Divide [prod1 prod0] by twos.\n prod0 := div(prod0, twos)\n\n // Flip twos such that it is 2^256 / twos. If twos is zero, then it becomes one.\n twos := add(div(sub(0, twos), twos), 1)\n }\n\n // Shift in bits from prod1 into prod0.\n prod0 |= prod1 * twos;\n\n // Invert denominator mod 2^256. Now that denominator is an odd number, it has an inverse modulo 2^256 such\n // that denominator * inv = 1 mod 2^256. Compute the inverse by starting with a seed that is correct for\n // four bits. That is, denominator * inv = 1 mod 2^4.\n uint256 inverse = (3 * denominator) ^ 2;\n\n // Use the Newton-Raphson iteration to improve the precision. Thanks to Hensel's lifting lemma, this also works\n // in modular arithmetic, doubling the correct bits in each step.\n inverse *= 2 - denominator * inverse; // inverse mod 2^8\n inverse *= 2 - denominator * inverse; // inverse mod 2^16\n inverse *= 2 - denominator * inverse; // inverse mod 2^32\n inverse *= 2 - denominator * inverse; // inverse mod 2^64\n inverse *= 2 - denominator * inverse; // inverse mod 2^128\n inverse *= 2 - denominator * inverse; // inverse mod 2^256\n\n // Because the division is now exact we can divide by multiplying with the modular inverse of denominator.\n // This will give us the correct result modulo 2^256. Since the preconditions guarantee that the outcome is\n // less than 2^256, this is the final result. We don't need to compute the high bits of the result and prod1\n // is no longer required.\n result = prod0 * inverse;\n return result;\n }\n }\n\n /**\n * @notice Calculates x * y / denominator with full precision, following the selected rounding direction.\n */\n function mulDiv(uint256 x, uint256 y, uint256 denominator, Rounding rounding) internal pure returns (uint256) {\n uint256 result = mulDiv(x, y, denominator);\n if (rounding == Rounding.Up \u0026\u0026 mulmod(x, y, denominator) \u003e 0) {\n result += 1;\n }\n return result;\n }\n\n /**\n * @dev Returns the square root of a number. If the number is not a perfect square, the value is rounded down.\n *\n * Inspired by Henry S. Warren, Jr.'s \"Hacker's Delight\" (Chapter 11).\n */\n function sqrt(uint256 a) internal pure returns (uint256) {\n if (a == 0) {\n return 0;\n }\n\n // For our first guess, we get the biggest power of 2 which is smaller than the square root of the target.\n //\n // We know that the \"msb\" (most significant bit) of our target number `a` is a power of 2 such that we have\n // `msb(a) \u003c= a \u003c 2*msb(a)`. This value can be written `msb(a)=2**k` with `k=log2(a)`.\n //\n // This can be rewritten `2**log2(a) \u003c= a \u003c 2**(log2(a) + 1)`\n // → `sqrt(2**k) \u003c= sqrt(a) \u003c sqrt(2**(k+1))`\n // → `2**(k/2) \u003c= sqrt(a) \u003c 2**((k+1)/2) \u003c= 2**(k/2 + 1)`\n //\n // Consequently, `2**(log2(a) / 2)` is a good first approximation of `sqrt(a)` with at least 1 correct bit.\n uint256 result = 1 \u003c\u003c (log2(a) \u003e\u003e 1);\n\n // At this point `result` is an estimation with one bit of precision. We know the true value is a uint128,\n // since it is the square root of a uint256. Newton's method converges quadratically (precision doubles at\n // every iteration). We thus need at most 7 iteration to turn our partial result with one bit of precision\n // into the expected uint128 result.\n unchecked {\n result = (result + a / result) \u003e\u003e 1;\n result = (result + a / result) \u003e\u003e 1;\n result = (result + a / result) \u003e\u003e 1;\n result = (result + a / result) \u003e\u003e 1;\n result = (result + a / result) \u003e\u003e 1;\n result = (result + a / result) \u003e\u003e 1;\n result = (result + a / result) \u003e\u003e 1;\n return min(result, a / result);\n }\n }\n\n /**\n * @notice Calculates sqrt(a), following the selected rounding direction.\n */\n function sqrt(uint256 a, Rounding rounding) internal pure returns (uint256) {\n unchecked {\n uint256 result = sqrt(a);\n return result + (rounding == Rounding.Up \u0026\u0026 result * result \u003c a ? 1 : 0);\n }\n }\n\n /**\n * @dev Return the log in base 2, rounded down, of a positive value.\n * Returns 0 if given 0.\n */\n function log2(uint256 value) internal pure returns (uint256) {\n uint256 result = 0;\n unchecked {\n if (value \u003e\u003e 128 \u003e 0) {\n value \u003e\u003e= 128;\n result += 128;\n }\n if (value \u003e\u003e 64 \u003e 0) {\n value \u003e\u003e= 64;\n result += 64;\n }\n if (value \u003e\u003e 32 \u003e 0) {\n value \u003e\u003e= 32;\n result += 32;\n }\n if (value \u003e\u003e 16 \u003e 0) {\n value \u003e\u003e= 16;\n result += 16;\n }\n if (value \u003e\u003e 8 \u003e 0) {\n value \u003e\u003e= 8;\n result += 8;\n }\n if (value \u003e\u003e 4 \u003e 0) {\n value \u003e\u003e= 4;\n result += 4;\n }\n if (value \u003e\u003e 2 \u003e 0) {\n value \u003e\u003e= 2;\n result += 2;\n }\n if (value \u003e\u003e 1 \u003e 0) {\n result += 1;\n }\n }\n return result;\n }\n\n /**\n * @dev Return the log in base 2, following the selected rounding direction, of a positive value.\n * Returns 0 if given 0.\n */\n function log2(uint256 value, Rounding rounding) internal pure returns (uint256) {\n unchecked {\n uint256 result = log2(value);\n return result + (rounding == Rounding.Up \u0026\u0026 1 \u003c\u003c result \u003c value ? 1 : 0);\n }\n }\n\n /**\n * @dev Return the log in base 10, rounded down, of a positive value.\n * Returns 0 if given 0.\n */\n function log10(uint256 value) internal pure returns (uint256) {\n uint256 result = 0;\n unchecked {\n if (value \u003e= 10 ** 64) {\n value /= 10 ** 64;\n result += 64;\n }\n if (value \u003e= 10 ** 32) {\n value /= 10 ** 32;\n result += 32;\n }\n if (value \u003e= 10 ** 16) {\n value /= 10 ** 16;\n result += 16;\n }\n if (value \u003e= 10 ** 8) {\n value /= 10 ** 8;\n result += 8;\n }\n if (value \u003e= 10 ** 4) {\n value /= 10 ** 4;\n result += 4;\n }\n if (value \u003e= 10 ** 2) {\n value /= 10 ** 2;\n result += 2;\n }\n if (value \u003e= 10 ** 1) {\n result += 1;\n }\n }\n return result;\n }\n\n /**\n * @dev Return the log in base 10, following the selected rounding direction, of a positive value.\n * Returns 0 if given 0.\n */\n function log10(uint256 value, Rounding rounding) internal pure returns (uint256) {\n unchecked {\n uint256 result = log10(value);\n return result + (rounding == Rounding.Up \u0026\u0026 10 ** result \u003c value ? 1 : 0);\n }\n }\n\n /**\n * @dev Return the log in base 256, rounded down, of a positive value.\n * Returns 0 if given 0.\n *\n * Adding one to the result gives the number of pairs of hex symbols needed to represent `value` as a hex string.\n */\n function log256(uint256 value) internal pure returns (uint256) {\n uint256 result = 0;\n unchecked {\n if (value \u003e\u003e 128 \u003e 0) {\n value \u003e\u003e= 128;\n result += 16;\n }\n if (value \u003e\u003e 64 \u003e 0) {\n value \u003e\u003e= 64;\n result += 8;\n }\n if (value \u003e\u003e 32 \u003e 0) {\n value \u003e\u003e= 32;\n result += 4;\n }\n if (value \u003e\u003e 16 \u003e 0) {\n value \u003e\u003e= 16;\n result += 2;\n }\n if (value \u003e\u003e 8 \u003e 0) {\n result += 1;\n }\n }\n return result;\n }\n\n /**\n * @dev Return the log in base 256, following the selected rounding direction, of a positive value.\n * Returns 0 if given 0.\n */\n function log256(uint256 value, Rounding rounding) internal pure returns (uint256) {\n unchecked {\n uint256 result = log256(value);\n return result + (rounding == Rounding.Up \u0026\u0026 1 \u003c\u003c (result \u003c\u003c 3) \u003c value ? 1 : 0);\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/utils/math/SignedMath.sol\n\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/math/SignedMath.sol)\n\n/**\n * @dev Standard signed math utilities missing in the Solidity language.\n */\nlibrary SignedMath {\n /**\n * @dev Returns the largest of two signed numbers.\n */\n function max(int256 a, int256 b) internal pure returns (int256) {\n return a \u003e b ? a : b;\n }\n\n /**\n * @dev Returns the smallest of two signed numbers.\n */\n function min(int256 a, int256 b) internal pure returns (int256) {\n return a \u003c b ? a : b;\n }\n\n /**\n * @dev Returns the average of two signed numbers without overflow.\n * The result is rounded towards zero.\n */\n function average(int256 a, int256 b) internal pure returns (int256) {\n // Formula from the book \"Hacker's Delight\"\n int256 x = (a \u0026 b) + ((a ^ b) \u003e\u003e 1);\n return x + (int256(uint256(x) \u003e\u003e 255) \u0026 (a ^ b));\n }\n\n /**\n * @dev Returns the absolute unsigned value of a signed value.\n */\n function abs(int256 n) internal pure returns (uint256) {\n unchecked {\n // must be unchecked in order to support `n = type(int256).min`\n return uint256(n \u003e= 0 ? n : -n);\n }\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// 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/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/InterfaceSummit.sol\n\ninterface InterfaceSummit {\n // ══════════════════════════════════════════ ACCEPT AGENT STATEMENTS ══════════════════════════════════════════════\n\n /**\n * @notice Accepts a receipt, which local `AgentManager` verified to have been signed by an active Notary.\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 * - Notary who signed the receipt is referenced as the \"Receipt Notary\".\n * - Notary who signed the attestation on destination chain is referenced as the \"Attestation Notary\".\n * \u003e Will revert if any of these is true:\n * \u003e - Called by anyone other than local `AgentManager`.\n * \u003e - Receipt body payload is not properly formatted.\n * \u003e - Receipt signer is in Dispute.\n * \u003e - Receipt's snapshot root is unknown.\n * @param rcptNotaryIndex Index of Receipt Notary in Agent Merkle Tree\n * @param attNotaryIndex Index of Attestation Notary in Agent Merkle Tree\n * @param sigIndex Index of stored Notary signature\n * @param attNonce Nonce of the attestation used for proving the executed message\n * @param paddedTips Padded encoded paid tips information\n * @param rcptPayload Raw payload with message execution receipt\n * @return wasAccepted Whether the receipt was accepted\n */\n function acceptReceipt(\n uint32 rcptNotaryIndex,\n uint32 attNotaryIndex,\n uint256 sigIndex,\n uint32 attNonce,\n uint256 paddedTips,\n bytes memory rcptPayload\n ) external returns (bool wasAccepted);\n\n /**\n * @notice Accepts a snapshot, which local `AgentManager` verified to have been signed by an active Guard.\n * \u003e Snapshot is a list of states for a set of Origin contracts residing on any of the chains.\n * All the states in the Guard-signed snapshot become available for Notary signing.\n * \u003e Will revert if any of these is true:\n * \u003e - Called by anyone other than local `AgentManager`.\n * \u003e - Snapshot payload is not properly formatted.\n * \u003e - Snapshot contains a state older then the Guard has previously submitted.\n * @param guardIndex Index of Guard in Agent Merkle Tree\n * @param sigIndex Index of stored Agent signature\n * @param snapPayload Raw payload with snapshot data\n */\n function acceptGuardSnapshot(uint32 guardIndex, uint256 sigIndex, bytes memory snapPayload) external;\n\n /**\n * @notice Accepts a snapshot, which local `AgentManager` verified to have been signed by an active Notary.\n * \u003e Snapshot is a list of states for a set of Origin contracts residing on any of the chains.\n * Snapshot Merkle Root is calculated and saved for valid snapshots, i.e.\n * snapshots which are only using states previously submitted by any of the Guards.\n * - Notary could use states singed by the same of different Guards 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 - Called by anyone other than local `AgentManager`.\n * \u003e - Snapshot payload is not properly formatted.\n * \u003e - Snapshot contains a state older then the Notary has previously submitted.\n * \u003e - Snapshot contains a state that no Guard has previously submitted.\n * @param notaryIndex Index of Notary in Agent Merkle Tree\n * @param sigIndex Index of stored Agent signature\n * @param agentRoot Current root of the Agent Merkle Tree\n * @param snapPayload Raw payload with snapshot data\n * @return attPayload Raw payload with data for attestation derived from Notary snapshot.\n */\n function acceptNotarySnapshot(uint32 notaryIndex, uint256 sigIndex, bytes32 agentRoot, bytes memory snapPayload)\n external\n returns (bytes memory attPayload);\n\n // ════════════════════════════════════════════════ TIPS LOGIC ═════════════════════════════════════════════════════\n\n /**\n * @notice Distributes tips using the first Receipt from the \"receipt quarantine queue\".\n * Possible scenarios:\n * - Receipt queue is empty =\u003e does nothing\n * - Receipt optimistic period is not over =\u003e does nothing\n * - Either of Notaries present in Receipt was slashed =\u003e receipt is deleted from the queue\n * - Either of Notaries present in Receipt in Dispute =\u003e receipt is moved to the end of queue\n * - None of the above =\u003e receipt tips are distributed\n * @dev Returned value makes it possible to do the following: `while (distributeTips()) {}`\n * @return queuePopped Whether the first element was popped from the queue\n */\n function distributeTips() external returns (bool queuePopped);\n\n /**\n * @notice Withdraws locked base message tips from requested domain Origin to the recipient.\n * This is done by a call to a local Origin contract, or by a manager message to the remote chain.\n * @dev This will revert, if the pending balance of origin tips (earned-claimed) is lower than requested.\n * @param origin Domain of chain to withdraw tips on\n * @param amount Amount of tips to withdraw\n */\n function withdrawTips(uint32 origin, uint256 amount) external;\n\n // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════\n\n /**\n * @notice Returns earned and claimed tips for the actor.\n * Note: Tips for address(0) belong to the Treasury.\n * @param actor Address of the actor\n * @param origin Domain where the tips were initially paid\n * @return earned Total amount of origin tips the actor has earned so far\n * @return claimed Total amount of origin tips the actor has claimed so far\n */\n function actorTips(address actor, uint32 origin) external view returns (uint128 earned, uint128 claimed);\n\n /**\n * @notice Returns the amount of receipts in the \"Receipt Quarantine Queue\".\n */\n function receiptQueueLength() external view returns (uint256);\n\n /**\n * @notice Returns the state with the highest known nonce\n * submitted by any of the currently active Guards.\n * @param origin Domain of origin chain\n * @return statePayload Raw payload with latest active Guard state for origin\n */\n function getLatestState(uint32 origin) external view returns (bytes memory statePayload);\n}\n\n// node_modules/@openzeppelin/contracts/utils/Strings.sol\n\n// OpenZeppelin Contracts (last updated v4.9.0) (utils/Strings.sol)\n\n/**\n * @dev String operations.\n */\nlibrary Strings {\n bytes16 private constant _SYMBOLS = \"0123456789abcdef\";\n uint8 private constant _ADDRESS_LENGTH = 20;\n\n /**\n * @dev Converts a `uint256` to its ASCII `string` decimal representation.\n */\n function toString(uint256 value) internal pure returns (string memory) {\n unchecked {\n uint256 length = Math.log10(value) + 1;\n string memory buffer = new string(length);\n uint256 ptr;\n /// @solidity memory-safe-assembly\n assembly {\n ptr := add(buffer, add(32, length))\n }\n while (true) {\n ptr--;\n /// @solidity memory-safe-assembly\n assembly {\n mstore8(ptr, byte(mod(value, 10), _SYMBOLS))\n }\n value /= 10;\n if (value == 0) break;\n }\n return buffer;\n }\n }\n\n /**\n * @dev Converts a `int256` to its ASCII `string` decimal representation.\n */\n function toString(int256 value) internal pure returns (string memory) {\n return string(abi.encodePacked(value \u003c 0 ? \"-\" : \"\", toString(SignedMath.abs(value))));\n }\n\n /**\n * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation.\n */\n function toHexString(uint256 value) internal pure returns (string memory) {\n unchecked {\n return toHexString(value, Math.log256(value) + 1);\n }\n }\n\n /**\n * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length.\n */\n function toHexString(uint256 value, uint256 length) internal pure returns (string memory) {\n bytes memory buffer = new bytes(2 * length + 2);\n buffer[0] = \"0\";\n buffer[1] = \"x\";\n for (uint256 i = 2 * length + 1; i \u003e 1; --i) {\n buffer[i] = _SYMBOLS[value \u0026 0xf];\n value \u003e\u003e= 4;\n }\n require(value == 0, \"Strings: hex length insufficient\");\n return string(buffer);\n }\n\n /**\n * @dev Converts an `address` with fixed length of 20 bytes to its not checksummed ASCII `string` hexadecimal representation.\n */\n function toHexString(address addr) internal pure returns (string memory) {\n return toHexString(uint256(uint160(addr)), _ADDRESS_LENGTH);\n }\n\n /**\n * @dev Returns true if the two strings are equal.\n */\n function equal(string memory a, string memory b) internal pure returns (bool) {\n return keccak256(bytes(a)) == keccak256(bytes(b));\n }\n}\n\n// node_modules/@openzeppelin/contracts-upgradeable/utils/ContextUpgradeable.sol\n\n// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)\n\n/**\n * @dev Provides information about the current execution context, including the\n * sender of the transaction and its data. While these are generally available\n * via msg.sender and msg.data, they should not be accessed in such a direct\n * manner, since when dealing with meta-transactions the account sending and\n * paying for execution may not be the actual sender (as far as an application\n * is concerned).\n *\n * This contract is only required for intermediate, library-like contracts.\n */\nabstract contract ContextUpgradeable is Initializable {\n function __Context_init() internal onlyInitializing {\n }\n\n function __Context_init_unchained() internal onlyInitializing {\n }\n function _msgSender() internal view virtual returns (address) {\n return msg.sender;\n }\n\n function _msgData() internal view virtual returns (bytes calldata) {\n return msg.data;\n }\n\n /**\n * @dev This empty reserved space is put in place to allow future versions to add new\n * variables without shifting down storage in the inheritance chain.\n * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\n */\n uint256[50] private __gap;\n}\n\n// contracts/libs/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/utils/cryptography/ECDSA.sol\n\n// OpenZeppelin Contracts (last updated v4.9.0) (utils/cryptography/ECDSA.sol)\n\n/**\n * @dev Elliptic Curve Digital Signature Algorithm (ECDSA) operations.\n *\n * These functions can be used to verify that a message was signed by the holder\n * of the private keys of a given address.\n */\nlibrary ECDSA {\n enum RecoverError {\n NoError,\n InvalidSignature,\n InvalidSignatureLength,\n InvalidSignatureS,\n InvalidSignatureV // Deprecated in v4.8\n }\n\n function _throwError(RecoverError error) private pure {\n if (error == RecoverError.NoError) {\n return; // no error: do nothing\n } else if (error == RecoverError.InvalidSignature) {\n revert(\"ECDSA: invalid signature\");\n } else if (error == RecoverError.InvalidSignatureLength) {\n revert(\"ECDSA: invalid signature length\");\n } else if (error == RecoverError.InvalidSignatureS) {\n revert(\"ECDSA: invalid signature 's' value\");\n }\n }\n\n /**\n * @dev Returns the address that signed a hashed message (`hash`) with\n * `signature` or error string. This address can then be used for verification purposes.\n *\n * The `ecrecover` EVM opcode allows for malleable (non-unique) signatures:\n * this function rejects them by requiring the `s` value to be in the lower\n * half order, and the `v` value to be either 27 or 28.\n *\n * IMPORTANT: `hash` _must_ be the result of a hash operation for the\n * verification to be secure: it is possible to craft signatures that\n * recover to arbitrary addresses for non-hashed data. A safe way to ensure\n * this is by receiving a hash of the original message (which may otherwise\n * be too long), and then calling {toEthSignedMessageHash} on it.\n *\n * Documentation for signature generation:\n * - with https://web3js.readthedocs.io/en/v1.3.4/web3-eth-accounts.html#sign[Web3.js]\n * - with https://docs.ethers.io/v5/api/signer/#Signer-signMessage[ethers]\n *\n * _Available since v4.3._\n */\n function tryRecover(bytes32 hash, bytes memory signature) internal pure returns (address, RecoverError) {\n if (signature.length == 65) {\n bytes32 r;\n bytes32 s;\n uint8 v;\n // ecrecover takes the signature parameters, and the only way to get them\n // currently is to use assembly.\n /// @solidity memory-safe-assembly\n assembly {\n r := mload(add(signature, 0x20))\n s := mload(add(signature, 0x40))\n v := byte(0, mload(add(signature, 0x60)))\n }\n return tryRecover(hash, v, r, s);\n } else {\n return (address(0), RecoverError.InvalidSignatureLength);\n }\n }\n\n /**\n * @dev Returns the address that signed a hashed message (`hash`) with\n * `signature`. This address can then be used for verification purposes.\n *\n * The `ecrecover` EVM opcode allows for malleable (non-unique) signatures:\n * this function rejects them by requiring the `s` value to be in the lower\n * half order, and the `v` value to be either 27 or 28.\n *\n * IMPORTANT: `hash` _must_ be the result of a hash operation for the\n * verification to be secure: it is possible to craft signatures that\n * recover to arbitrary addresses for non-hashed data. A safe way to ensure\n * this is by receiving a hash of the original message (which may otherwise\n * be too long), and then calling {toEthSignedMessageHash} on it.\n */\n function recover(bytes32 hash, bytes memory signature) internal pure returns (address) {\n (address recovered, RecoverError error) = tryRecover(hash, signature);\n _throwError(error);\n return recovered;\n }\n\n /**\n * @dev Overload of {ECDSA-tryRecover} that receives the `r` and `vs` short-signature fields separately.\n *\n * See https://eips.ethereum.org/EIPS/eip-2098[EIP-2098 short signatures]\n *\n * _Available since v4.3._\n */\n function tryRecover(bytes32 hash, bytes32 r, bytes32 vs) internal pure returns (address, RecoverError) {\n bytes32 s = vs \u0026 bytes32(0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff);\n uint8 v = uint8((uint256(vs) \u003e\u003e 255) + 27);\n return tryRecover(hash, v, r, s);\n }\n\n /**\n * @dev Overload of {ECDSA-recover} that receives the `r and `vs` short-signature fields separately.\n *\n * _Available since v4.2._\n */\n function recover(bytes32 hash, bytes32 r, bytes32 vs) internal pure returns (address) {\n (address recovered, RecoverError error) = tryRecover(hash, r, vs);\n _throwError(error);\n return recovered;\n }\n\n /**\n * @dev Overload of {ECDSA-tryRecover} that receives the `v`,\n * `r` and `s` signature fields separately.\n *\n * _Available since v4.3._\n */\n function tryRecover(bytes32 hash, uint8 v, bytes32 r, bytes32 s) internal pure returns (address, RecoverError) {\n // EIP-2 still allows signature malleability for ecrecover(). Remove this possibility and make the signature\n // unique. Appendix F in the Ethereum Yellow paper (https://ethereum.github.io/yellowpaper/paper.pdf), defines\n // the valid range for s in (301): 0 \u003c s \u003c secp256k1n ÷ 2 + 1, and for v in (302): v ∈ {27, 28}. Most\n // signatures from current libraries generate a unique signature with an s-value in the lower half order.\n //\n // If your library generates malleable signatures, such as s-values in the upper range, calculate a new s-value\n // with 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141 - s1 and flip v from 27 to 28 or\n // vice versa. If your library also generates signatures with 0/1 for v instead 27/28, add 27 to v to accept\n // these malleable signatures as well.\n if (uint256(s) \u003e 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0) {\n return (address(0), RecoverError.InvalidSignatureS);\n }\n\n // If the signature is valid (and not malleable), return the signer address\n address signer = ecrecover(hash, v, r, s);\n if (signer == address(0)) {\n return (address(0), RecoverError.InvalidSignature);\n }\n\n return (signer, RecoverError.NoError);\n }\n\n /**\n * @dev Overload of {ECDSA-recover} that receives the `v`,\n * `r` and `s` signature fields separately.\n */\n function recover(bytes32 hash, uint8 v, bytes32 r, bytes32 s) internal pure returns (address) {\n (address recovered, RecoverError error) = tryRecover(hash, v, r, s);\n _throwError(error);\n return recovered;\n }\n\n /**\n * @dev Returns an Ethereum Signed Message, created from a `hash`. This\n * produces hash corresponding to the one signed with the\n * https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`]\n * JSON-RPC method as part of EIP-191.\n *\n * See {recover}.\n */\n function toEthSignedMessageHash(bytes32 hash) internal pure returns (bytes32 message) {\n // 32 is the length in bytes of hash,\n // enforced by the type signature above\n /// @solidity memory-safe-assembly\n assembly {\n mstore(0x00, \"\\x19Ethereum Signed Message:\\n32\")\n mstore(0x1c, hash)\n message := keccak256(0x00, 0x3c)\n }\n }\n\n /**\n * @dev Returns an Ethereum Signed Message, created from `s`. This\n * produces hash corresponding to the one signed with the\n * https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`]\n * JSON-RPC method as part of EIP-191.\n *\n * See {recover}.\n */\n function toEthSignedMessageHash(bytes memory s) internal pure returns (bytes32) {\n return keccak256(abi.encodePacked(\"\\x19Ethereum Signed Message:\\n\", Strings.toString(s.length), s));\n }\n\n /**\n * @dev Returns an Ethereum Signed Typed Data, created from a\n * `domainSeparator` and a `structHash`. This produces hash corresponding\n * to the one signed with the\n * https://eips.ethereum.org/EIPS/eip-712[`eth_signTypedData`]\n * JSON-RPC method as part of EIP-712.\n *\n * See {recover}.\n */\n function toTypedDataHash(bytes32 domainSeparator, bytes32 structHash) internal pure returns (bytes32 data) {\n /// @solidity memory-safe-assembly\n assembly {\n let ptr := mload(0x40)\n mstore(ptr, \"\\x19\\x01\")\n mstore(add(ptr, 0x02), domainSeparator)\n mstore(add(ptr, 0x22), structHash)\n data := keccak256(ptr, 0x42)\n }\n }\n\n /**\n * @dev Returns an Ethereum Signed Data with intended validator, created from a\n * `validator` and `data` according to the version 0 of EIP-191.\n *\n * See {recover}.\n */\n function toDataWithIntendedValidatorHash(address validator, bytes memory data) internal pure returns (bytes32) {\n return keccak256(abi.encodePacked(\"\\x19\\x00\", validator, data));\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/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/inbox/StatementInbox.sol\n\n// ══════════════════════════════ LIBRARY IMPORTS ══════════════════════════════\n\n// ═════════════════════════════ INTERNAL IMPORTS ══════════════════════════════\n\n// ═════════════════════════════ EXTERNAL IMPORTS ══════════════════════════════\n\n/// @notice `StatementInbox` is the entry point for all agent-signed statements. It verifies the\n/// agent signatures, and passes the unsigned statements to the contract to consume it via `acceptX` functions. Is is\n/// also used to verify the agent-signed statements and initiate the agent slashing, should the statement be invalid.\n/// `StatementInbox` is responsible for the following:\n/// - Accepting State and Receipt Reports to initiate a dispute between Guard and Notary.\n/// - Storing all the Guard Reports with the Guard signature leading to a dispute.\n/// - Verifying State/State Reports referencing the local chain and slashing the signer if statement is invalid.\n/// - Verifying Receipt/Receipt Reports referencing the local chain and slashing the signer if statement is invalid.\nabstract contract StatementInbox is MessagingBase, StatementInboxEvents, IStatementInbox {\n using AttestationLib for bytes;\n using ReceiptLib for bytes;\n using StateLib for bytes;\n using SnapshotLib for bytes;\n\n struct StoredReport {\n uint256 sigIndex;\n bytes statementPayload;\n }\n\n // ══════════════════════════════════════════════════ STORAGE ══════════════════════════════════════════════════════\n\n address public agentManager;\n address public origin;\n address public destination;\n\n // TODO: optimize this\n bytes[] internal _storedSignatures;\n StoredReport[] internal _storedReports;\n\n /// @dev gap for upgrade safety\n uint256[45] private __GAP; // solhint-disable-line var-name-mixedcase\n\n // ════════════════════════════════════════════════ INITIALIZER ════════════════════════════════════════════════════\n\n /// @dev Initializes the contract:\n /// - Sets up `msg.sender` as the owner of the contract.\n /// - Sets up `agentManager`, `origin`, and `destination`.\n // solhint-disable-next-line func-name-mixedcase\n function __StatementInbox_init(address agentManager_, address origin_, address destination_)\n internal\n onlyInitializing\n {\n agentManager = agentManager_;\n origin = origin_;\n destination = destination_;\n __Ownable2Step_init();\n }\n\n // ══════════════════════════════════════════ SUBMIT AGENT STATEMENTS ══════════════════════════════════════════════\n\n /// @inheritdoc IStatementInbox\n // solhint-disable-next-line ordering\n function submitStateReportWithSnapshot(\n uint8 stateIndex,\n bytes memory srSignature,\n bytes memory snapPayload,\n bytes memory snapSignature\n ) external returns (bool wasAccepted) {\n // This will revert if payload is not a snapshot\n Snapshot snapshot = snapPayload.castToSnapshot();\n // This will revert if the snapshot signer is not a known Notary\n (AgentStatus memory notaryStatus,) =\n _verifySnapshot({snapshot: snapshot, snapSignature: snapSignature, verifyNotary: true});\n // Notary needs to be Active/Unstaking\n notaryStatus.verifyActiveUnstaking();\n // Check if Notary is active on this chain\n _verifyNotaryDomain(notaryStatus.domain);\n // This will revert if state index is out of range\n State state = snapshot.state(stateIndex);\n // This will revert if the report signer is not an known Guard\n (AgentStatus memory guardStatus,) = _verifyStateReport(state, srSignature);\n // Check that Guard is active\n guardStatus.verifyActive();\n _saveReport(state.unwrap().clone(), srSignature);\n // This will revert if either actor is already in dispute\n IAgentManager(agentManager).openDispute(guardStatus.index, notaryStatus.index);\n return true;\n }\n\n /// @inheritdoc IStatementInbox\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 // This will revert if payload is not a snapshot\n Snapshot snapshot = snapPayload.castToSnapshot();\n // This will revert if state index is out of range\n State state = snapshot.state(stateIndex);\n // This will revert if the report signer is not an known Guard\n (AgentStatus memory guardStatus,) = _verifyStateReport(state, srSignature);\n // Check that Guard is active\n guardStatus.verifyActive();\n // This will revert if payload is not an attestation\n Attestation att = attPayload.castToAttestation();\n // This will revert if signer is not an known Notary\n (AgentStatus memory notaryStatus,) = _verifyAttestation(att, attSignature);\n // Notary needs to be Active/Unstaking\n notaryStatus.verifyActiveUnstaking();\n // Check if Notary is active on this chain\n _verifyNotaryDomain(notaryStatus.domain);\n if (snapshot.calculateRoot() != att.snapRoot()) revert IncorrectSnapshotRoot();\n _saveReport(state.unwrap().clone(), srSignature);\n // This will revert if either actor is already in dispute\n IAgentManager(agentManager).openDispute(guardStatus.index, notaryStatus.index);\n return true;\n }\n\n /// @inheritdoc IStatementInbox\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 // This will revert if payload is not a state\n State state = statePayload.castToState();\n // This will revert if the report signer is not an known Guard\n (AgentStatus memory guardStatus,) = _verifyStateReport(state, srSignature);\n // Check that Guard is active\n guardStatus.verifyActive();\n // This will revert if payload is not an attestation\n Attestation att = attPayload.castToAttestation();\n // This will revert if signer is not a known Notary\n (AgentStatus memory notaryStatus,) = _verifyAttestation(att, attSignature);\n // Notary needs to be Active/Unstaking\n notaryStatus.verifyActiveUnstaking();\n // Check if Notary is active on this chain\n _verifyNotaryDomain(notaryStatus.domain);\n // This will revert if any of these is true:\n // - Attestation root is not equal to Merkle Root derived from State and Snapshot Proof.\n // - Snapshot Proof's first element does not match the State metadata.\n // - Snapshot Proof length exceeds Snapshot tree Height.\n // - State index is out of range.\n _verifySnapshotMerkle(att, stateIndex, state, snapProof);\n _saveReport(statePayload, srSignature);\n // This will revert if either actor is already in dispute\n IAgentManager(agentManager).openDispute(guardStatus.index, notaryStatus.index);\n return true;\n }\n\n // ══════════════════════════════════════════ VERIFY AGENT STATEMENTS ══════════════════════════════════════════════\n\n /// @inheritdoc IStatementInbox\n function verifyReceipt(bytes memory rcptPayload, bytes memory rcptSignature)\n external\n returns (bool isValidReceipt)\n {\n // This will revert if payload is not a receipt\n Receipt rcpt = rcptPayload.castToReceipt();\n // This will revert if the attestation signer is not a known Notary\n (AgentStatus memory status, address notary) = _verifyReceipt(rcpt, rcptSignature);\n // Notary needs to be Active/Unstaking\n status.verifyActiveUnstaking();\n isValidReceipt = IExecutionHub(destination).isValidReceipt(rcptPayload);\n if (!isValidReceipt) {\n emit InvalidReceipt(rcptPayload, rcptSignature);\n IAgentManager(agentManager).slashAgent(status.domain, notary, msg.sender);\n }\n }\n\n /// @inheritdoc IStatementInbox\n function verifyReceiptReport(bytes memory rcptPayload, bytes memory rrSignature)\n external\n returns (bool isValidReport)\n {\n // This will revert if payload is not a receipt\n Receipt rcpt = rcptPayload.castToReceipt();\n // This will revert if the report signer is not a known Guard\n (AgentStatus memory status, address guard) = _verifyReceiptReport(rcpt, rrSignature);\n // Guard needs to be Active/Unstaking\n status.verifyActiveUnstaking();\n // Report is valid IF AND ONLY IF the reported receipt in invalid\n isValidReport = !IExecutionHub(destination).isValidReceipt(rcptPayload);\n if (!isValidReport) {\n emit InvalidReceiptReport(rcptPayload, rrSignature);\n IAgentManager(agentManager).slashAgent(status.domain, guard, msg.sender);\n }\n }\n\n /// @inheritdoc IStatementInbox\n function verifyStateWithAttestation(\n uint8 stateIndex,\n bytes memory snapPayload,\n bytes memory attPayload,\n bytes memory attSignature\n ) external returns (bool isValidState) {\n // This will revert if payload is not an attestation\n Attestation att = attPayload.castToAttestation();\n // This will revert if the attestation signer is not a known Notary\n (AgentStatus memory status, address notary) = _verifyAttestation(att, attSignature);\n // Notary needs to be Active/Unstaking\n status.verifyActiveUnstaking();\n // This will revert if payload is not a snapshot\n Snapshot snapshot = snapPayload.castToSnapshot();\n if (snapshot.calculateRoot() != att.snapRoot()) revert IncorrectSnapshotRoot();\n // This will revert if state does not refer to this chain\n bytes memory statePayload = snapshot.state(stateIndex).unwrap().clone();\n isValidState = IStateHub(origin).isValidState(statePayload);\n if (!isValidState) {\n emit InvalidStateWithAttestation(stateIndex, statePayload, attPayload, attSignature);\n IAgentManager(agentManager).slashAgent(status.domain, notary, msg.sender);\n }\n }\n\n /// @inheritdoc IStatementInbox\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 // This will revert if payload is not an attestation\n Attestation att = attPayload.castToAttestation();\n // This will revert if the attestation signer is not a known Notary\n (AgentStatus memory status, address notary) = _verifyAttestation(att, attSignature);\n // Notary needs to be Active/Unstaking\n status.verifyActiveUnstaking();\n // This will revert if payload is not a state\n State state = statePayload.castToState();\n // This will revert if any of these is true:\n // - Attestation root is not equal to Merkle Root derived from State and Snapshot Proof.\n // - Snapshot Proof's first element does not match the State metadata.\n // - Snapshot Proof length exceeds Snapshot tree Height.\n // - State index is out of range.\n _verifySnapshotMerkle(att, stateIndex, state, snapProof);\n // This will revert if state does not refer to this chain\n isValidState = IStateHub(origin).isValidState(statePayload);\n if (!isValidState) {\n emit InvalidStateWithAttestation(stateIndex, statePayload, attPayload, attSignature);\n IAgentManager(agentManager).slashAgent(status.domain, notary, msg.sender);\n }\n }\n\n /// @inheritdoc IStatementInbox\n function verifyStateWithSnapshot(uint8 stateIndex, bytes memory snapPayload, bytes memory snapSignature)\n external\n returns (bool isValidState)\n {\n // This will revert if payload is not a snapshot\n Snapshot snapshot = snapPayload.castToSnapshot();\n // This will revert if the snapshot signer is not a known Guard/Notary\n (AgentStatus memory status, address agent) =\n _verifySnapshot({snapshot: snapshot, snapSignature: snapSignature, verifyNotary: false});\n // Agent needs to be Active/Unstaking\n status.verifyActiveUnstaking();\n // This will revert if state does not refer to this chain\n isValidState = IStateHub(origin).isValidState(snapshot.state(stateIndex).unwrap().clone());\n if (!isValidState) {\n emit InvalidStateWithSnapshot(stateIndex, snapPayload, snapSignature);\n IAgentManager(agentManager).slashAgent(status.domain, agent, msg.sender);\n }\n }\n\n /// @inheritdoc IStatementInbox\n function verifyStateReport(bytes memory statePayload, bytes memory srSignature)\n external\n returns (bool isValidReport)\n {\n // This will revert if payload is not a state\n State state = statePayload.castToState();\n // This will revert if the report signer is not a known Guard\n (AgentStatus memory status, address guard) = _verifyStateReport(state, srSignature);\n // Guard needs to be Active/Unstaking\n status.verifyActiveUnstaking();\n // Report is valid IF AND ONLY IF the reported state in invalid\n // This will revert if the reported state does not refer to this chain\n isValidReport = !IStateHub(origin).isValidState(statePayload);\n if (!isValidReport) {\n emit InvalidStateReport(statePayload, srSignature);\n IAgentManager(agentManager).slashAgent(status.domain, guard, msg.sender);\n }\n }\n\n // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════\n\n /// @inheritdoc IStatementInbox\n function getReportsAmount() external view returns (uint256) {\n return _storedReports.length;\n }\n\n /// @inheritdoc IStatementInbox\n function getGuardReport(uint256 index)\n external\n view\n returns (bytes memory statementPayload, bytes memory reportSignature)\n {\n if (index \u003e= _storedReports.length) revert IndexOutOfRange();\n StoredReport memory storedReport = _storedReports[index];\n statementPayload = storedReport.statementPayload;\n reportSignature = _storedSignatures[storedReport.sigIndex];\n }\n\n /// @inheritdoc IStatementInbox\n function getStoredSignature(uint256 index) external view returns (bytes memory) {\n return _storedSignatures[index];\n }\n\n // ══════════════════════════════════════════════ INTERNAL LOGIC ═══════════════════════════════════════════════════\n\n /// @dev Saves the statement reported by Guard as invalid and the Guard Report signature.\n function _saveReport(bytes memory statementPayload, bytes memory reportSignature) internal {\n uint256 sigIndex = _saveSignature(reportSignature);\n _storedReports.push(StoredReport(sigIndex, statementPayload));\n }\n\n /// @dev Saves the signature and returns its index.\n function _saveSignature(bytes memory signature) internal returns (uint256 sigIndex) {\n sigIndex = _storedSignatures.length;\n _storedSignatures.push(signature);\n }\n\n // ═══════════════════════════════════════════════ AGENT CHECKS ════════════════════════════════════════════════════\n\n /**\n * @dev Recovers a signer from a hashed message, and a EIP-191 signature for it.\n * Will revert, if the signer is not a known agent.\n * @dev Agent flag could be any of these: Active/Unstaking/Resting/Fraudulent/Slashed\n * Further checks need to be performed in a caller function.\n * @param hashedStatement Hash of the statement that was signed by an Agent\n * @param signature Agent signature for the hashed statement\n * @return status Struct representing agent status:\n * - flag Unknown/Active/Unstaking/Resting/Fraudulent/Slashed\n * - domain Domain where agent is/was active\n * - index Index of agent in the Agent Merkle Tree\n * @return agent Agent that signed the statement\n */\n function _recoverAgent(bytes32 hashedStatement, bytes memory signature)\n internal\n view\n returns (AgentStatus memory status, address agent)\n {\n bytes32 ethSignedMsg = ECDSA.toEthSignedMessageHash(hashedStatement);\n agent = ECDSA.recover(ethSignedMsg, signature);\n status = IAgentManager(agentManager).agentStatus(agent);\n // Discard signature of unknown agents.\n // Further flag checks are supposed to be performed in a caller function.\n status.verifyKnown();\n }\n\n /// @dev Verifies that Notary signature is active on local domain.\n function _verifyNotaryDomain(uint32 notaryDomain) internal view {\n // Notary needs to be from the local domain (if contract is not deployed on Synapse Chain).\n // Or Notary could be from any domain (if contract is deployed on Synapse Chain).\n if (notaryDomain != localDomain \u0026\u0026 localDomain != synapseDomain) revert IncorrectAgentDomain();\n }\n\n // ════════════════════════════════════════ ATTESTATION RELATED CHECKS ═════════════════════════════════════════════\n\n /**\n * @dev Internal function to verify the signed attestation payload.\n * Reverts if any of these is true:\n * - Attestation signer is not a known Notary.\n * @param att Typed memory view over attestation payload\n * @param attSignature Notary signature for the attestation\n * @return status Struct representing agent status, see {_recoverAgent}\n * @return notary Notary that signed the snapshot\n */\n function _verifyAttestation(Attestation att, bytes memory attSignature)\n internal\n view\n returns (AgentStatus memory status, address notary)\n {\n // This will revert if signer is not a known agent\n (status, notary) = _recoverAgent(att.hashValid(), attSignature);\n // Attestation signer needs to be a Notary, not a Guard\n if (status.domain == 0) revert AgentNotNotary();\n }\n\n /**\n * @dev Internal function to verify the signed attestation report payload.\n * Reverts if any of these is true:\n * - Report signer is not a known Guard.\n * @param att Typed memory view over attestation payload that Guard reports as invalid\n * @param arSignature Guard signature for the \"invalid attestation\" report\n * @return status Struct representing guard status, see {_recoverAgent}\n * @return guard Guard that signed the report\n */\n function _verifyAttestationReport(Attestation att, bytes memory arSignature)\n internal\n view\n returns (AgentStatus memory status, address guard)\n {\n // This will revert if signer is not a known agent\n (status, guard) = _recoverAgent(att.hashInvalid(), arSignature);\n // Report signer needs to be a Guard, not a Notary\n if (status.domain != 0) revert AgentNotGuard();\n }\n\n // ══════════════════════════════════════════ RECEIPT RELATED CHECKS ═══════════════════════════════════════════════\n\n /**\n * @dev Internal function to verify the signed receipt payload.\n * Reverts if any of these is true:\n * - Receipt signer is not a known Notary.\n * @param rcpt Typed memory view over receipt payload\n * @param rcptSignature Notary signature for the receipt\n * @return status Struct representing agent status, see {_recoverAgent}\n * @return notary Notary that signed the snapshot\n */\n function _verifyReceipt(Receipt rcpt, bytes memory rcptSignature)\n internal\n view\n returns (AgentStatus memory status, address notary)\n {\n // This will revert if signer is not a known agent\n (status, notary) = _recoverAgent(rcpt.hashValid(), rcptSignature);\n // Receipt signer needs to be a Notary, not a Guard\n if (status.domain == 0) revert AgentNotNotary();\n }\n\n /**\n * @dev Internal function to verify the signed receipt report payload.\n * Reverts if any of these is true:\n * - Report signer is not a known Guard.\n * @param rcpt Typed memory view over receipt payload that Guard reports as invalid\n * @param rrSignature Guard signature for the \"invalid receipt\" report\n * @return status Struct representing guard status, see {_recoverAgent}\n * @return guard Guard that signed the report\n */\n function _verifyReceiptReport(Receipt rcpt, bytes memory rrSignature)\n internal\n view\n returns (AgentStatus memory status, address guard)\n {\n // This will revert if signer is not a known agent\n (status, guard) = _recoverAgent(rcpt.hashInvalid(), rrSignature);\n // Report signer needs to be a Guard, not a Notary\n if (status.domain != 0) revert AgentNotGuard();\n }\n\n // ═══════════════════════════════════════ STATE/SNAPSHOT RELATED CHECKS ═══════════════════════════════════════════\n\n /**\n * @dev Internal function to verify the signed snapshot report payload.\n * Reverts if any of these is true:\n * - Report signer is not a known Guard.\n * @param state Typed memory view over state payload that Guard reports as invalid\n * @param srSignature Guard signature for the report\n * @return status Struct representing guard status, see {_recoverAgent}\n * @return guard Guard that signed the report\n */\n function _verifyStateReport(State state, bytes memory srSignature)\n internal\n view\n returns (AgentStatus memory status, address guard)\n {\n // This will revert if signer is not a known agent\n (status, guard) = _recoverAgent(state.hashInvalid(), srSignature);\n // Report signer needs to be a Guard, not a Notary\n if (status.domain != 0) revert AgentNotGuard();\n }\n\n /**\n * @dev Internal function to verify the signed snapshot payload.\n * Reverts if any of these is true:\n * - Snapshot signer is not a known Agent.\n * - Snapshot signer is not a Notary (if verifyNotary is true).\n * @param snapshot Typed memory view over snapshot payload\n * @param snapSignature Agent signature for the snapshot\n * @param verifyNotary If true, snapshot signer needs to be a Notary, not a Guard\n * @return status Struct representing agent status, see {_recoverAgent}\n * @return agent Agent that signed the snapshot\n */\n function _verifySnapshot(Snapshot snapshot, bytes memory snapSignature, bool verifyNotary)\n internal\n view\n returns (AgentStatus memory status, address agent)\n {\n // This will revert if signer is not a known agent\n (status, agent) = _recoverAgent(snapshot.hashValid(), snapSignature);\n // If requested, snapshot signer needs to be a Notary, not a Guard\n if (verifyNotary \u0026\u0026 status.domain == 0) revert AgentNotNotary();\n }\n\n // ═══════════════════════════════════════════ MERKLE RELATED CHECKS ═══════════════════════════════════════════════\n\n /**\n * @dev Internal function to verify that snapshot roots match.\n * Reverts if any of these is true:\n * - Attestation root is not equal to Merkle Root derived from State and Snapshot Proof.\n * - Snapshot Proof's first element does not match the State metadata.\n * - Snapshot Proof length exceeds Snapshot tree Height.\n * - State index is out of range.\n * @param att Typed memory view over Attestation\n * @param stateIndex Index of state in the snapshot\n * @param state Typed memory view over the provided state payload\n * @param snapProof Raw payload with snapshot data\n */\n function _verifySnapshotMerkle(Attestation att, uint8 stateIndex, State state, bytes32[] memory snapProof)\n internal\n pure\n {\n // Snapshot proof first element should match State metadata (aka \"right sub-leaf\")\n (, bytes32 rightSubLeaf) = state.subLeafs();\n if (snapProof[0] != rightSubLeaf) revert IncorrectSnapshotProof();\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(state.root(), state.origin(), snapProof, stateIndex);\n // Snapshot root should match the attestation root\n if (att.snapRoot() != snapshotRoot) revert IncorrectSnapshotRoot();\n }\n}\n\n// contracts/inbox/Inbox.sol\n\n// ══════════════════════════════ LIBRARY IMPORTS ══════════════════════════════\n\n// ═════════════════════════════ INTERNAL IMPORTS ══════════════════════════════\n\n/// @notice `Inbox` is the child of `StatementInbox` contract, that is used on Synapse Chain.\n/// In addition to the functionality of `StatementInbox`, it also:\n/// - Accepts Guard and Notary Snapshots and passes them to `Summit` contract.\n/// - Accepts Notary-signed Receipts and passes them to `Summit` contract.\n/// - Accepts Receipt Reports to initiate a dispute between Guard and Notary.\n/// - Verifies Attestations and Attestation Reports, and slashes the signer if they are invalid.\ncontract Inbox is StatementInbox, InboxEvents, InterfaceInbox {\n using AttestationLib for bytes;\n using ReceiptLib for bytes;\n using SnapshotLib for bytes;\n\n // Struct to get around stack too deep error. TODO: revisit this\n struct ReceiptInfo {\n AgentStatus rcptNotaryStatus;\n address notary;\n uint32 attNonce;\n AgentStatus attNotaryStatus;\n }\n\n // ══════════════════════════════════════════════════ STORAGE ══════════════════════════════════════════════════════\n\n // The address of the Summit contract.\n address public summit;\n\n // ═════════════════════════════════════════ CONSTRUCTOR \u0026 INITIALIZER ═════════════════════════════════════════════\n\n constructor(uint32 synapseDomain_) MessagingBase(\"0.0.3\", synapseDomain_) {\n if (localDomain != synapseDomain) revert MustBeSynapseDomain();\n }\n\n /// @notice Initializes `Inbox` contract:\n /// - Sets `msg.sender` as the owner of the contract\n /// - Sets `agentManager`, `origin`, `destination` and `summit` addresses\n function initialize(address agentManager_, address origin_, address destination_, address summit_)\n external\n initializer\n {\n __StatementInbox_init(agentManager_, origin_, destination_);\n summit = summit_;\n }\n\n // ══════════════════════════════════════════ SUBMIT AGENT STATEMENTS ══════════════════════════════════════════════\n\n /// @inheritdoc InterfaceInbox\n function submitSnapshot(bytes memory snapPayload, bytes memory snapSignature)\n external\n returns (bytes memory attPayload, bytes32 agentRoot_, uint256[] memory snapGas)\n {\n // This will revert if payload is not a snapshot\n Snapshot snapshot = snapPayload.castToSnapshot();\n // This will revert if the signer is not a known Guard/Notary\n (AgentStatus memory status, address agent) =\n _verifySnapshot({snapshot: snapshot, snapSignature: snapSignature, verifyNotary: false});\n // Check that Agent is active\n status.verifyActive();\n // Store Agent signature for the Snapshot\n uint256 sigIndex = _saveSignature(snapSignature);\n if (status.domain == 0) {\n // Guard that is in Dispute could still submit new snapshots, so we don't check that\n InterfaceSummit(summit).acceptGuardSnapshot({\n guardIndex: status.index,\n sigIndex: sigIndex,\n snapPayload: snapPayload\n });\n } else {\n // Get current agentRoot from AgentManager\n agentRoot_ = IAgentManager(agentManager).agentRoot();\n // This will revert if Notary is in Dispute\n attPayload = InterfaceSummit(summit).acceptNotarySnapshot({\n notaryIndex: status.index,\n sigIndex: sigIndex,\n agentRoot: agentRoot_,\n snapPayload: snapPayload\n });\n ChainGas[] memory snapGas_ = snapshot.snapGas();\n // Pass created attestation to Destination to enable executing messages coming to Synapse Chain\n InterfaceDestination(destination).acceptAttestation(\n status.index, type(uint256).max, attPayload, agentRoot_, snapGas_\n );\n // Use assembly to cast ChainGas[] to uint256[] without copying. Highest bits are left zeroed.\n // solhint-disable-next-line no-inline-assembly\n assembly {\n snapGas := snapGas_\n }\n }\n emit SnapshotAccepted(status.domain, agent, snapPayload, snapSignature);\n }\n\n /// @inheritdoc InterfaceInbox\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 // Struct to get around stack too deep error.\n ReceiptInfo memory info;\n // This will revert if payload is not a receipt\n Receipt rcpt = rcptPayload.castToReceipt();\n // This will revert if the receipt signer is not a known Notary\n (info.rcptNotaryStatus, info.notary) = _verifyReceipt(rcpt, rcptSignature);\n // Receipt Notary needs to be Active\n info.rcptNotaryStatus.verifyActive();\n info.attNonce = IExecutionHub(destination).getAttestationNonce(rcpt.snapshotRoot());\n if (info.attNonce == 0) revert IncorrectSnapshotRoot();\n // Attestation Notary domain needs to match the destination domain\n info.attNotaryStatus = IAgentManager(agentManager).agentStatus(rcpt.attNotary());\n if (info.attNotaryStatus.domain != rcpt.destination()) revert IncorrectAgentDomain();\n // Check that the correct tip values for the message were provided\n _verifyReceiptTips(rcpt.messageHash(), paddedTips, headerHash, bodyHash);\n // Store Notary signature for the Receipt\n uint256 sigIndex = _saveSignature(rcptSignature);\n // This will revert if Receipt Notary is in Dispute\n wasAccepted = InterfaceSummit(summit).acceptReceipt({\n rcptNotaryIndex: info.rcptNotaryStatus.index,\n attNotaryIndex: info.attNotaryStatus.index,\n sigIndex: sigIndex,\n attNonce: info.attNonce,\n paddedTips: paddedTips,\n rcptPayload: rcptPayload\n });\n if (wasAccepted) {\n emit ReceiptAccepted(info.rcptNotaryStatus.domain, info.notary, rcptPayload, rcptSignature);\n }\n }\n\n /// @inheritdoc InterfaceInbox\n function submitReceiptReport(bytes memory rcptPayload, bytes memory rcptSignature, bytes memory rrSignature)\n external\n returns (bool wasAccepted)\n {\n // This will revert if payload is not a receipt\n Receipt rcpt = rcptPayload.castToReceipt();\n // This will revert if the receipt signer is not a known Guard\n (AgentStatus memory guardStatus,) = _verifyReceiptReport(rcpt, rrSignature);\n // Guard needs to be Active\n guardStatus.verifyActive();\n // This will revert if report signer is not a known Notary\n (AgentStatus memory notaryStatus,) = _verifyReceipt(rcpt, rcptSignature);\n // Notary needs to be Active/Unstaking\n notaryStatus.verifyActiveUnstaking();\n _saveReport(rcptPayload, rrSignature);\n // This will revert if either actor is already in dispute\n IAgentManager(agentManager).openDispute(guardStatus.index, notaryStatus.index);\n return true;\n }\n\n /// @inheritdoc InterfaceInbox\n function passReceipt(uint32 attNotaryIndex, uint32 attNonce, uint256 paddedTips, bytes memory rcptPayload)\n external\n returns (bool wasAccepted)\n {\n // Only Destination can pass receipts\n if (msg.sender != destination) revert CallerNotDestination();\n return InterfaceSummit(summit).acceptReceipt({\n rcptNotaryIndex: attNotaryIndex,\n attNotaryIndex: attNotaryIndex,\n sigIndex: type(uint256).max,\n attNonce: attNonce,\n paddedTips: paddedTips,\n rcptPayload: rcptPayload\n });\n }\n\n // ══════════════════════════════════════════ VERIFY AGENT STATEMENTS ══════════════════════════════════════════════\n\n /// @inheritdoc InterfaceInbox\n function verifyAttestation(bytes memory attPayload, bytes memory attSignature)\n external\n returns (bool isValidAttestation)\n {\n // This will revert if payload is not an attestation\n Attestation att = attPayload.castToAttestation();\n // This will revert if the attestation signer is not a known Notary\n (AgentStatus memory status, address notary) = _verifyAttestation(att, attSignature);\n // Notary needs to be Active/Unstaking\n status.verifyActiveUnstaking();\n isValidAttestation = ISnapshotHub(summit).isValidAttestation(attPayload);\n if (!isValidAttestation) {\n emit InvalidAttestation(attPayload, attSignature);\n IAgentManager(agentManager).slashAgent(status.domain, notary, msg.sender);\n }\n }\n\n /// @inheritdoc InterfaceInbox\n function verifyAttestationReport(bytes memory attPayload, bytes memory arSignature)\n external\n returns (bool isValidReport)\n {\n // This will revert if payload is not an attestation\n Attestation att = attPayload.castToAttestation();\n // This will revert if the report signer is not a known Guard\n (AgentStatus memory status, address guard) = _verifyAttestationReport(att, arSignature);\n // Guard needs to be Active/Unstaking\n status.verifyActiveUnstaking();\n // Report is valid IF AND ONLY IF the reported attestation in invalid\n isValidReport = !ISnapshotHub(summit).isValidAttestation(attPayload);\n if (!isValidReport) {\n emit InvalidAttestationReport(attPayload, arSignature);\n IAgentManager(agentManager).slashAgent(status.domain, guard, msg.sender);\n }\n }\n\n // ══════════════════════════════════════════════ INTERNAL VIEWS ═══════════════════════════════════════════════════\n\n /// @dev Verifies that tips proof matches the message hash.\n function _verifyReceiptTips(bytes32 msgHash, uint256 paddedTips, bytes32 headerHash, bytes32 bodyHash)\n internal\n pure\n {\n Tips tips = TipsLib.wrapPadded(paddedTips);\n // full message leaf is (header, baseMessage), while base message leaf is (tips, remainingBody).\n if (MerkleMath.getParent(headerHash, MerkleMath.getParent(tips.leaf(), bodyHash)) != msgHash) {\n revert IncorrectTipsProof();\n }\n }\n}\n","language":"Solidity","languageVersion":"0.8.17","compilerVersion":"0.8.17","compilerOptions":"--combined-json bin,bin-runtime,srcmap,srcmap-runtime,abi,userdoc,devdoc,metadata,hashes --optimize --optimize-runs 10000 --allow-paths ., ./, ../","srcMap":"189098:5436:0:-:0;;;;;;;;;;;;;;;-1:-1:-1;;;189098:5436:0;;;;;;;;;;;;;;;;;","srcMapRuntime":"189098: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/Inbox.sol\":\"AttestationLib\"},\"evmVersion\":\"london\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\"},\"optimizer\":{\"enabled\":true,\"runs\":10000},\"remappings\":[]},\"sources\":{\"solidity/Inbox.sol\":{\"keccak256\":\"0x9b516081a036814c0169e20e484d4a5499066b7a6f48fada952b5e844a1ca3e5\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://32bde393b3f24ef4307d9626d4143f337b3c0bd34e17bb969fd5a15221d96987\",\"dweb:/ipfs/QmTkt2XZRtgsbSpmsVQUM3c4ebETQoDVYbmEV9yheBghnr\"]}},\"version\":1}"},"hashes":{}},"solidity/Inbox.sol:ChainContext":{"code":"0x60566037600b82828239805160001a607314602a57634e487b7160e01b600052600060045260246000fd5b30600052607381538281f3fe73000000000000000000000000000000000000000030146080604052600080fdfea2646970667358221220e407b1759f89a270c3eb53de8815450ae7ebb86d83757c131af43f0af3b7902664736f6c63430008110033","runtime-code":"0x73000000000000000000000000000000000000000030146080604052600080fdfea2646970667358221220e407b1759f89a270c3eb53de8815450ae7ebb86d83757c131af43f0af3b7902664736f6c63430008110033","info":{"source":"// SPDX-License-Identifier: MIT\npragma solidity =0.8.17 ^0.8.0 ^0.8.1 ^0.8.2;\n\n// contracts/events/InboxEvents.sol\n\nabstract contract InboxEvents {\n /**\n * @notice Emitted when a snapshot is accepted by the Summit contract.\n * @param domain Domain where the signed Agent is active (ZERO for Guards)\n * @param agent Agent who signed the snapshot\n * @param snapPayload Raw payload with snapshot data\n * @param snapSignature Agent signature for the snapshot\n */\n event SnapshotAccepted(uint32 indexed domain, address indexed agent, bytes snapPayload, bytes snapSignature);\n\n /**\n * @notice Emitted when a snapshot is accepted by the Summit contract.\n * @param domain Domain where the signed Notary is active\n * @param notary Notary who signed the attestation\n * @param rcptPayload Raw payload with receipt data\n * @param rcptSignature Notary signature for the receipt\n */\n event ReceiptAccepted(uint32 domain, address notary, bytes rcptPayload, bytes rcptSignature);\n\n /**\n * @notice Emitted when a proof of invalid attestation is submitted.\n * @param attPayload Raw payload with Attestation data\n * @param attSignature Notary signature for the attestation\n */\n event InvalidAttestation(bytes attPayload, bytes attSignature);\n\n /**\n * @notice Emitted when a proof of invalid attestation report is submitted.\n * @param arPayload Raw payload with report data\n * @param arSignature Guard signature for the report\n */\n event InvalidAttestationReport(bytes arPayload, bytes arSignature);\n}\n\n// contracts/events/StatementInboxEvents.sol\n\nabstract contract StatementInboxEvents {\n // ════════════════════════════════════════════ STATEMENT ACCEPTED ═════════════════════════════════════════════════\n\n /**\n * @notice Emitted when a snapshot is accepted by the Destination contract.\n * @param domain Domain where the signed Notary is active\n * @param notary Notary who signed the attestation\n * @param attPayload Raw payload with attestation data\n * @param attSignature Notary signature for the attestation\n */\n event AttestationAccepted(uint32 domain, address notary, bytes attPayload, bytes attSignature);\n\n // ═════════════════════════════════════════ INVALID STATEMENT PROVED ══════════════════════════════════════════════\n\n /**\n * @notice Emitted when a proof of invalid receipt statement is submitted.\n * @param rcptPayload Raw payload with the receipt statement\n * @param rcptSignature Notary signature for the receipt statement\n */\n event InvalidReceipt(bytes rcptPayload, bytes rcptSignature);\n\n /**\n * @notice Emitted when a proof of invalid receipt report is submitted.\n * @param rrPayload Raw payload with report data\n * @param rrSignature Guard signature for the report\n */\n event InvalidReceiptReport(bytes rrPayload, bytes rrSignature);\n\n /**\n * @notice Emitted when a proof of invalid state in the signed attestation is submitted.\n * @param stateIndex Index of invalid state in the snapshot\n * @param statePayload Raw payload with state data\n * @param attPayload Raw payload with Attestation data for snapshot\n * @param attSignature Notary signature for the attestation\n */\n event InvalidStateWithAttestation(uint8 stateIndex, bytes statePayload, bytes attPayload, bytes attSignature);\n\n /**\n * @notice Emitted when a proof of invalid state in the signed snapshot is submitted.\n * @param stateIndex Index of invalid state in the snapshot\n * @param snapPayload Raw payload with snapshot data\n * @param snapSignature Agent signature for the snapshot\n */\n event InvalidStateWithSnapshot(uint8 stateIndex, bytes snapPayload, bytes snapSignature);\n\n /**\n * @notice Emitted when a proof of invalid state report is submitted.\n * @param srPayload Raw payload with report data\n * @param srSignature Guard signature for the report\n */\n event InvalidStateReport(bytes srPayload, bytes srSignature);\n}\n\n// contracts/interfaces/ISnapshotHub.sol\n\ninterface ISnapshotHub {\n /**\n * @notice Check that a given attestation is valid: matches the historical attestation\n * derived from an accepted Notary snapshot.\n * @dev Will revert if any of these is true:\n * - Attestation payload is not properly formatted.\n * @param attPayload Raw payload with attestation data\n * @return isValid Whether the provided attestation is valid\n */\n function isValidAttestation(bytes memory attPayload) external view returns (bool isValid);\n\n /**\n * @notice Returns saved attestation with the given nonce.\n * @dev Reverts if attestation with given nonce hasn't been created yet.\n * @param attNonce Nonce for the attestation\n * @return attPayload Raw payload with formatted Attestation data\n * @return agentRoot Agent root hash used for the attestation\n * @return snapGas Snapshot gas data used for the attestation\n */\n function getAttestation(uint32 attNonce)\n external\n view\n returns (bytes memory attPayload, bytes32 agentRoot, uint256[] memory snapGas);\n\n /**\n * @notice Returns the state with the highest known nonce submitted by a given Agent.\n * @param origin Domain of origin chain\n * @param agent Agent address\n * @return statePayload Raw payload with agent's latest state for origin\n */\n function getLatestAgentState(uint32 origin, address agent) external view returns (bytes memory statePayload);\n\n /**\n * @notice Returns latest saved attestation for a Notary.\n * @param notary Notary address\n * @return attPayload Raw payload with formatted Attestation data\n * @return agentRoot Agent root hash used for the attestation\n * @return snapGas Snapshot gas data used for the attestation\n */\n function getLatestNotaryAttestation(address notary)\n external\n view\n returns (bytes memory attPayload, bytes32 agentRoot, uint256[] memory snapGas);\n\n /**\n * @notice Returns Guard snapshot from the list of all accepted Guard snapshots.\n * @dev Reverts if snapshot with given index hasn't been accepted yet.\n * @param index Snapshot index in the list of all Guard snapshots\n * @return snapPayload Raw payload with Guard snapshot\n * @return snapSignature Raw payload with Guard signature for snapshot\n */\n function getGuardSnapshot(uint256 index)\n external\n view\n returns (bytes memory snapPayload, bytes memory snapSignature);\n\n /**\n * @notice Returns Notary snapshot from the list of all accepted Guard snapshots.\n * @dev Reverts if snapshot with given index hasn't been accepted yet.\n * @param index Snapshot index in the list of all Notary snapshots\n * @return snapPayload Raw payload with Notary snapshot\n * @return snapSignature Raw payload with Notary signature for snapshot\n */\n function getNotarySnapshot(uint256 index)\n external\n view\n returns (bytes memory snapPayload, bytes memory snapSignature);\n\n /**\n * @notice Returns Notary snapshot that was used for creating a given attestation.\n * @dev Reverts if any of these is true:\n * - Attestation payload is not properly formatted.\n * - Attestation is invalid (doesn't have a matching Notary snapshot).\n * @param attPayload Raw payload with attestation data\n * @return snapPayload Raw payload with Notary snapshot\n * @return snapSignature Raw payload with Notary signature for snapshot\n */\n function getNotarySnapshot(bytes memory attPayload)\n external\n view\n returns (bytes memory snapPayload, bytes memory snapSignature);\n\n /**\n * @notice Returns proof of inclusion of (root, origin) fields of a given snapshot's state\n * into the Snapshot Merkle Tree for a given attestation.\n * @dev Reverts if any of these is true:\n * - Attestation with given nonce hasn't been created yet.\n * - State index is out of range of snapshot list.\n * @param attNonce Nonce for the attestation\n * @param stateIndex Index of state in the attestation's snapshot\n * @return snapProof The snapshot proof\n */\n function getSnapshotProof(uint32 attNonce, uint8 stateIndex) external view returns (bytes32[] memory snapProof);\n}\n\n// contracts/interfaces/IStateHub.sol\n\ninterface IStateHub {\n /**\n * @notice Check that a given state is valid: matches the historical state of Origin contract.\n * Note: any Agent including an invalid state in their snapshot will be slashed\n * upon providing the snapshot and agent signature for it to Origin contract.\n * @dev Will revert if any of these is true:\n * - State payload is not properly formatted.\n * @param statePayload Raw payload with state data\n * @return isValid Whether the provided state is valid\n */\n function isValidState(bytes memory statePayload) external view returns (bool isValid);\n\n /**\n * @notice Returns the amount of saved states so far.\n * @dev This includes the initial state of \"empty Origin Merkle Tree\".\n */\n function statesAmount() external view returns (uint256);\n\n /**\n * @notice Suggest the data (state after latest sent message) to sign for an Agent.\n * Note: signing the suggested state data will will never lead to slashing of the actor,\n * assuming they have confirmed that the block, which number is included in the data,\n * is not subject to reorganization (which is different for every observed chain).\n * @return statePayload Raw payload with the latest state data\n */\n function suggestLatestState() external view returns (bytes memory statePayload);\n\n /**\n * @notice Given the historical nonce, suggest the state data to sign for an Agent.\n * Note: signing the suggested state data will will never lead to slashing of the actor,\n * assuming they have confirmed that the block, which number is included in the data,\n * is not subject to reorganization (which is different for every observed chain).\n * @param nonce Historical nonce to form a state\n * @return statePayload Raw payload with historical state data\n */\n function suggestState(uint32 nonce) external view returns (bytes memory statePayload);\n}\n\n// contracts/interfaces/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/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// node_modules/@openzeppelin/contracts/utils/math/Math.sol\n\n// OpenZeppelin Contracts (last updated v4.9.0) (utils/math/Math.sol)\n\n/**\n * @dev Standard math utilities missing in the Solidity language.\n */\nlibrary Math {\n enum Rounding {\n Down, // Toward negative infinity\n Up, // Toward infinity\n Zero // Toward zero\n }\n\n /**\n * @dev Returns the largest of two numbers.\n */\n function max(uint256 a, uint256 b) internal pure returns (uint256) {\n return a \u003e b ? a : b;\n }\n\n /**\n * @dev Returns the smallest of two numbers.\n */\n function min(uint256 a, uint256 b) internal pure returns (uint256) {\n return a \u003c b ? a : b;\n }\n\n /**\n * @dev Returns the average of two numbers. The result is rounded towards\n * zero.\n */\n function average(uint256 a, uint256 b) internal pure returns (uint256) {\n // (a + b) / 2 can overflow.\n return (a \u0026 b) + (a ^ b) / 2;\n }\n\n /**\n * @dev Returns the ceiling of the division of two numbers.\n *\n * This differs from standard division with `/` in that it rounds up instead\n * of rounding down.\n */\n function ceilDiv(uint256 a, uint256 b) internal pure returns (uint256) {\n // (a + b - 1) / b can overflow on addition, so we distribute.\n return a == 0 ? 0 : (a - 1) / b + 1;\n }\n\n /**\n * @notice Calculates floor(x * y / denominator) with full precision. Throws if result overflows a uint256 or denominator == 0\n * @dev Original credit to Remco Bloemen under MIT license (https://xn--2-umb.com/21/muldiv)\n * with further edits by Uniswap Labs also under MIT license.\n */\n function mulDiv(uint256 x, uint256 y, uint256 denominator) internal pure returns (uint256 result) {\n unchecked {\n // 512-bit multiply [prod1 prod0] = x * y. Compute the product mod 2^256 and mod 2^256 - 1, then use\n // use the Chinese Remainder Theorem to reconstruct the 512 bit result. The result is stored in two 256\n // variables such that product = prod1 * 2^256 + prod0.\n uint256 prod0; // Least significant 256 bits of the product\n uint256 prod1; // Most significant 256 bits of the product\n assembly {\n let mm := mulmod(x, y, not(0))\n prod0 := mul(x, y)\n prod1 := sub(sub(mm, prod0), lt(mm, prod0))\n }\n\n // Handle non-overflow cases, 256 by 256 division.\n if (prod1 == 0) {\n // Solidity will revert if denominator == 0, unlike the div opcode on its own.\n // The surrounding unchecked block does not change this fact.\n // See https://docs.soliditylang.org/en/latest/control-structures.html#checked-or-unchecked-arithmetic.\n return prod0 / denominator;\n }\n\n // Make sure the result is less than 2^256. Also prevents denominator == 0.\n require(denominator \u003e prod1, \"Math: mulDiv overflow\");\n\n ///////////////////////////////////////////////\n // 512 by 256 division.\n ///////////////////////////////////////////////\n\n // Make division exact by subtracting the remainder from [prod1 prod0].\n uint256 remainder;\n assembly {\n // Compute remainder using mulmod.\n remainder := mulmod(x, y, denominator)\n\n // Subtract 256 bit number from 512 bit number.\n prod1 := sub(prod1, gt(remainder, prod0))\n prod0 := sub(prod0, remainder)\n }\n\n // Factor powers of two out of denominator and compute largest power of two divisor of denominator. Always \u003e= 1.\n // See https://cs.stackexchange.com/q/138556/92363.\n\n // Does not overflow because the denominator cannot be zero at this stage in the function.\n uint256 twos = denominator \u0026 (~denominator + 1);\n assembly {\n // Divide denominator by twos.\n denominator := div(denominator, twos)\n\n // Divide [prod1 prod0] by twos.\n prod0 := div(prod0, twos)\n\n // Flip twos such that it is 2^256 / twos. If twos is zero, then it becomes one.\n twos := add(div(sub(0, twos), twos), 1)\n }\n\n // Shift in bits from prod1 into prod0.\n prod0 |= prod1 * twos;\n\n // Invert denominator mod 2^256. Now that denominator is an odd number, it has an inverse modulo 2^256 such\n // that denominator * inv = 1 mod 2^256. Compute the inverse by starting with a seed that is correct for\n // four bits. That is, denominator * inv = 1 mod 2^4.\n uint256 inverse = (3 * denominator) ^ 2;\n\n // Use the Newton-Raphson iteration to improve the precision. Thanks to Hensel's lifting lemma, this also works\n // in modular arithmetic, doubling the correct bits in each step.\n inverse *= 2 - denominator * inverse; // inverse mod 2^8\n inverse *= 2 - denominator * inverse; // inverse mod 2^16\n inverse *= 2 - denominator * inverse; // inverse mod 2^32\n inverse *= 2 - denominator * inverse; // inverse mod 2^64\n inverse *= 2 - denominator * inverse; // inverse mod 2^128\n inverse *= 2 - denominator * inverse; // inverse mod 2^256\n\n // Because the division is now exact we can divide by multiplying with the modular inverse of denominator.\n // This will give us the correct result modulo 2^256. Since the preconditions guarantee that the outcome is\n // less than 2^256, this is the final result. We don't need to compute the high bits of the result and prod1\n // is no longer required.\n result = prod0 * inverse;\n return result;\n }\n }\n\n /**\n * @notice Calculates x * y / denominator with full precision, following the selected rounding direction.\n */\n function mulDiv(uint256 x, uint256 y, uint256 denominator, Rounding rounding) internal pure returns (uint256) {\n uint256 result = mulDiv(x, y, denominator);\n if (rounding == Rounding.Up \u0026\u0026 mulmod(x, y, denominator) \u003e 0) {\n result += 1;\n }\n return result;\n }\n\n /**\n * @dev Returns the square root of a number. If the number is not a perfect square, the value is rounded down.\n *\n * Inspired by Henry S. Warren, Jr.'s \"Hacker's Delight\" (Chapter 11).\n */\n function sqrt(uint256 a) internal pure returns (uint256) {\n if (a == 0) {\n return 0;\n }\n\n // For our first guess, we get the biggest power of 2 which is smaller than the square root of the target.\n //\n // We know that the \"msb\" (most significant bit) of our target number `a` is a power of 2 such that we have\n // `msb(a) \u003c= a \u003c 2*msb(a)`. This value can be written `msb(a)=2**k` with `k=log2(a)`.\n //\n // This can be rewritten `2**log2(a) \u003c= a \u003c 2**(log2(a) + 1)`\n // → `sqrt(2**k) \u003c= sqrt(a) \u003c sqrt(2**(k+1))`\n // → `2**(k/2) \u003c= sqrt(a) \u003c 2**((k+1)/2) \u003c= 2**(k/2 + 1)`\n //\n // Consequently, `2**(log2(a) / 2)` is a good first approximation of `sqrt(a)` with at least 1 correct bit.\n uint256 result = 1 \u003c\u003c (log2(a) \u003e\u003e 1);\n\n // At this point `result` is an estimation with one bit of precision. We know the true value is a uint128,\n // since it is the square root of a uint256. Newton's method converges quadratically (precision doubles at\n // every iteration). We thus need at most 7 iteration to turn our partial result with one bit of precision\n // into the expected uint128 result.\n unchecked {\n result = (result + a / result) \u003e\u003e 1;\n result = (result + a / result) \u003e\u003e 1;\n result = (result + a / result) \u003e\u003e 1;\n result = (result + a / result) \u003e\u003e 1;\n result = (result + a / result) \u003e\u003e 1;\n result = (result + a / result) \u003e\u003e 1;\n result = (result + a / result) \u003e\u003e 1;\n return min(result, a / result);\n }\n }\n\n /**\n * @notice Calculates sqrt(a), following the selected rounding direction.\n */\n function sqrt(uint256 a, Rounding rounding) internal pure returns (uint256) {\n unchecked {\n uint256 result = sqrt(a);\n return result + (rounding == Rounding.Up \u0026\u0026 result * result \u003c a ? 1 : 0);\n }\n }\n\n /**\n * @dev Return the log in base 2, rounded down, of a positive value.\n * Returns 0 if given 0.\n */\n function log2(uint256 value) internal pure returns (uint256) {\n uint256 result = 0;\n unchecked {\n if (value \u003e\u003e 128 \u003e 0) {\n value \u003e\u003e= 128;\n result += 128;\n }\n if (value \u003e\u003e 64 \u003e 0) {\n value \u003e\u003e= 64;\n result += 64;\n }\n if (value \u003e\u003e 32 \u003e 0) {\n value \u003e\u003e= 32;\n result += 32;\n }\n if (value \u003e\u003e 16 \u003e 0) {\n value \u003e\u003e= 16;\n result += 16;\n }\n if (value \u003e\u003e 8 \u003e 0) {\n value \u003e\u003e= 8;\n result += 8;\n }\n if (value \u003e\u003e 4 \u003e 0) {\n value \u003e\u003e= 4;\n result += 4;\n }\n if (value \u003e\u003e 2 \u003e 0) {\n value \u003e\u003e= 2;\n result += 2;\n }\n if (value \u003e\u003e 1 \u003e 0) {\n result += 1;\n }\n }\n return result;\n }\n\n /**\n * @dev Return the log in base 2, following the selected rounding direction, of a positive value.\n * Returns 0 if given 0.\n */\n function log2(uint256 value, Rounding rounding) internal pure returns (uint256) {\n unchecked {\n uint256 result = log2(value);\n return result + (rounding == Rounding.Up \u0026\u0026 1 \u003c\u003c result \u003c value ? 1 : 0);\n }\n }\n\n /**\n * @dev Return the log in base 10, rounded down, of a positive value.\n * Returns 0 if given 0.\n */\n function log10(uint256 value) internal pure returns (uint256) {\n uint256 result = 0;\n unchecked {\n if (value \u003e= 10 ** 64) {\n value /= 10 ** 64;\n result += 64;\n }\n if (value \u003e= 10 ** 32) {\n value /= 10 ** 32;\n result += 32;\n }\n if (value \u003e= 10 ** 16) {\n value /= 10 ** 16;\n result += 16;\n }\n if (value \u003e= 10 ** 8) {\n value /= 10 ** 8;\n result += 8;\n }\n if (value \u003e= 10 ** 4) {\n value /= 10 ** 4;\n result += 4;\n }\n if (value \u003e= 10 ** 2) {\n value /= 10 ** 2;\n result += 2;\n }\n if (value \u003e= 10 ** 1) {\n result += 1;\n }\n }\n return result;\n }\n\n /**\n * @dev Return the log in base 10, following the selected rounding direction, of a positive value.\n * Returns 0 if given 0.\n */\n function log10(uint256 value, Rounding rounding) internal pure returns (uint256) {\n unchecked {\n uint256 result = log10(value);\n return result + (rounding == Rounding.Up \u0026\u0026 10 ** result \u003c value ? 1 : 0);\n }\n }\n\n /**\n * @dev Return the log in base 256, rounded down, of a positive value.\n * Returns 0 if given 0.\n *\n * Adding one to the result gives the number of pairs of hex symbols needed to represent `value` as a hex string.\n */\n function log256(uint256 value) internal pure returns (uint256) {\n uint256 result = 0;\n unchecked {\n if (value \u003e\u003e 128 \u003e 0) {\n value \u003e\u003e= 128;\n result += 16;\n }\n if (value \u003e\u003e 64 \u003e 0) {\n value \u003e\u003e= 64;\n result += 8;\n }\n if (value \u003e\u003e 32 \u003e 0) {\n value \u003e\u003e= 32;\n result += 4;\n }\n if (value \u003e\u003e 16 \u003e 0) {\n value \u003e\u003e= 16;\n result += 2;\n }\n if (value \u003e\u003e 8 \u003e 0) {\n result += 1;\n }\n }\n return result;\n }\n\n /**\n * @dev Return the log in base 256, following the selected rounding direction, of a positive value.\n * Returns 0 if given 0.\n */\n function log256(uint256 value, Rounding rounding) internal pure returns (uint256) {\n unchecked {\n uint256 result = log256(value);\n return result + (rounding == Rounding.Up \u0026\u0026 1 \u003c\u003c (result \u003c\u003c 3) \u003c value ? 1 : 0);\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/utils/math/SignedMath.sol\n\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/math/SignedMath.sol)\n\n/**\n * @dev Standard signed math utilities missing in the Solidity language.\n */\nlibrary SignedMath {\n /**\n * @dev Returns the largest of two signed numbers.\n */\n function max(int256 a, int256 b) internal pure returns (int256) {\n return a \u003e b ? a : b;\n }\n\n /**\n * @dev Returns the smallest of two signed numbers.\n */\n function min(int256 a, int256 b) internal pure returns (int256) {\n return a \u003c b ? a : b;\n }\n\n /**\n * @dev Returns the average of two signed numbers without overflow.\n * The result is rounded towards zero.\n */\n function average(int256 a, int256 b) internal pure returns (int256) {\n // Formula from the book \"Hacker's Delight\"\n int256 x = (a \u0026 b) + ((a ^ b) \u003e\u003e 1);\n return x + (int256(uint256(x) \u003e\u003e 255) \u0026 (a ^ b));\n }\n\n /**\n * @dev Returns the absolute unsigned value of a signed value.\n */\n function abs(int256 n) internal pure returns (uint256) {\n unchecked {\n // must be unchecked in order to support `n = type(int256).min`\n return uint256(n \u003e= 0 ? n : -n);\n }\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// 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/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/InterfaceSummit.sol\n\ninterface InterfaceSummit {\n // ══════════════════════════════════════════ ACCEPT AGENT STATEMENTS ══════════════════════════════════════════════\n\n /**\n * @notice Accepts a receipt, which local `AgentManager` verified to have been signed by an active Notary.\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 * - Notary who signed the receipt is referenced as the \"Receipt Notary\".\n * - Notary who signed the attestation on destination chain is referenced as the \"Attestation Notary\".\n * \u003e Will revert if any of these is true:\n * \u003e - Called by anyone other than local `AgentManager`.\n * \u003e - Receipt body payload is not properly formatted.\n * \u003e - Receipt signer is in Dispute.\n * \u003e - Receipt's snapshot root is unknown.\n * @param rcptNotaryIndex Index of Receipt Notary in Agent Merkle Tree\n * @param attNotaryIndex Index of Attestation Notary in Agent Merkle Tree\n * @param sigIndex Index of stored Notary signature\n * @param attNonce Nonce of the attestation used for proving the executed message\n * @param paddedTips Padded encoded paid tips information\n * @param rcptPayload Raw payload with message execution receipt\n * @return wasAccepted Whether the receipt was accepted\n */\n function acceptReceipt(\n uint32 rcptNotaryIndex,\n uint32 attNotaryIndex,\n uint256 sigIndex,\n uint32 attNonce,\n uint256 paddedTips,\n bytes memory rcptPayload\n ) external returns (bool wasAccepted);\n\n /**\n * @notice Accepts a snapshot, which local `AgentManager` verified to have been signed by an active Guard.\n * \u003e Snapshot is a list of states for a set of Origin contracts residing on any of the chains.\n * All the states in the Guard-signed snapshot become available for Notary signing.\n * \u003e Will revert if any of these is true:\n * \u003e - Called by anyone other than local `AgentManager`.\n * \u003e - Snapshot payload is not properly formatted.\n * \u003e - Snapshot contains a state older then the Guard has previously submitted.\n * @param guardIndex Index of Guard in Agent Merkle Tree\n * @param sigIndex Index of stored Agent signature\n * @param snapPayload Raw payload with snapshot data\n */\n function acceptGuardSnapshot(uint32 guardIndex, uint256 sigIndex, bytes memory snapPayload) external;\n\n /**\n * @notice Accepts a snapshot, which local `AgentManager` verified to have been signed by an active Notary.\n * \u003e Snapshot is a list of states for a set of Origin contracts residing on any of the chains.\n * Snapshot Merkle Root is calculated and saved for valid snapshots, i.e.\n * snapshots which are only using states previously submitted by any of the Guards.\n * - Notary could use states singed by the same of different Guards 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 - Called by anyone other than local `AgentManager`.\n * \u003e - Snapshot payload is not properly formatted.\n * \u003e - Snapshot contains a state older then the Notary has previously submitted.\n * \u003e - Snapshot contains a state that no Guard has previously submitted.\n * @param notaryIndex Index of Notary in Agent Merkle Tree\n * @param sigIndex Index of stored Agent signature\n * @param agentRoot Current root of the Agent Merkle Tree\n * @param snapPayload Raw payload with snapshot data\n * @return attPayload Raw payload with data for attestation derived from Notary snapshot.\n */\n function acceptNotarySnapshot(uint32 notaryIndex, uint256 sigIndex, bytes32 agentRoot, bytes memory snapPayload)\n external\n returns (bytes memory attPayload);\n\n // ════════════════════════════════════════════════ TIPS LOGIC ═════════════════════════════════════════════════════\n\n /**\n * @notice Distributes tips using the first Receipt from the \"receipt quarantine queue\".\n * Possible scenarios:\n * - Receipt queue is empty =\u003e does nothing\n * - Receipt optimistic period is not over =\u003e does nothing\n * - Either of Notaries present in Receipt was slashed =\u003e receipt is deleted from the queue\n * - Either of Notaries present in Receipt in Dispute =\u003e receipt is moved to the end of queue\n * - None of the above =\u003e receipt tips are distributed\n * @dev Returned value makes it possible to do the following: `while (distributeTips()) {}`\n * @return queuePopped Whether the first element was popped from the queue\n */\n function distributeTips() external returns (bool queuePopped);\n\n /**\n * @notice Withdraws locked base message tips from requested domain Origin to the recipient.\n * This is done by a call to a local Origin contract, or by a manager message to the remote chain.\n * @dev This will revert, if the pending balance of origin tips (earned-claimed) is lower than requested.\n * @param origin Domain of chain to withdraw tips on\n * @param amount Amount of tips to withdraw\n */\n function withdrawTips(uint32 origin, uint256 amount) external;\n\n // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════\n\n /**\n * @notice Returns earned and claimed tips for the actor.\n * Note: Tips for address(0) belong to the Treasury.\n * @param actor Address of the actor\n * @param origin Domain where the tips were initially paid\n * @return earned Total amount of origin tips the actor has earned so far\n * @return claimed Total amount of origin tips the actor has claimed so far\n */\n function actorTips(address actor, uint32 origin) external view returns (uint128 earned, uint128 claimed);\n\n /**\n * @notice Returns the amount of receipts in the \"Receipt Quarantine Queue\".\n */\n function receiptQueueLength() external view returns (uint256);\n\n /**\n * @notice Returns the state with the highest known nonce\n * submitted by any of the currently active Guards.\n * @param origin Domain of origin chain\n * @return statePayload Raw payload with latest active Guard state for origin\n */\n function getLatestState(uint32 origin) external view returns (bytes memory statePayload);\n}\n\n// node_modules/@openzeppelin/contracts/utils/Strings.sol\n\n// OpenZeppelin Contracts (last updated v4.9.0) (utils/Strings.sol)\n\n/**\n * @dev String operations.\n */\nlibrary Strings {\n bytes16 private constant _SYMBOLS = \"0123456789abcdef\";\n uint8 private constant _ADDRESS_LENGTH = 20;\n\n /**\n * @dev Converts a `uint256` to its ASCII `string` decimal representation.\n */\n function toString(uint256 value) internal pure returns (string memory) {\n unchecked {\n uint256 length = Math.log10(value) + 1;\n string memory buffer = new string(length);\n uint256 ptr;\n /// @solidity memory-safe-assembly\n assembly {\n ptr := add(buffer, add(32, length))\n }\n while (true) {\n ptr--;\n /// @solidity memory-safe-assembly\n assembly {\n mstore8(ptr, byte(mod(value, 10), _SYMBOLS))\n }\n value /= 10;\n if (value == 0) break;\n }\n return buffer;\n }\n }\n\n /**\n * @dev Converts a `int256` to its ASCII `string` decimal representation.\n */\n function toString(int256 value) internal pure returns (string memory) {\n return string(abi.encodePacked(value \u003c 0 ? \"-\" : \"\", toString(SignedMath.abs(value))));\n }\n\n /**\n * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation.\n */\n function toHexString(uint256 value) internal pure returns (string memory) {\n unchecked {\n return toHexString(value, Math.log256(value) + 1);\n }\n }\n\n /**\n * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length.\n */\n function toHexString(uint256 value, uint256 length) internal pure returns (string memory) {\n bytes memory buffer = new bytes(2 * length + 2);\n buffer[0] = \"0\";\n buffer[1] = \"x\";\n for (uint256 i = 2 * length + 1; i \u003e 1; --i) {\n buffer[i] = _SYMBOLS[value \u0026 0xf];\n value \u003e\u003e= 4;\n }\n require(value == 0, \"Strings: hex length insufficient\");\n return string(buffer);\n }\n\n /**\n * @dev Converts an `address` with fixed length of 20 bytes to its not checksummed ASCII `string` hexadecimal representation.\n */\n function toHexString(address addr) internal pure returns (string memory) {\n return toHexString(uint256(uint160(addr)), _ADDRESS_LENGTH);\n }\n\n /**\n * @dev Returns true if the two strings are equal.\n */\n function equal(string memory a, string memory b) internal pure returns (bool) {\n return keccak256(bytes(a)) == keccak256(bytes(b));\n }\n}\n\n// node_modules/@openzeppelin/contracts-upgradeable/utils/ContextUpgradeable.sol\n\n// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)\n\n/**\n * @dev Provides information about the current execution context, including the\n * sender of the transaction and its data. While these are generally available\n * via msg.sender and msg.data, they should not be accessed in such a direct\n * manner, since when dealing with meta-transactions the account sending and\n * paying for execution may not be the actual sender (as far as an application\n * is concerned).\n *\n * This contract is only required for intermediate, library-like contracts.\n */\nabstract contract ContextUpgradeable is Initializable {\n function __Context_init() internal onlyInitializing {\n }\n\n function __Context_init_unchained() internal onlyInitializing {\n }\n function _msgSender() internal view virtual returns (address) {\n return msg.sender;\n }\n\n function _msgData() internal view virtual returns (bytes calldata) {\n return msg.data;\n }\n\n /**\n * @dev This empty reserved space is put in place to allow future versions to add new\n * variables without shifting down storage in the inheritance chain.\n * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\n */\n uint256[50] private __gap;\n}\n\n// contracts/libs/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/utils/cryptography/ECDSA.sol\n\n// OpenZeppelin Contracts (last updated v4.9.0) (utils/cryptography/ECDSA.sol)\n\n/**\n * @dev Elliptic Curve Digital Signature Algorithm (ECDSA) operations.\n *\n * These functions can be used to verify that a message was signed by the holder\n * of the private keys of a given address.\n */\nlibrary ECDSA {\n enum RecoverError {\n NoError,\n InvalidSignature,\n InvalidSignatureLength,\n InvalidSignatureS,\n InvalidSignatureV // Deprecated in v4.8\n }\n\n function _throwError(RecoverError error) private pure {\n if (error == RecoverError.NoError) {\n return; // no error: do nothing\n } else if (error == RecoverError.InvalidSignature) {\n revert(\"ECDSA: invalid signature\");\n } else if (error == RecoverError.InvalidSignatureLength) {\n revert(\"ECDSA: invalid signature length\");\n } else if (error == RecoverError.InvalidSignatureS) {\n revert(\"ECDSA: invalid signature 's' value\");\n }\n }\n\n /**\n * @dev Returns the address that signed a hashed message (`hash`) with\n * `signature` or error string. This address can then be used for verification purposes.\n *\n * The `ecrecover` EVM opcode allows for malleable (non-unique) signatures:\n * this function rejects them by requiring the `s` value to be in the lower\n * half order, and the `v` value to be either 27 or 28.\n *\n * IMPORTANT: `hash` _must_ be the result of a hash operation for the\n * verification to be secure: it is possible to craft signatures that\n * recover to arbitrary addresses for non-hashed data. A safe way to ensure\n * this is by receiving a hash of the original message (which may otherwise\n * be too long), and then calling {toEthSignedMessageHash} on it.\n *\n * Documentation for signature generation:\n * - with https://web3js.readthedocs.io/en/v1.3.4/web3-eth-accounts.html#sign[Web3.js]\n * - with https://docs.ethers.io/v5/api/signer/#Signer-signMessage[ethers]\n *\n * _Available since v4.3._\n */\n function tryRecover(bytes32 hash, bytes memory signature) internal pure returns (address, RecoverError) {\n if (signature.length == 65) {\n bytes32 r;\n bytes32 s;\n uint8 v;\n // ecrecover takes the signature parameters, and the only way to get them\n // currently is to use assembly.\n /// @solidity memory-safe-assembly\n assembly {\n r := mload(add(signature, 0x20))\n s := mload(add(signature, 0x40))\n v := byte(0, mload(add(signature, 0x60)))\n }\n return tryRecover(hash, v, r, s);\n } else {\n return (address(0), RecoverError.InvalidSignatureLength);\n }\n }\n\n /**\n * @dev Returns the address that signed a hashed message (`hash`) with\n * `signature`. This address can then be used for verification purposes.\n *\n * The `ecrecover` EVM opcode allows for malleable (non-unique) signatures:\n * this function rejects them by requiring the `s` value to be in the lower\n * half order, and the `v` value to be either 27 or 28.\n *\n * IMPORTANT: `hash` _must_ be the result of a hash operation for the\n * verification to be secure: it is possible to craft signatures that\n * recover to arbitrary addresses for non-hashed data. A safe way to ensure\n * this is by receiving a hash of the original message (which may otherwise\n * be too long), and then calling {toEthSignedMessageHash} on it.\n */\n function recover(bytes32 hash, bytes memory signature) internal pure returns (address) {\n (address recovered, RecoverError error) = tryRecover(hash, signature);\n _throwError(error);\n return recovered;\n }\n\n /**\n * @dev Overload of {ECDSA-tryRecover} that receives the `r` and `vs` short-signature fields separately.\n *\n * See https://eips.ethereum.org/EIPS/eip-2098[EIP-2098 short signatures]\n *\n * _Available since v4.3._\n */\n function tryRecover(bytes32 hash, bytes32 r, bytes32 vs) internal pure returns (address, RecoverError) {\n bytes32 s = vs \u0026 bytes32(0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff);\n uint8 v = uint8((uint256(vs) \u003e\u003e 255) + 27);\n return tryRecover(hash, v, r, s);\n }\n\n /**\n * @dev Overload of {ECDSA-recover} that receives the `r and `vs` short-signature fields separately.\n *\n * _Available since v4.2._\n */\n function recover(bytes32 hash, bytes32 r, bytes32 vs) internal pure returns (address) {\n (address recovered, RecoverError error) = tryRecover(hash, r, vs);\n _throwError(error);\n return recovered;\n }\n\n /**\n * @dev Overload of {ECDSA-tryRecover} that receives the `v`,\n * `r` and `s` signature fields separately.\n *\n * _Available since v4.3._\n */\n function tryRecover(bytes32 hash, uint8 v, bytes32 r, bytes32 s) internal pure returns (address, RecoverError) {\n // EIP-2 still allows signature malleability for ecrecover(). Remove this possibility and make the signature\n // unique. Appendix F in the Ethereum Yellow paper (https://ethereum.github.io/yellowpaper/paper.pdf), defines\n // the valid range for s in (301): 0 \u003c s \u003c secp256k1n ÷ 2 + 1, and for v in (302): v ∈ {27, 28}. Most\n // signatures from current libraries generate a unique signature with an s-value in the lower half order.\n //\n // If your library generates malleable signatures, such as s-values in the upper range, calculate a new s-value\n // with 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141 - s1 and flip v from 27 to 28 or\n // vice versa. If your library also generates signatures with 0/1 for v instead 27/28, add 27 to v to accept\n // these malleable signatures as well.\n if (uint256(s) \u003e 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0) {\n return (address(0), RecoverError.InvalidSignatureS);\n }\n\n // If the signature is valid (and not malleable), return the signer address\n address signer = ecrecover(hash, v, r, s);\n if (signer == address(0)) {\n return (address(0), RecoverError.InvalidSignature);\n }\n\n return (signer, RecoverError.NoError);\n }\n\n /**\n * @dev Overload of {ECDSA-recover} that receives the `v`,\n * `r` and `s` signature fields separately.\n */\n function recover(bytes32 hash, uint8 v, bytes32 r, bytes32 s) internal pure returns (address) {\n (address recovered, RecoverError error) = tryRecover(hash, v, r, s);\n _throwError(error);\n return recovered;\n }\n\n /**\n * @dev Returns an Ethereum Signed Message, created from a `hash`. This\n * produces hash corresponding to the one signed with the\n * https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`]\n * JSON-RPC method as part of EIP-191.\n *\n * See {recover}.\n */\n function toEthSignedMessageHash(bytes32 hash) internal pure returns (bytes32 message) {\n // 32 is the length in bytes of hash,\n // enforced by the type signature above\n /// @solidity memory-safe-assembly\n assembly {\n mstore(0x00, \"\\x19Ethereum Signed Message:\\n32\")\n mstore(0x1c, hash)\n message := keccak256(0x00, 0x3c)\n }\n }\n\n /**\n * @dev Returns an Ethereum Signed Message, created from `s`. This\n * produces hash corresponding to the one signed with the\n * https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`]\n * JSON-RPC method as part of EIP-191.\n *\n * See {recover}.\n */\n function toEthSignedMessageHash(bytes memory s) internal pure returns (bytes32) {\n return keccak256(abi.encodePacked(\"\\x19Ethereum Signed Message:\\n\", Strings.toString(s.length), s));\n }\n\n /**\n * @dev Returns an Ethereum Signed Typed Data, created from a\n * `domainSeparator` and a `structHash`. This produces hash corresponding\n * to the one signed with the\n * https://eips.ethereum.org/EIPS/eip-712[`eth_signTypedData`]\n * JSON-RPC method as part of EIP-712.\n *\n * See {recover}.\n */\n function toTypedDataHash(bytes32 domainSeparator, bytes32 structHash) internal pure returns (bytes32 data) {\n /// @solidity memory-safe-assembly\n assembly {\n let ptr := mload(0x40)\n mstore(ptr, \"\\x19\\x01\")\n mstore(add(ptr, 0x02), domainSeparator)\n mstore(add(ptr, 0x22), structHash)\n data := keccak256(ptr, 0x42)\n }\n }\n\n /**\n * @dev Returns an Ethereum Signed Data with intended validator, created from a\n * `validator` and `data` according to the version 0 of EIP-191.\n *\n * See {recover}.\n */\n function toDataWithIntendedValidatorHash(address validator, bytes memory data) internal pure returns (bytes32) {\n return keccak256(abi.encodePacked(\"\\x19\\x00\", validator, data));\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/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/inbox/StatementInbox.sol\n\n// ══════════════════════════════ LIBRARY IMPORTS ══════════════════════════════\n\n// ═════════════════════════════ INTERNAL IMPORTS ══════════════════════════════\n\n// ═════════════════════════════ EXTERNAL IMPORTS ══════════════════════════════\n\n/// @notice `StatementInbox` is the entry point for all agent-signed statements. It verifies the\n/// agent signatures, and passes the unsigned statements to the contract to consume it via `acceptX` functions. Is is\n/// also used to verify the agent-signed statements and initiate the agent slashing, should the statement be invalid.\n/// `StatementInbox` is responsible for the following:\n/// - Accepting State and Receipt Reports to initiate a dispute between Guard and Notary.\n/// - Storing all the Guard Reports with the Guard signature leading to a dispute.\n/// - Verifying State/State Reports referencing the local chain and slashing the signer if statement is invalid.\n/// - Verifying Receipt/Receipt Reports referencing the local chain and slashing the signer if statement is invalid.\nabstract contract StatementInbox is MessagingBase, StatementInboxEvents, IStatementInbox {\n using AttestationLib for bytes;\n using ReceiptLib for bytes;\n using StateLib for bytes;\n using SnapshotLib for bytes;\n\n struct StoredReport {\n uint256 sigIndex;\n bytes statementPayload;\n }\n\n // ══════════════════════════════════════════════════ STORAGE ══════════════════════════════════════════════════════\n\n address public agentManager;\n address public origin;\n address public destination;\n\n // TODO: optimize this\n bytes[] internal _storedSignatures;\n StoredReport[] internal _storedReports;\n\n /// @dev gap for upgrade safety\n uint256[45] private __GAP; // solhint-disable-line var-name-mixedcase\n\n // ════════════════════════════════════════════════ INITIALIZER ════════════════════════════════════════════════════\n\n /// @dev Initializes the contract:\n /// - Sets up `msg.sender` as the owner of the contract.\n /// - Sets up `agentManager`, `origin`, and `destination`.\n // solhint-disable-next-line func-name-mixedcase\n function __StatementInbox_init(address agentManager_, address origin_, address destination_)\n internal\n onlyInitializing\n {\n agentManager = agentManager_;\n origin = origin_;\n destination = destination_;\n __Ownable2Step_init();\n }\n\n // ══════════════════════════════════════════ SUBMIT AGENT STATEMENTS ══════════════════════════════════════════════\n\n /// @inheritdoc IStatementInbox\n // solhint-disable-next-line ordering\n function submitStateReportWithSnapshot(\n uint8 stateIndex,\n bytes memory srSignature,\n bytes memory snapPayload,\n bytes memory snapSignature\n ) external returns (bool wasAccepted) {\n // This will revert if payload is not a snapshot\n Snapshot snapshot = snapPayload.castToSnapshot();\n // This will revert if the snapshot signer is not a known Notary\n (AgentStatus memory notaryStatus,) =\n _verifySnapshot({snapshot: snapshot, snapSignature: snapSignature, verifyNotary: true});\n // Notary needs to be Active/Unstaking\n notaryStatus.verifyActiveUnstaking();\n // Check if Notary is active on this chain\n _verifyNotaryDomain(notaryStatus.domain);\n // This will revert if state index is out of range\n State state = snapshot.state(stateIndex);\n // This will revert if the report signer is not an known Guard\n (AgentStatus memory guardStatus,) = _verifyStateReport(state, srSignature);\n // Check that Guard is active\n guardStatus.verifyActive();\n _saveReport(state.unwrap().clone(), srSignature);\n // This will revert if either actor is already in dispute\n IAgentManager(agentManager).openDispute(guardStatus.index, notaryStatus.index);\n return true;\n }\n\n /// @inheritdoc IStatementInbox\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 // This will revert if payload is not a snapshot\n Snapshot snapshot = snapPayload.castToSnapshot();\n // This will revert if state index is out of range\n State state = snapshot.state(stateIndex);\n // This will revert if the report signer is not an known Guard\n (AgentStatus memory guardStatus,) = _verifyStateReport(state, srSignature);\n // Check that Guard is active\n guardStatus.verifyActive();\n // This will revert if payload is not an attestation\n Attestation att = attPayload.castToAttestation();\n // This will revert if signer is not an known Notary\n (AgentStatus memory notaryStatus,) = _verifyAttestation(att, attSignature);\n // Notary needs to be Active/Unstaking\n notaryStatus.verifyActiveUnstaking();\n // Check if Notary is active on this chain\n _verifyNotaryDomain(notaryStatus.domain);\n if (snapshot.calculateRoot() != att.snapRoot()) revert IncorrectSnapshotRoot();\n _saveReport(state.unwrap().clone(), srSignature);\n // This will revert if either actor is already in dispute\n IAgentManager(agentManager).openDispute(guardStatus.index, notaryStatus.index);\n return true;\n }\n\n /// @inheritdoc IStatementInbox\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 // This will revert if payload is not a state\n State state = statePayload.castToState();\n // This will revert if the report signer is not an known Guard\n (AgentStatus memory guardStatus,) = _verifyStateReport(state, srSignature);\n // Check that Guard is active\n guardStatus.verifyActive();\n // This will revert if payload is not an attestation\n Attestation att = attPayload.castToAttestation();\n // This will revert if signer is not a known Notary\n (AgentStatus memory notaryStatus,) = _verifyAttestation(att, attSignature);\n // Notary needs to be Active/Unstaking\n notaryStatus.verifyActiveUnstaking();\n // Check if Notary is active on this chain\n _verifyNotaryDomain(notaryStatus.domain);\n // This will revert if any of these is true:\n // - Attestation root is not equal to Merkle Root derived from State and Snapshot Proof.\n // - Snapshot Proof's first element does not match the State metadata.\n // - Snapshot Proof length exceeds Snapshot tree Height.\n // - State index is out of range.\n _verifySnapshotMerkle(att, stateIndex, state, snapProof);\n _saveReport(statePayload, srSignature);\n // This will revert if either actor is already in dispute\n IAgentManager(agentManager).openDispute(guardStatus.index, notaryStatus.index);\n return true;\n }\n\n // ══════════════════════════════════════════ VERIFY AGENT STATEMENTS ══════════════════════════════════════════════\n\n /// @inheritdoc IStatementInbox\n function verifyReceipt(bytes memory rcptPayload, bytes memory rcptSignature)\n external\n returns (bool isValidReceipt)\n {\n // This will revert if payload is not a receipt\n Receipt rcpt = rcptPayload.castToReceipt();\n // This will revert if the attestation signer is not a known Notary\n (AgentStatus memory status, address notary) = _verifyReceipt(rcpt, rcptSignature);\n // Notary needs to be Active/Unstaking\n status.verifyActiveUnstaking();\n isValidReceipt = IExecutionHub(destination).isValidReceipt(rcptPayload);\n if (!isValidReceipt) {\n emit InvalidReceipt(rcptPayload, rcptSignature);\n IAgentManager(agentManager).slashAgent(status.domain, notary, msg.sender);\n }\n }\n\n /// @inheritdoc IStatementInbox\n function verifyReceiptReport(bytes memory rcptPayload, bytes memory rrSignature)\n external\n returns (bool isValidReport)\n {\n // This will revert if payload is not a receipt\n Receipt rcpt = rcptPayload.castToReceipt();\n // This will revert if the report signer is not a known Guard\n (AgentStatus memory status, address guard) = _verifyReceiptReport(rcpt, rrSignature);\n // Guard needs to be Active/Unstaking\n status.verifyActiveUnstaking();\n // Report is valid IF AND ONLY IF the reported receipt in invalid\n isValidReport = !IExecutionHub(destination).isValidReceipt(rcptPayload);\n if (!isValidReport) {\n emit InvalidReceiptReport(rcptPayload, rrSignature);\n IAgentManager(agentManager).slashAgent(status.domain, guard, msg.sender);\n }\n }\n\n /// @inheritdoc IStatementInbox\n function verifyStateWithAttestation(\n uint8 stateIndex,\n bytes memory snapPayload,\n bytes memory attPayload,\n bytes memory attSignature\n ) external returns (bool isValidState) {\n // This will revert if payload is not an attestation\n Attestation att = attPayload.castToAttestation();\n // This will revert if the attestation signer is not a known Notary\n (AgentStatus memory status, address notary) = _verifyAttestation(att, attSignature);\n // Notary needs to be Active/Unstaking\n status.verifyActiveUnstaking();\n // This will revert if payload is not a snapshot\n Snapshot snapshot = snapPayload.castToSnapshot();\n if (snapshot.calculateRoot() != att.snapRoot()) revert IncorrectSnapshotRoot();\n // This will revert if state does not refer to this chain\n bytes memory statePayload = snapshot.state(stateIndex).unwrap().clone();\n isValidState = IStateHub(origin).isValidState(statePayload);\n if (!isValidState) {\n emit InvalidStateWithAttestation(stateIndex, statePayload, attPayload, attSignature);\n IAgentManager(agentManager).slashAgent(status.domain, notary, msg.sender);\n }\n }\n\n /// @inheritdoc IStatementInbox\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 // This will revert if payload is not an attestation\n Attestation att = attPayload.castToAttestation();\n // This will revert if the attestation signer is not a known Notary\n (AgentStatus memory status, address notary) = _verifyAttestation(att, attSignature);\n // Notary needs to be Active/Unstaking\n status.verifyActiveUnstaking();\n // This will revert if payload is not a state\n State state = statePayload.castToState();\n // This will revert if any of these is true:\n // - Attestation root is not equal to Merkle Root derived from State and Snapshot Proof.\n // - Snapshot Proof's first element does not match the State metadata.\n // - Snapshot Proof length exceeds Snapshot tree Height.\n // - State index is out of range.\n _verifySnapshotMerkle(att, stateIndex, state, snapProof);\n // This will revert if state does not refer to this chain\n isValidState = IStateHub(origin).isValidState(statePayload);\n if (!isValidState) {\n emit InvalidStateWithAttestation(stateIndex, statePayload, attPayload, attSignature);\n IAgentManager(agentManager).slashAgent(status.domain, notary, msg.sender);\n }\n }\n\n /// @inheritdoc IStatementInbox\n function verifyStateWithSnapshot(uint8 stateIndex, bytes memory snapPayload, bytes memory snapSignature)\n external\n returns (bool isValidState)\n {\n // This will revert if payload is not a snapshot\n Snapshot snapshot = snapPayload.castToSnapshot();\n // This will revert if the snapshot signer is not a known Guard/Notary\n (AgentStatus memory status, address agent) =\n _verifySnapshot({snapshot: snapshot, snapSignature: snapSignature, verifyNotary: false});\n // Agent needs to be Active/Unstaking\n status.verifyActiveUnstaking();\n // This will revert if state does not refer to this chain\n isValidState = IStateHub(origin).isValidState(snapshot.state(stateIndex).unwrap().clone());\n if (!isValidState) {\n emit InvalidStateWithSnapshot(stateIndex, snapPayload, snapSignature);\n IAgentManager(agentManager).slashAgent(status.domain, agent, msg.sender);\n }\n }\n\n /// @inheritdoc IStatementInbox\n function verifyStateReport(bytes memory statePayload, bytes memory srSignature)\n external\n returns (bool isValidReport)\n {\n // This will revert if payload is not a state\n State state = statePayload.castToState();\n // This will revert if the report signer is not a known Guard\n (AgentStatus memory status, address guard) = _verifyStateReport(state, srSignature);\n // Guard needs to be Active/Unstaking\n status.verifyActiveUnstaking();\n // Report is valid IF AND ONLY IF the reported state in invalid\n // This will revert if the reported state does not refer to this chain\n isValidReport = !IStateHub(origin).isValidState(statePayload);\n if (!isValidReport) {\n emit InvalidStateReport(statePayload, srSignature);\n IAgentManager(agentManager).slashAgent(status.domain, guard, msg.sender);\n }\n }\n\n // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════\n\n /// @inheritdoc IStatementInbox\n function getReportsAmount() external view returns (uint256) {\n return _storedReports.length;\n }\n\n /// @inheritdoc IStatementInbox\n function getGuardReport(uint256 index)\n external\n view\n returns (bytes memory statementPayload, bytes memory reportSignature)\n {\n if (index \u003e= _storedReports.length) revert IndexOutOfRange();\n StoredReport memory storedReport = _storedReports[index];\n statementPayload = storedReport.statementPayload;\n reportSignature = _storedSignatures[storedReport.sigIndex];\n }\n\n /// @inheritdoc IStatementInbox\n function getStoredSignature(uint256 index) external view returns (bytes memory) {\n return _storedSignatures[index];\n }\n\n // ══════════════════════════════════════════════ INTERNAL LOGIC ═══════════════════════════════════════════════════\n\n /// @dev Saves the statement reported by Guard as invalid and the Guard Report signature.\n function _saveReport(bytes memory statementPayload, bytes memory reportSignature) internal {\n uint256 sigIndex = _saveSignature(reportSignature);\n _storedReports.push(StoredReport(sigIndex, statementPayload));\n }\n\n /// @dev Saves the signature and returns its index.\n function _saveSignature(bytes memory signature) internal returns (uint256 sigIndex) {\n sigIndex = _storedSignatures.length;\n _storedSignatures.push(signature);\n }\n\n // ═══════════════════════════════════════════════ AGENT CHECKS ════════════════════════════════════════════════════\n\n /**\n * @dev Recovers a signer from a hashed message, and a EIP-191 signature for it.\n * Will revert, if the signer is not a known agent.\n * @dev Agent flag could be any of these: Active/Unstaking/Resting/Fraudulent/Slashed\n * Further checks need to be performed in a caller function.\n * @param hashedStatement Hash of the statement that was signed by an Agent\n * @param signature Agent signature for the hashed statement\n * @return status Struct representing agent status:\n * - flag Unknown/Active/Unstaking/Resting/Fraudulent/Slashed\n * - domain Domain where agent is/was active\n * - index Index of agent in the Agent Merkle Tree\n * @return agent Agent that signed the statement\n */\n function _recoverAgent(bytes32 hashedStatement, bytes memory signature)\n internal\n view\n returns (AgentStatus memory status, address agent)\n {\n bytes32 ethSignedMsg = ECDSA.toEthSignedMessageHash(hashedStatement);\n agent = ECDSA.recover(ethSignedMsg, signature);\n status = IAgentManager(agentManager).agentStatus(agent);\n // Discard signature of unknown agents.\n // Further flag checks are supposed to be performed in a caller function.\n status.verifyKnown();\n }\n\n /// @dev Verifies that Notary signature is active on local domain.\n function _verifyNotaryDomain(uint32 notaryDomain) internal view {\n // Notary needs to be from the local domain (if contract is not deployed on Synapse Chain).\n // Or Notary could be from any domain (if contract is deployed on Synapse Chain).\n if (notaryDomain != localDomain \u0026\u0026 localDomain != synapseDomain) revert IncorrectAgentDomain();\n }\n\n // ════════════════════════════════════════ ATTESTATION RELATED CHECKS ═════════════════════════════════════════════\n\n /**\n * @dev Internal function to verify the signed attestation payload.\n * Reverts if any of these is true:\n * - Attestation signer is not a known Notary.\n * @param att Typed memory view over attestation payload\n * @param attSignature Notary signature for the attestation\n * @return status Struct representing agent status, see {_recoverAgent}\n * @return notary Notary that signed the snapshot\n */\n function _verifyAttestation(Attestation att, bytes memory attSignature)\n internal\n view\n returns (AgentStatus memory status, address notary)\n {\n // This will revert if signer is not a known agent\n (status, notary) = _recoverAgent(att.hashValid(), attSignature);\n // Attestation signer needs to be a Notary, not a Guard\n if (status.domain == 0) revert AgentNotNotary();\n }\n\n /**\n * @dev Internal function to verify the signed attestation report payload.\n * Reverts if any of these is true:\n * - Report signer is not a known Guard.\n * @param att Typed memory view over attestation payload that Guard reports as invalid\n * @param arSignature Guard signature for the \"invalid attestation\" report\n * @return status Struct representing guard status, see {_recoverAgent}\n * @return guard Guard that signed the report\n */\n function _verifyAttestationReport(Attestation att, bytes memory arSignature)\n internal\n view\n returns (AgentStatus memory status, address guard)\n {\n // This will revert if signer is not a known agent\n (status, guard) = _recoverAgent(att.hashInvalid(), arSignature);\n // Report signer needs to be a Guard, not a Notary\n if (status.domain != 0) revert AgentNotGuard();\n }\n\n // ══════════════════════════════════════════ RECEIPT RELATED CHECKS ═══════════════════════════════════════════════\n\n /**\n * @dev Internal function to verify the signed receipt payload.\n * Reverts if any of these is true:\n * - Receipt signer is not a known Notary.\n * @param rcpt Typed memory view over receipt payload\n * @param rcptSignature Notary signature for the receipt\n * @return status Struct representing agent status, see {_recoverAgent}\n * @return notary Notary that signed the snapshot\n */\n function _verifyReceipt(Receipt rcpt, bytes memory rcptSignature)\n internal\n view\n returns (AgentStatus memory status, address notary)\n {\n // This will revert if signer is not a known agent\n (status, notary) = _recoverAgent(rcpt.hashValid(), rcptSignature);\n // Receipt signer needs to be a Notary, not a Guard\n if (status.domain == 0) revert AgentNotNotary();\n }\n\n /**\n * @dev Internal function to verify the signed receipt report payload.\n * Reverts if any of these is true:\n * - Report signer is not a known Guard.\n * @param rcpt Typed memory view over receipt payload that Guard reports as invalid\n * @param rrSignature Guard signature for the \"invalid receipt\" report\n * @return status Struct representing guard status, see {_recoverAgent}\n * @return guard Guard that signed the report\n */\n function _verifyReceiptReport(Receipt rcpt, bytes memory rrSignature)\n internal\n view\n returns (AgentStatus memory status, address guard)\n {\n // This will revert if signer is not a known agent\n (status, guard) = _recoverAgent(rcpt.hashInvalid(), rrSignature);\n // Report signer needs to be a Guard, not a Notary\n if (status.domain != 0) revert AgentNotGuard();\n }\n\n // ═══════════════════════════════════════ STATE/SNAPSHOT RELATED CHECKS ═══════════════════════════════════════════\n\n /**\n * @dev Internal function to verify the signed snapshot report payload.\n * Reverts if any of these is true:\n * - Report signer is not a known Guard.\n * @param state Typed memory view over state payload that Guard reports as invalid\n * @param srSignature Guard signature for the report\n * @return status Struct representing guard status, see {_recoverAgent}\n * @return guard Guard that signed the report\n */\n function _verifyStateReport(State state, bytes memory srSignature)\n internal\n view\n returns (AgentStatus memory status, address guard)\n {\n // This will revert if signer is not a known agent\n (status, guard) = _recoverAgent(state.hashInvalid(), srSignature);\n // Report signer needs to be a Guard, not a Notary\n if (status.domain != 0) revert AgentNotGuard();\n }\n\n /**\n * @dev Internal function to verify the signed snapshot payload.\n * Reverts if any of these is true:\n * - Snapshot signer is not a known Agent.\n * - Snapshot signer is not a Notary (if verifyNotary is true).\n * @param snapshot Typed memory view over snapshot payload\n * @param snapSignature Agent signature for the snapshot\n * @param verifyNotary If true, snapshot signer needs to be a Notary, not a Guard\n * @return status Struct representing agent status, see {_recoverAgent}\n * @return agent Agent that signed the snapshot\n */\n function _verifySnapshot(Snapshot snapshot, bytes memory snapSignature, bool verifyNotary)\n internal\n view\n returns (AgentStatus memory status, address agent)\n {\n // This will revert if signer is not a known agent\n (status, agent) = _recoverAgent(snapshot.hashValid(), snapSignature);\n // If requested, snapshot signer needs to be a Notary, not a Guard\n if (verifyNotary \u0026\u0026 status.domain == 0) revert AgentNotNotary();\n }\n\n // ═══════════════════════════════════════════ MERKLE RELATED CHECKS ═══════════════════════════════════════════════\n\n /**\n * @dev Internal function to verify that snapshot roots match.\n * Reverts if any of these is true:\n * - Attestation root is not equal to Merkle Root derived from State and Snapshot Proof.\n * - Snapshot Proof's first element does not match the State metadata.\n * - Snapshot Proof length exceeds Snapshot tree Height.\n * - State index is out of range.\n * @param att Typed memory view over Attestation\n * @param stateIndex Index of state in the snapshot\n * @param state Typed memory view over the provided state payload\n * @param snapProof Raw payload with snapshot data\n */\n function _verifySnapshotMerkle(Attestation att, uint8 stateIndex, State state, bytes32[] memory snapProof)\n internal\n pure\n {\n // Snapshot proof first element should match State metadata (aka \"right sub-leaf\")\n (, bytes32 rightSubLeaf) = state.subLeafs();\n if (snapProof[0] != rightSubLeaf) revert IncorrectSnapshotProof();\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(state.root(), state.origin(), snapProof, stateIndex);\n // Snapshot root should match the attestation root\n if (att.snapRoot() != snapshotRoot) revert IncorrectSnapshotRoot();\n }\n}\n\n// contracts/inbox/Inbox.sol\n\n// ══════════════════════════════ LIBRARY IMPORTS ══════════════════════════════\n\n// ═════════════════════════════ INTERNAL IMPORTS ══════════════════════════════\n\n/// @notice `Inbox` is the child of `StatementInbox` contract, that is used on Synapse Chain.\n/// In addition to the functionality of `StatementInbox`, it also:\n/// - Accepts Guard and Notary Snapshots and passes them to `Summit` contract.\n/// - Accepts Notary-signed Receipts and passes them to `Summit` contract.\n/// - Accepts Receipt Reports to initiate a dispute between Guard and Notary.\n/// - Verifies Attestations and Attestation Reports, and slashes the signer if they are invalid.\ncontract Inbox is StatementInbox, InboxEvents, InterfaceInbox {\n using AttestationLib for bytes;\n using ReceiptLib for bytes;\n using SnapshotLib for bytes;\n\n // Struct to get around stack too deep error. TODO: revisit this\n struct ReceiptInfo {\n AgentStatus rcptNotaryStatus;\n address notary;\n uint32 attNonce;\n AgentStatus attNotaryStatus;\n }\n\n // ══════════════════════════════════════════════════ STORAGE ══════════════════════════════════════════════════════\n\n // The address of the Summit contract.\n address public summit;\n\n // ═════════════════════════════════════════ CONSTRUCTOR \u0026 INITIALIZER ═════════════════════════════════════════════\n\n constructor(uint32 synapseDomain_) MessagingBase(\"0.0.3\", synapseDomain_) {\n if (localDomain != synapseDomain) revert MustBeSynapseDomain();\n }\n\n /// @notice Initializes `Inbox` contract:\n /// - Sets `msg.sender` as the owner of the contract\n /// - Sets `agentManager`, `origin`, `destination` and `summit` addresses\n function initialize(address agentManager_, address origin_, address destination_, address summit_)\n external\n initializer\n {\n __StatementInbox_init(agentManager_, origin_, destination_);\n summit = summit_;\n }\n\n // ══════════════════════════════════════════ SUBMIT AGENT STATEMENTS ══════════════════════════════════════════════\n\n /// @inheritdoc InterfaceInbox\n function submitSnapshot(bytes memory snapPayload, bytes memory snapSignature)\n external\n returns (bytes memory attPayload, bytes32 agentRoot_, uint256[] memory snapGas)\n {\n // This will revert if payload is not a snapshot\n Snapshot snapshot = snapPayload.castToSnapshot();\n // This will revert if the signer is not a known Guard/Notary\n (AgentStatus memory status, address agent) =\n _verifySnapshot({snapshot: snapshot, snapSignature: snapSignature, verifyNotary: false});\n // Check that Agent is active\n status.verifyActive();\n // Store Agent signature for the Snapshot\n uint256 sigIndex = _saveSignature(snapSignature);\n if (status.domain == 0) {\n // Guard that is in Dispute could still submit new snapshots, so we don't check that\n InterfaceSummit(summit).acceptGuardSnapshot({\n guardIndex: status.index,\n sigIndex: sigIndex,\n snapPayload: snapPayload\n });\n } else {\n // Get current agentRoot from AgentManager\n agentRoot_ = IAgentManager(agentManager).agentRoot();\n // This will revert if Notary is in Dispute\n attPayload = InterfaceSummit(summit).acceptNotarySnapshot({\n notaryIndex: status.index,\n sigIndex: sigIndex,\n agentRoot: agentRoot_,\n snapPayload: snapPayload\n });\n ChainGas[] memory snapGas_ = snapshot.snapGas();\n // Pass created attestation to Destination to enable executing messages coming to Synapse Chain\n InterfaceDestination(destination).acceptAttestation(\n status.index, type(uint256).max, attPayload, agentRoot_, snapGas_\n );\n // Use assembly to cast ChainGas[] to uint256[] without copying. Highest bits are left zeroed.\n // solhint-disable-next-line no-inline-assembly\n assembly {\n snapGas := snapGas_\n }\n }\n emit SnapshotAccepted(status.domain, agent, snapPayload, snapSignature);\n }\n\n /// @inheritdoc InterfaceInbox\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 // Struct to get around stack too deep error.\n ReceiptInfo memory info;\n // This will revert if payload is not a receipt\n Receipt rcpt = rcptPayload.castToReceipt();\n // This will revert if the receipt signer is not a known Notary\n (info.rcptNotaryStatus, info.notary) = _verifyReceipt(rcpt, rcptSignature);\n // Receipt Notary needs to be Active\n info.rcptNotaryStatus.verifyActive();\n info.attNonce = IExecutionHub(destination).getAttestationNonce(rcpt.snapshotRoot());\n if (info.attNonce == 0) revert IncorrectSnapshotRoot();\n // Attestation Notary domain needs to match the destination domain\n info.attNotaryStatus = IAgentManager(agentManager).agentStatus(rcpt.attNotary());\n if (info.attNotaryStatus.domain != rcpt.destination()) revert IncorrectAgentDomain();\n // Check that the correct tip values for the message were provided\n _verifyReceiptTips(rcpt.messageHash(), paddedTips, headerHash, bodyHash);\n // Store Notary signature for the Receipt\n uint256 sigIndex = _saveSignature(rcptSignature);\n // This will revert if Receipt Notary is in Dispute\n wasAccepted = InterfaceSummit(summit).acceptReceipt({\n rcptNotaryIndex: info.rcptNotaryStatus.index,\n attNotaryIndex: info.attNotaryStatus.index,\n sigIndex: sigIndex,\n attNonce: info.attNonce,\n paddedTips: paddedTips,\n rcptPayload: rcptPayload\n });\n if (wasAccepted) {\n emit ReceiptAccepted(info.rcptNotaryStatus.domain, info.notary, rcptPayload, rcptSignature);\n }\n }\n\n /// @inheritdoc InterfaceInbox\n function submitReceiptReport(bytes memory rcptPayload, bytes memory rcptSignature, bytes memory rrSignature)\n external\n returns (bool wasAccepted)\n {\n // This will revert if payload is not a receipt\n Receipt rcpt = rcptPayload.castToReceipt();\n // This will revert if the receipt signer is not a known Guard\n (AgentStatus memory guardStatus,) = _verifyReceiptReport(rcpt, rrSignature);\n // Guard needs to be Active\n guardStatus.verifyActive();\n // This will revert if report signer is not a known Notary\n (AgentStatus memory notaryStatus,) = _verifyReceipt(rcpt, rcptSignature);\n // Notary needs to be Active/Unstaking\n notaryStatus.verifyActiveUnstaking();\n _saveReport(rcptPayload, rrSignature);\n // This will revert if either actor is already in dispute\n IAgentManager(agentManager).openDispute(guardStatus.index, notaryStatus.index);\n return true;\n }\n\n /// @inheritdoc InterfaceInbox\n function passReceipt(uint32 attNotaryIndex, uint32 attNonce, uint256 paddedTips, bytes memory rcptPayload)\n external\n returns (bool wasAccepted)\n {\n // Only Destination can pass receipts\n if (msg.sender != destination) revert CallerNotDestination();\n return InterfaceSummit(summit).acceptReceipt({\n rcptNotaryIndex: attNotaryIndex,\n attNotaryIndex: attNotaryIndex,\n sigIndex: type(uint256).max,\n attNonce: attNonce,\n paddedTips: paddedTips,\n rcptPayload: rcptPayload\n });\n }\n\n // ══════════════════════════════════════════ VERIFY AGENT STATEMENTS ══════════════════════════════════════════════\n\n /// @inheritdoc InterfaceInbox\n function verifyAttestation(bytes memory attPayload, bytes memory attSignature)\n external\n returns (bool isValidAttestation)\n {\n // This will revert if payload is not an attestation\n Attestation att = attPayload.castToAttestation();\n // This will revert if the attestation signer is not a known Notary\n (AgentStatus memory status, address notary) = _verifyAttestation(att, attSignature);\n // Notary needs to be Active/Unstaking\n status.verifyActiveUnstaking();\n isValidAttestation = ISnapshotHub(summit).isValidAttestation(attPayload);\n if (!isValidAttestation) {\n emit InvalidAttestation(attPayload, attSignature);\n IAgentManager(agentManager).slashAgent(status.domain, notary, msg.sender);\n }\n }\n\n /// @inheritdoc InterfaceInbox\n function verifyAttestationReport(bytes memory attPayload, bytes memory arSignature)\n external\n returns (bool isValidReport)\n {\n // This will revert if payload is not an attestation\n Attestation att = attPayload.castToAttestation();\n // This will revert if the report signer is not a known Guard\n (AgentStatus memory status, address guard) = _verifyAttestationReport(att, arSignature);\n // Guard needs to be Active/Unstaking\n status.verifyActiveUnstaking();\n // Report is valid IF AND ONLY IF the reported attestation in invalid\n isValidReport = !ISnapshotHub(summit).isValidAttestation(attPayload);\n if (!isValidReport) {\n emit InvalidAttestationReport(attPayload, arSignature);\n IAgentManager(agentManager).slashAgent(status.domain, guard, msg.sender);\n }\n }\n\n // ══════════════════════════════════════════════ INTERNAL VIEWS ═══════════════════════════════════════════════════\n\n /// @dev Verifies that tips proof matches the message hash.\n function _verifyReceiptTips(bytes32 msgHash, uint256 paddedTips, bytes32 headerHash, bytes32 bodyHash)\n internal\n pure\n {\n Tips tips = TipsLib.wrapPadded(paddedTips);\n // full message leaf is (header, baseMessage), while base message leaf is (tips, remainingBody).\n if (MerkleMath.getParent(headerHash, MerkleMath.getParent(tips.leaf(), bodyHash)) != msgHash) {\n revert IncorrectTipsProof();\n }\n }\n}\n","language":"Solidity","languageVersion":"0.8.17","compilerVersion":"0.8.17","compilerOptions":"--combined-json bin,bin-runtime,srcmap,srcmap-runtime,abi,userdoc,devdoc,metadata,hashes --optimize --optimize-runs 10000 --allow-paths ., ./, ../","srcMap":"109611:976:0:-:0;;;;;;;;;;;;;;;-1:-1:-1;;;109611:976:0;;;;;;;;;;;;;;;;;","srcMapRuntime":"109611: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/Inbox.sol\":\"ChainContext\"},\"evmVersion\":\"london\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\"},\"optimizer\":{\"enabled\":true,\"runs\":10000},\"remappings\":[]},\"sources\":{\"solidity/Inbox.sol\":{\"keccak256\":\"0x9b516081a036814c0169e20e484d4a5499066b7a6f48fada952b5e844a1ca3e5\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://32bde393b3f24ef4307d9626d4143f337b3c0bd34e17bb969fd5a15221d96987\",\"dweb:/ipfs/QmTkt2XZRtgsbSpmsVQUM3c4ebETQoDVYbmEV9yheBghnr\"]}},\"version\":1}"},"hashes":{}},"solidity/Inbox.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/InboxEvents.sol\n\nabstract contract InboxEvents {\n /**\n * @notice Emitted when a snapshot is accepted by the Summit contract.\n * @param domain Domain where the signed Agent is active (ZERO for Guards)\n * @param agent Agent who signed the snapshot\n * @param snapPayload Raw payload with snapshot data\n * @param snapSignature Agent signature for the snapshot\n */\n event SnapshotAccepted(uint32 indexed domain, address indexed agent, bytes snapPayload, bytes snapSignature);\n\n /**\n * @notice Emitted when a snapshot is accepted by the Summit contract.\n * @param domain Domain where the signed Notary is active\n * @param notary Notary who signed the attestation\n * @param rcptPayload Raw payload with receipt data\n * @param rcptSignature Notary signature for the receipt\n */\n event ReceiptAccepted(uint32 domain, address notary, bytes rcptPayload, bytes rcptSignature);\n\n /**\n * @notice Emitted when a proof of invalid attestation is submitted.\n * @param attPayload Raw payload with Attestation data\n * @param attSignature Notary signature for the attestation\n */\n event InvalidAttestation(bytes attPayload, bytes attSignature);\n\n /**\n * @notice Emitted when a proof of invalid attestation report is submitted.\n * @param arPayload Raw payload with report data\n * @param arSignature Guard signature for the report\n */\n event InvalidAttestationReport(bytes arPayload, bytes arSignature);\n}\n\n// contracts/events/StatementInboxEvents.sol\n\nabstract contract StatementInboxEvents {\n // ════════════════════════════════════════════ STATEMENT ACCEPTED ═════════════════════════════════════════════════\n\n /**\n * @notice Emitted when a snapshot is accepted by the Destination contract.\n * @param domain Domain where the signed Notary is active\n * @param notary Notary who signed the attestation\n * @param attPayload Raw payload with attestation data\n * @param attSignature Notary signature for the attestation\n */\n event AttestationAccepted(uint32 domain, address notary, bytes attPayload, bytes attSignature);\n\n // ═════════════════════════════════════════ INVALID STATEMENT PROVED ══════════════════════════════════════════════\n\n /**\n * @notice Emitted when a proof of invalid receipt statement is submitted.\n * @param rcptPayload Raw payload with the receipt statement\n * @param rcptSignature Notary signature for the receipt statement\n */\n event InvalidReceipt(bytes rcptPayload, bytes rcptSignature);\n\n /**\n * @notice Emitted when a proof of invalid receipt report is submitted.\n * @param rrPayload Raw payload with report data\n * @param rrSignature Guard signature for the report\n */\n event InvalidReceiptReport(bytes rrPayload, bytes rrSignature);\n\n /**\n * @notice Emitted when a proof of invalid state in the signed attestation is submitted.\n * @param stateIndex Index of invalid state in the snapshot\n * @param statePayload Raw payload with state data\n * @param attPayload Raw payload with Attestation data for snapshot\n * @param attSignature Notary signature for the attestation\n */\n event InvalidStateWithAttestation(uint8 stateIndex, bytes statePayload, bytes attPayload, bytes attSignature);\n\n /**\n * @notice Emitted when a proof of invalid state in the signed snapshot is submitted.\n * @param stateIndex Index of invalid state in the snapshot\n * @param snapPayload Raw payload with snapshot data\n * @param snapSignature Agent signature for the snapshot\n */\n event InvalidStateWithSnapshot(uint8 stateIndex, bytes snapPayload, bytes snapSignature);\n\n /**\n * @notice Emitted when a proof of invalid state report is submitted.\n * @param srPayload Raw payload with report data\n * @param srSignature Guard signature for the report\n */\n event InvalidStateReport(bytes srPayload, bytes srSignature);\n}\n\n// contracts/interfaces/ISnapshotHub.sol\n\ninterface ISnapshotHub {\n /**\n * @notice Check that a given attestation is valid: matches the historical attestation\n * derived from an accepted Notary snapshot.\n * @dev Will revert if any of these is true:\n * - Attestation payload is not properly formatted.\n * @param attPayload Raw payload with attestation data\n * @return isValid Whether the provided attestation is valid\n */\n function isValidAttestation(bytes memory attPayload) external view returns (bool isValid);\n\n /**\n * @notice Returns saved attestation with the given nonce.\n * @dev Reverts if attestation with given nonce hasn't been created yet.\n * @param attNonce Nonce for the attestation\n * @return attPayload Raw payload with formatted Attestation data\n * @return agentRoot Agent root hash used for the attestation\n * @return snapGas Snapshot gas data used for the attestation\n */\n function getAttestation(uint32 attNonce)\n external\n view\n returns (bytes memory attPayload, bytes32 agentRoot, uint256[] memory snapGas);\n\n /**\n * @notice Returns the state with the highest known nonce submitted by a given Agent.\n * @param origin Domain of origin chain\n * @param agent Agent address\n * @return statePayload Raw payload with agent's latest state for origin\n */\n function getLatestAgentState(uint32 origin, address agent) external view returns (bytes memory statePayload);\n\n /**\n * @notice Returns latest saved attestation for a Notary.\n * @param notary Notary address\n * @return attPayload Raw payload with formatted Attestation data\n * @return agentRoot Agent root hash used for the attestation\n * @return snapGas Snapshot gas data used for the attestation\n */\n function getLatestNotaryAttestation(address notary)\n external\n view\n returns (bytes memory attPayload, bytes32 agentRoot, uint256[] memory snapGas);\n\n /**\n * @notice Returns Guard snapshot from the list of all accepted Guard snapshots.\n * @dev Reverts if snapshot with given index hasn't been accepted yet.\n * @param index Snapshot index in the list of all Guard snapshots\n * @return snapPayload Raw payload with Guard snapshot\n * @return snapSignature Raw payload with Guard signature for snapshot\n */\n function getGuardSnapshot(uint256 index)\n external\n view\n returns (bytes memory snapPayload, bytes memory snapSignature);\n\n /**\n * @notice Returns Notary snapshot from the list of all accepted Guard snapshots.\n * @dev Reverts if snapshot with given index hasn't been accepted yet.\n * @param index Snapshot index in the list of all Notary snapshots\n * @return snapPayload Raw payload with Notary snapshot\n * @return snapSignature Raw payload with Notary signature for snapshot\n */\n function getNotarySnapshot(uint256 index)\n external\n view\n returns (bytes memory snapPayload, bytes memory snapSignature);\n\n /**\n * @notice Returns Notary snapshot that was used for creating a given attestation.\n * @dev Reverts if any of these is true:\n * - Attestation payload is not properly formatted.\n * - Attestation is invalid (doesn't have a matching Notary snapshot).\n * @param attPayload Raw payload with attestation data\n * @return snapPayload Raw payload with Notary snapshot\n * @return snapSignature Raw payload with Notary signature for snapshot\n */\n function getNotarySnapshot(bytes memory attPayload)\n external\n view\n returns (bytes memory snapPayload, bytes memory snapSignature);\n\n /**\n * @notice Returns proof of inclusion of (root, origin) fields of a given snapshot's state\n * into the Snapshot Merkle Tree for a given attestation.\n * @dev Reverts if any of these is true:\n * - Attestation with given nonce hasn't been created yet.\n * - State index is out of range of snapshot list.\n * @param attNonce Nonce for the attestation\n * @param stateIndex Index of state in the attestation's snapshot\n * @return snapProof The snapshot proof\n */\n function getSnapshotProof(uint32 attNonce, uint8 stateIndex) external view returns (bytes32[] memory snapProof);\n}\n\n// contracts/interfaces/IStateHub.sol\n\ninterface IStateHub {\n /**\n * @notice Check that a given state is valid: matches the historical state of Origin contract.\n * Note: any Agent including an invalid state in their snapshot will be slashed\n * upon providing the snapshot and agent signature for it to Origin contract.\n * @dev Will revert if any of these is true:\n * - State payload is not properly formatted.\n * @param statePayload Raw payload with state data\n * @return isValid Whether the provided state is valid\n */\n function isValidState(bytes memory statePayload) external view returns (bool isValid);\n\n /**\n * @notice Returns the amount of saved states so far.\n * @dev This includes the initial state of \"empty Origin Merkle Tree\".\n */\n function statesAmount() external view returns (uint256);\n\n /**\n * @notice Suggest the data (state after latest sent message) to sign for an Agent.\n * Note: signing the suggested state data will will never lead to slashing of the actor,\n * assuming they have confirmed that the block, which number is included in the data,\n * is not subject to reorganization (which is different for every observed chain).\n * @return statePayload Raw payload with the latest state data\n */\n function suggestLatestState() external view returns (bytes memory statePayload);\n\n /**\n * @notice Given the historical nonce, suggest the state data to sign for an Agent.\n * Note: signing the suggested state data will will never lead to slashing of the actor,\n * assuming they have confirmed that the block, which number is included in the data,\n * is not subject to reorganization (which is different for every observed chain).\n * @param nonce Historical nonce to form a state\n * @return statePayload Raw payload with historical state data\n */\n function suggestState(uint32 nonce) external view returns (bytes memory statePayload);\n}\n\n// contracts/interfaces/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/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// node_modules/@openzeppelin/contracts/utils/math/Math.sol\n\n// OpenZeppelin Contracts (last updated v4.9.0) (utils/math/Math.sol)\n\n/**\n * @dev Standard math utilities missing in the Solidity language.\n */\nlibrary Math {\n enum Rounding {\n Down, // Toward negative infinity\n Up, // Toward infinity\n Zero // Toward zero\n }\n\n /**\n * @dev Returns the largest of two numbers.\n */\n function max(uint256 a, uint256 b) internal pure returns (uint256) {\n return a \u003e b ? a : b;\n }\n\n /**\n * @dev Returns the smallest of two numbers.\n */\n function min(uint256 a, uint256 b) internal pure returns (uint256) {\n return a \u003c b ? a : b;\n }\n\n /**\n * @dev Returns the average of two numbers. The result is rounded towards\n * zero.\n */\n function average(uint256 a, uint256 b) internal pure returns (uint256) {\n // (a + b) / 2 can overflow.\n return (a \u0026 b) + (a ^ b) / 2;\n }\n\n /**\n * @dev Returns the ceiling of the division of two numbers.\n *\n * This differs from standard division with `/` in that it rounds up instead\n * of rounding down.\n */\n function ceilDiv(uint256 a, uint256 b) internal pure returns (uint256) {\n // (a + b - 1) / b can overflow on addition, so we distribute.\n return a == 0 ? 0 : (a - 1) / b + 1;\n }\n\n /**\n * @notice Calculates floor(x * y / denominator) with full precision. Throws if result overflows a uint256 or denominator == 0\n * @dev Original credit to Remco Bloemen under MIT license (https://xn--2-umb.com/21/muldiv)\n * with further edits by Uniswap Labs also under MIT license.\n */\n function mulDiv(uint256 x, uint256 y, uint256 denominator) internal pure returns (uint256 result) {\n unchecked {\n // 512-bit multiply [prod1 prod0] = x * y. Compute the product mod 2^256 and mod 2^256 - 1, then use\n // use the Chinese Remainder Theorem to reconstruct the 512 bit result. The result is stored in two 256\n // variables such that product = prod1 * 2^256 + prod0.\n uint256 prod0; // Least significant 256 bits of the product\n uint256 prod1; // Most significant 256 bits of the product\n assembly {\n let mm := mulmod(x, y, not(0))\n prod0 := mul(x, y)\n prod1 := sub(sub(mm, prod0), lt(mm, prod0))\n }\n\n // Handle non-overflow cases, 256 by 256 division.\n if (prod1 == 0) {\n // Solidity will revert if denominator == 0, unlike the div opcode on its own.\n // The surrounding unchecked block does not change this fact.\n // See https://docs.soliditylang.org/en/latest/control-structures.html#checked-or-unchecked-arithmetic.\n return prod0 / denominator;\n }\n\n // Make sure the result is less than 2^256. Also prevents denominator == 0.\n require(denominator \u003e prod1, \"Math: mulDiv overflow\");\n\n ///////////////////////////////////////////////\n // 512 by 256 division.\n ///////////////////////////////////////////////\n\n // Make division exact by subtracting the remainder from [prod1 prod0].\n uint256 remainder;\n assembly {\n // Compute remainder using mulmod.\n remainder := mulmod(x, y, denominator)\n\n // Subtract 256 bit number from 512 bit number.\n prod1 := sub(prod1, gt(remainder, prod0))\n prod0 := sub(prod0, remainder)\n }\n\n // Factor powers of two out of denominator and compute largest power of two divisor of denominator. Always \u003e= 1.\n // See https://cs.stackexchange.com/q/138556/92363.\n\n // Does not overflow because the denominator cannot be zero at this stage in the function.\n uint256 twos = denominator \u0026 (~denominator + 1);\n assembly {\n // Divide denominator by twos.\n denominator := div(denominator, twos)\n\n // Divide [prod1 prod0] by twos.\n prod0 := div(prod0, twos)\n\n // Flip twos such that it is 2^256 / twos. If twos is zero, then it becomes one.\n twos := add(div(sub(0, twos), twos), 1)\n }\n\n // Shift in bits from prod1 into prod0.\n prod0 |= prod1 * twos;\n\n // Invert denominator mod 2^256. Now that denominator is an odd number, it has an inverse modulo 2^256 such\n // that denominator * inv = 1 mod 2^256. Compute the inverse by starting with a seed that is correct for\n // four bits. That is, denominator * inv = 1 mod 2^4.\n uint256 inverse = (3 * denominator) ^ 2;\n\n // Use the Newton-Raphson iteration to improve the precision. Thanks to Hensel's lifting lemma, this also works\n // in modular arithmetic, doubling the correct bits in each step.\n inverse *= 2 - denominator * inverse; // inverse mod 2^8\n inverse *= 2 - denominator * inverse; // inverse mod 2^16\n inverse *= 2 - denominator * inverse; // inverse mod 2^32\n inverse *= 2 - denominator * inverse; // inverse mod 2^64\n inverse *= 2 - denominator * inverse; // inverse mod 2^128\n inverse *= 2 - denominator * inverse; // inverse mod 2^256\n\n // Because the division is now exact we can divide by multiplying with the modular inverse of denominator.\n // This will give us the correct result modulo 2^256. Since the preconditions guarantee that the outcome is\n // less than 2^256, this is the final result. We don't need to compute the high bits of the result and prod1\n // is no longer required.\n result = prod0 * inverse;\n return result;\n }\n }\n\n /**\n * @notice Calculates x * y / denominator with full precision, following the selected rounding direction.\n */\n function mulDiv(uint256 x, uint256 y, uint256 denominator, Rounding rounding) internal pure returns (uint256) {\n uint256 result = mulDiv(x, y, denominator);\n if (rounding == Rounding.Up \u0026\u0026 mulmod(x, y, denominator) \u003e 0) {\n result += 1;\n }\n return result;\n }\n\n /**\n * @dev Returns the square root of a number. If the number is not a perfect square, the value is rounded down.\n *\n * Inspired by Henry S. Warren, Jr.'s \"Hacker's Delight\" (Chapter 11).\n */\n function sqrt(uint256 a) internal pure returns (uint256) {\n if (a == 0) {\n return 0;\n }\n\n // For our first guess, we get the biggest power of 2 which is smaller than the square root of the target.\n //\n // We know that the \"msb\" (most significant bit) of our target number `a` is a power of 2 such that we have\n // `msb(a) \u003c= a \u003c 2*msb(a)`. This value can be written `msb(a)=2**k` with `k=log2(a)`.\n //\n // This can be rewritten `2**log2(a) \u003c= a \u003c 2**(log2(a) + 1)`\n // → `sqrt(2**k) \u003c= sqrt(a) \u003c sqrt(2**(k+1))`\n // → `2**(k/2) \u003c= sqrt(a) \u003c 2**((k+1)/2) \u003c= 2**(k/2 + 1)`\n //\n // Consequently, `2**(log2(a) / 2)` is a good first approximation of `sqrt(a)` with at least 1 correct bit.\n uint256 result = 1 \u003c\u003c (log2(a) \u003e\u003e 1);\n\n // At this point `result` is an estimation with one bit of precision. We know the true value is a uint128,\n // since it is the square root of a uint256. Newton's method converges quadratically (precision doubles at\n // every iteration). We thus need at most 7 iteration to turn our partial result with one bit of precision\n // into the expected uint128 result.\n unchecked {\n result = (result + a / result) \u003e\u003e 1;\n result = (result + a / result) \u003e\u003e 1;\n result = (result + a / result) \u003e\u003e 1;\n result = (result + a / result) \u003e\u003e 1;\n result = (result + a / result) \u003e\u003e 1;\n result = (result + a / result) \u003e\u003e 1;\n result = (result + a / result) \u003e\u003e 1;\n return min(result, a / result);\n }\n }\n\n /**\n * @notice Calculates sqrt(a), following the selected rounding direction.\n */\n function sqrt(uint256 a, Rounding rounding) internal pure returns (uint256) {\n unchecked {\n uint256 result = sqrt(a);\n return result + (rounding == Rounding.Up \u0026\u0026 result * result \u003c a ? 1 : 0);\n }\n }\n\n /**\n * @dev Return the log in base 2, rounded down, of a positive value.\n * Returns 0 if given 0.\n */\n function log2(uint256 value) internal pure returns (uint256) {\n uint256 result = 0;\n unchecked {\n if (value \u003e\u003e 128 \u003e 0) {\n value \u003e\u003e= 128;\n result += 128;\n }\n if (value \u003e\u003e 64 \u003e 0) {\n value \u003e\u003e= 64;\n result += 64;\n }\n if (value \u003e\u003e 32 \u003e 0) {\n value \u003e\u003e= 32;\n result += 32;\n }\n if (value \u003e\u003e 16 \u003e 0) {\n value \u003e\u003e= 16;\n result += 16;\n }\n if (value \u003e\u003e 8 \u003e 0) {\n value \u003e\u003e= 8;\n result += 8;\n }\n if (value \u003e\u003e 4 \u003e 0) {\n value \u003e\u003e= 4;\n result += 4;\n }\n if (value \u003e\u003e 2 \u003e 0) {\n value \u003e\u003e= 2;\n result += 2;\n }\n if (value \u003e\u003e 1 \u003e 0) {\n result += 1;\n }\n }\n return result;\n }\n\n /**\n * @dev Return the log in base 2, following the selected rounding direction, of a positive value.\n * Returns 0 if given 0.\n */\n function log2(uint256 value, Rounding rounding) internal pure returns (uint256) {\n unchecked {\n uint256 result = log2(value);\n return result + (rounding == Rounding.Up \u0026\u0026 1 \u003c\u003c result \u003c value ? 1 : 0);\n }\n }\n\n /**\n * @dev Return the log in base 10, rounded down, of a positive value.\n * Returns 0 if given 0.\n */\n function log10(uint256 value) internal pure returns (uint256) {\n uint256 result = 0;\n unchecked {\n if (value \u003e= 10 ** 64) {\n value /= 10 ** 64;\n result += 64;\n }\n if (value \u003e= 10 ** 32) {\n value /= 10 ** 32;\n result += 32;\n }\n if (value \u003e= 10 ** 16) {\n value /= 10 ** 16;\n result += 16;\n }\n if (value \u003e= 10 ** 8) {\n value /= 10 ** 8;\n result += 8;\n }\n if (value \u003e= 10 ** 4) {\n value /= 10 ** 4;\n result += 4;\n }\n if (value \u003e= 10 ** 2) {\n value /= 10 ** 2;\n result += 2;\n }\n if (value \u003e= 10 ** 1) {\n result += 1;\n }\n }\n return result;\n }\n\n /**\n * @dev Return the log in base 10, following the selected rounding direction, of a positive value.\n * Returns 0 if given 0.\n */\n function log10(uint256 value, Rounding rounding) internal pure returns (uint256) {\n unchecked {\n uint256 result = log10(value);\n return result + (rounding == Rounding.Up \u0026\u0026 10 ** result \u003c value ? 1 : 0);\n }\n }\n\n /**\n * @dev Return the log in base 256, rounded down, of a positive value.\n * Returns 0 if given 0.\n *\n * Adding one to the result gives the number of pairs of hex symbols needed to represent `value` as a hex string.\n */\n function log256(uint256 value) internal pure returns (uint256) {\n uint256 result = 0;\n unchecked {\n if (value \u003e\u003e 128 \u003e 0) {\n value \u003e\u003e= 128;\n result += 16;\n }\n if (value \u003e\u003e 64 \u003e 0) {\n value \u003e\u003e= 64;\n result += 8;\n }\n if (value \u003e\u003e 32 \u003e 0) {\n value \u003e\u003e= 32;\n result += 4;\n }\n if (value \u003e\u003e 16 \u003e 0) {\n value \u003e\u003e= 16;\n result += 2;\n }\n if (value \u003e\u003e 8 \u003e 0) {\n result += 1;\n }\n }\n return result;\n }\n\n /**\n * @dev Return the log in base 256, following the selected rounding direction, of a positive value.\n * Returns 0 if given 0.\n */\n function log256(uint256 value, Rounding rounding) internal pure returns (uint256) {\n unchecked {\n uint256 result = log256(value);\n return result + (rounding == Rounding.Up \u0026\u0026 1 \u003c\u003c (result \u003c\u003c 3) \u003c value ? 1 : 0);\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/utils/math/SignedMath.sol\n\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/math/SignedMath.sol)\n\n/**\n * @dev Standard signed math utilities missing in the Solidity language.\n */\nlibrary SignedMath {\n /**\n * @dev Returns the largest of two signed numbers.\n */\n function max(int256 a, int256 b) internal pure returns (int256) {\n return a \u003e b ? a : b;\n }\n\n /**\n * @dev Returns the smallest of two signed numbers.\n */\n function min(int256 a, int256 b) internal pure returns (int256) {\n return a \u003c b ? a : b;\n }\n\n /**\n * @dev Returns the average of two signed numbers without overflow.\n * The result is rounded towards zero.\n */\n function average(int256 a, int256 b) internal pure returns (int256) {\n // Formula from the book \"Hacker's Delight\"\n int256 x = (a \u0026 b) + ((a ^ b) \u003e\u003e 1);\n return x + (int256(uint256(x) \u003e\u003e 255) \u0026 (a ^ b));\n }\n\n /**\n * @dev Returns the absolute unsigned value of a signed value.\n */\n function abs(int256 n) internal pure returns (uint256) {\n unchecked {\n // must be unchecked in order to support `n = type(int256).min`\n return uint256(n \u003e= 0 ? n : -n);\n }\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// 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/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/InterfaceSummit.sol\n\ninterface InterfaceSummit {\n // ══════════════════════════════════════════ ACCEPT AGENT STATEMENTS ══════════════════════════════════════════════\n\n /**\n * @notice Accepts a receipt, which local `AgentManager` verified to have been signed by an active Notary.\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 * - Notary who signed the receipt is referenced as the \"Receipt Notary\".\n * - Notary who signed the attestation on destination chain is referenced as the \"Attestation Notary\".\n * \u003e Will revert if any of these is true:\n * \u003e - Called by anyone other than local `AgentManager`.\n * \u003e - Receipt body payload is not properly formatted.\n * \u003e - Receipt signer is in Dispute.\n * \u003e - Receipt's snapshot root is unknown.\n * @param rcptNotaryIndex Index of Receipt Notary in Agent Merkle Tree\n * @param attNotaryIndex Index of Attestation Notary in Agent Merkle Tree\n * @param sigIndex Index of stored Notary signature\n * @param attNonce Nonce of the attestation used for proving the executed message\n * @param paddedTips Padded encoded paid tips information\n * @param rcptPayload Raw payload with message execution receipt\n * @return wasAccepted Whether the receipt was accepted\n */\n function acceptReceipt(\n uint32 rcptNotaryIndex,\n uint32 attNotaryIndex,\n uint256 sigIndex,\n uint32 attNonce,\n uint256 paddedTips,\n bytes memory rcptPayload\n ) external returns (bool wasAccepted);\n\n /**\n * @notice Accepts a snapshot, which local `AgentManager` verified to have been signed by an active Guard.\n * \u003e Snapshot is a list of states for a set of Origin contracts residing on any of the chains.\n * All the states in the Guard-signed snapshot become available for Notary signing.\n * \u003e Will revert if any of these is true:\n * \u003e - Called by anyone other than local `AgentManager`.\n * \u003e - Snapshot payload is not properly formatted.\n * \u003e - Snapshot contains a state older then the Guard has previously submitted.\n * @param guardIndex Index of Guard in Agent Merkle Tree\n * @param sigIndex Index of stored Agent signature\n * @param snapPayload Raw payload with snapshot data\n */\n function acceptGuardSnapshot(uint32 guardIndex, uint256 sigIndex, bytes memory snapPayload) external;\n\n /**\n * @notice Accepts a snapshot, which local `AgentManager` verified to have been signed by an active Notary.\n * \u003e Snapshot is a list of states for a set of Origin contracts residing on any of the chains.\n * Snapshot Merkle Root is calculated and saved for valid snapshots, i.e.\n * snapshots which are only using states previously submitted by any of the Guards.\n * - Notary could use states singed by the same of different Guards 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 - Called by anyone other than local `AgentManager`.\n * \u003e - Snapshot payload is not properly formatted.\n * \u003e - Snapshot contains a state older then the Notary has previously submitted.\n * \u003e - Snapshot contains a state that no Guard has previously submitted.\n * @param notaryIndex Index of Notary in Agent Merkle Tree\n * @param sigIndex Index of stored Agent signature\n * @param agentRoot Current root of the Agent Merkle Tree\n * @param snapPayload Raw payload with snapshot data\n * @return attPayload Raw payload with data for attestation derived from Notary snapshot.\n */\n function acceptNotarySnapshot(uint32 notaryIndex, uint256 sigIndex, bytes32 agentRoot, bytes memory snapPayload)\n external\n returns (bytes memory attPayload);\n\n // ════════════════════════════════════════════════ TIPS LOGIC ═════════════════════════════════════════════════════\n\n /**\n * @notice Distributes tips using the first Receipt from the \"receipt quarantine queue\".\n * Possible scenarios:\n * - Receipt queue is empty =\u003e does nothing\n * - Receipt optimistic period is not over =\u003e does nothing\n * - Either of Notaries present in Receipt was slashed =\u003e receipt is deleted from the queue\n * - Either of Notaries present in Receipt in Dispute =\u003e receipt is moved to the end of queue\n * - None of the above =\u003e receipt tips are distributed\n * @dev Returned value makes it possible to do the following: `while (distributeTips()) {}`\n * @return queuePopped Whether the first element was popped from the queue\n */\n function distributeTips() external returns (bool queuePopped);\n\n /**\n * @notice Withdraws locked base message tips from requested domain Origin to the recipient.\n * This is done by a call to a local Origin contract, or by a manager message to the remote chain.\n * @dev This will revert, if the pending balance of origin tips (earned-claimed) is lower than requested.\n * @param origin Domain of chain to withdraw tips on\n * @param amount Amount of tips to withdraw\n */\n function withdrawTips(uint32 origin, uint256 amount) external;\n\n // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════\n\n /**\n * @notice Returns earned and claimed tips for the actor.\n * Note: Tips for address(0) belong to the Treasury.\n * @param actor Address of the actor\n * @param origin Domain where the tips were initially paid\n * @return earned Total amount of origin tips the actor has earned so far\n * @return claimed Total amount of origin tips the actor has claimed so far\n */\n function actorTips(address actor, uint32 origin) external view returns (uint128 earned, uint128 claimed);\n\n /**\n * @notice Returns the amount of receipts in the \"Receipt Quarantine Queue\".\n */\n function receiptQueueLength() external view returns (uint256);\n\n /**\n * @notice Returns the state with the highest known nonce\n * submitted by any of the currently active Guards.\n * @param origin Domain of origin chain\n * @return statePayload Raw payload with latest active Guard state for origin\n */\n function getLatestState(uint32 origin) external view returns (bytes memory statePayload);\n}\n\n// node_modules/@openzeppelin/contracts/utils/Strings.sol\n\n// OpenZeppelin Contracts (last updated v4.9.0) (utils/Strings.sol)\n\n/**\n * @dev String operations.\n */\nlibrary Strings {\n bytes16 private constant _SYMBOLS = \"0123456789abcdef\";\n uint8 private constant _ADDRESS_LENGTH = 20;\n\n /**\n * @dev Converts a `uint256` to its ASCII `string` decimal representation.\n */\n function toString(uint256 value) internal pure returns (string memory) {\n unchecked {\n uint256 length = Math.log10(value) + 1;\n string memory buffer = new string(length);\n uint256 ptr;\n /// @solidity memory-safe-assembly\n assembly {\n ptr := add(buffer, add(32, length))\n }\n while (true) {\n ptr--;\n /// @solidity memory-safe-assembly\n assembly {\n mstore8(ptr, byte(mod(value, 10), _SYMBOLS))\n }\n value /= 10;\n if (value == 0) break;\n }\n return buffer;\n }\n }\n\n /**\n * @dev Converts a `int256` to its ASCII `string` decimal representation.\n */\n function toString(int256 value) internal pure returns (string memory) {\n return string(abi.encodePacked(value \u003c 0 ? \"-\" : \"\", toString(SignedMath.abs(value))));\n }\n\n /**\n * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation.\n */\n function toHexString(uint256 value) internal pure returns (string memory) {\n unchecked {\n return toHexString(value, Math.log256(value) + 1);\n }\n }\n\n /**\n * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length.\n */\n function toHexString(uint256 value, uint256 length) internal pure returns (string memory) {\n bytes memory buffer = new bytes(2 * length + 2);\n buffer[0] = \"0\";\n buffer[1] = \"x\";\n for (uint256 i = 2 * length + 1; i \u003e 1; --i) {\n buffer[i] = _SYMBOLS[value \u0026 0xf];\n value \u003e\u003e= 4;\n }\n require(value == 0, \"Strings: hex length insufficient\");\n return string(buffer);\n }\n\n /**\n * @dev Converts an `address` with fixed length of 20 bytes to its not checksummed ASCII `string` hexadecimal representation.\n */\n function toHexString(address addr) internal pure returns (string memory) {\n return toHexString(uint256(uint160(addr)), _ADDRESS_LENGTH);\n }\n\n /**\n * @dev Returns true if the two strings are equal.\n */\n function equal(string memory a, string memory b) internal pure returns (bool) {\n return keccak256(bytes(a)) == keccak256(bytes(b));\n }\n}\n\n// node_modules/@openzeppelin/contracts-upgradeable/utils/ContextUpgradeable.sol\n\n// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)\n\n/**\n * @dev Provides information about the current execution context, including the\n * sender of the transaction and its data. While these are generally available\n * via msg.sender and msg.data, they should not be accessed in such a direct\n * manner, since when dealing with meta-transactions the account sending and\n * paying for execution may not be the actual sender (as far as an application\n * is concerned).\n *\n * This contract is only required for intermediate, library-like contracts.\n */\nabstract contract ContextUpgradeable is Initializable {\n function __Context_init() internal onlyInitializing {\n }\n\n function __Context_init_unchained() internal onlyInitializing {\n }\n function _msgSender() internal view virtual returns (address) {\n return msg.sender;\n }\n\n function _msgData() internal view virtual returns (bytes calldata) {\n return msg.data;\n }\n\n /**\n * @dev This empty reserved space is put in place to allow future versions to add new\n * variables without shifting down storage in the inheritance chain.\n * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\n */\n uint256[50] private __gap;\n}\n\n// contracts/libs/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/utils/cryptography/ECDSA.sol\n\n// OpenZeppelin Contracts (last updated v4.9.0) (utils/cryptography/ECDSA.sol)\n\n/**\n * @dev Elliptic Curve Digital Signature Algorithm (ECDSA) operations.\n *\n * These functions can be used to verify that a message was signed by the holder\n * of the private keys of a given address.\n */\nlibrary ECDSA {\n enum RecoverError {\n NoError,\n InvalidSignature,\n InvalidSignatureLength,\n InvalidSignatureS,\n InvalidSignatureV // Deprecated in v4.8\n }\n\n function _throwError(RecoverError error) private pure {\n if (error == RecoverError.NoError) {\n return; // no error: do nothing\n } else if (error == RecoverError.InvalidSignature) {\n revert(\"ECDSA: invalid signature\");\n } else if (error == RecoverError.InvalidSignatureLength) {\n revert(\"ECDSA: invalid signature length\");\n } else if (error == RecoverError.InvalidSignatureS) {\n revert(\"ECDSA: invalid signature 's' value\");\n }\n }\n\n /**\n * @dev Returns the address that signed a hashed message (`hash`) with\n * `signature` or error string. This address can then be used for verification purposes.\n *\n * The `ecrecover` EVM opcode allows for malleable (non-unique) signatures:\n * this function rejects them by requiring the `s` value to be in the lower\n * half order, and the `v` value to be either 27 or 28.\n *\n * IMPORTANT: `hash` _must_ be the result of a hash operation for the\n * verification to be secure: it is possible to craft signatures that\n * recover to arbitrary addresses for non-hashed data. A safe way to ensure\n * this is by receiving a hash of the original message (which may otherwise\n * be too long), and then calling {toEthSignedMessageHash} on it.\n *\n * Documentation for signature generation:\n * - with https://web3js.readthedocs.io/en/v1.3.4/web3-eth-accounts.html#sign[Web3.js]\n * - with https://docs.ethers.io/v5/api/signer/#Signer-signMessage[ethers]\n *\n * _Available since v4.3._\n */\n function tryRecover(bytes32 hash, bytes memory signature) internal pure returns (address, RecoverError) {\n if (signature.length == 65) {\n bytes32 r;\n bytes32 s;\n uint8 v;\n // ecrecover takes the signature parameters, and the only way to get them\n // currently is to use assembly.\n /// @solidity memory-safe-assembly\n assembly {\n r := mload(add(signature, 0x20))\n s := mload(add(signature, 0x40))\n v := byte(0, mload(add(signature, 0x60)))\n }\n return tryRecover(hash, v, r, s);\n } else {\n return (address(0), RecoverError.InvalidSignatureLength);\n }\n }\n\n /**\n * @dev Returns the address that signed a hashed message (`hash`) with\n * `signature`. This address can then be used for verification purposes.\n *\n * The `ecrecover` EVM opcode allows for malleable (non-unique) signatures:\n * this function rejects them by requiring the `s` value to be in the lower\n * half order, and the `v` value to be either 27 or 28.\n *\n * IMPORTANT: `hash` _must_ be the result of a hash operation for the\n * verification to be secure: it is possible to craft signatures that\n * recover to arbitrary addresses for non-hashed data. A safe way to ensure\n * this is by receiving a hash of the original message (which may otherwise\n * be too long), and then calling {toEthSignedMessageHash} on it.\n */\n function recover(bytes32 hash, bytes memory signature) internal pure returns (address) {\n (address recovered, RecoverError error) = tryRecover(hash, signature);\n _throwError(error);\n return recovered;\n }\n\n /**\n * @dev Overload of {ECDSA-tryRecover} that receives the `r` and `vs` short-signature fields separately.\n *\n * See https://eips.ethereum.org/EIPS/eip-2098[EIP-2098 short signatures]\n *\n * _Available since v4.3._\n */\n function tryRecover(bytes32 hash, bytes32 r, bytes32 vs) internal pure returns (address, RecoverError) {\n bytes32 s = vs \u0026 bytes32(0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff);\n uint8 v = uint8((uint256(vs) \u003e\u003e 255) + 27);\n return tryRecover(hash, v, r, s);\n }\n\n /**\n * @dev Overload of {ECDSA-recover} that receives the `r and `vs` short-signature fields separately.\n *\n * _Available since v4.2._\n */\n function recover(bytes32 hash, bytes32 r, bytes32 vs) internal pure returns (address) {\n (address recovered, RecoverError error) = tryRecover(hash, r, vs);\n _throwError(error);\n return recovered;\n }\n\n /**\n * @dev Overload of {ECDSA-tryRecover} that receives the `v`,\n * `r` and `s` signature fields separately.\n *\n * _Available since v4.3._\n */\n function tryRecover(bytes32 hash, uint8 v, bytes32 r, bytes32 s) internal pure returns (address, RecoverError) {\n // EIP-2 still allows signature malleability for ecrecover(). Remove this possibility and make the signature\n // unique. Appendix F in the Ethereum Yellow paper (https://ethereum.github.io/yellowpaper/paper.pdf), defines\n // the valid range for s in (301): 0 \u003c s \u003c secp256k1n ÷ 2 + 1, and for v in (302): v ∈ {27, 28}. Most\n // signatures from current libraries generate a unique signature with an s-value in the lower half order.\n //\n // If your library generates malleable signatures, such as s-values in the upper range, calculate a new s-value\n // with 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141 - s1 and flip v from 27 to 28 or\n // vice versa. If your library also generates signatures with 0/1 for v instead 27/28, add 27 to v to accept\n // these malleable signatures as well.\n if (uint256(s) \u003e 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0) {\n return (address(0), RecoverError.InvalidSignatureS);\n }\n\n // If the signature is valid (and not malleable), return the signer address\n address signer = ecrecover(hash, v, r, s);\n if (signer == address(0)) {\n return (address(0), RecoverError.InvalidSignature);\n }\n\n return (signer, RecoverError.NoError);\n }\n\n /**\n * @dev Overload of {ECDSA-recover} that receives the `v`,\n * `r` and `s` signature fields separately.\n */\n function recover(bytes32 hash, uint8 v, bytes32 r, bytes32 s) internal pure returns (address) {\n (address recovered, RecoverError error) = tryRecover(hash, v, r, s);\n _throwError(error);\n return recovered;\n }\n\n /**\n * @dev Returns an Ethereum Signed Message, created from a `hash`. This\n * produces hash corresponding to the one signed with the\n * https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`]\n * JSON-RPC method as part of EIP-191.\n *\n * See {recover}.\n */\n function toEthSignedMessageHash(bytes32 hash) internal pure returns (bytes32 message) {\n // 32 is the length in bytes of hash,\n // enforced by the type signature above\n /// @solidity memory-safe-assembly\n assembly {\n mstore(0x00, \"\\x19Ethereum Signed Message:\\n32\")\n mstore(0x1c, hash)\n message := keccak256(0x00, 0x3c)\n }\n }\n\n /**\n * @dev Returns an Ethereum Signed Message, created from `s`. This\n * produces hash corresponding to the one signed with the\n * https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`]\n * JSON-RPC method as part of EIP-191.\n *\n * See {recover}.\n */\n function toEthSignedMessageHash(bytes memory s) internal pure returns (bytes32) {\n return keccak256(abi.encodePacked(\"\\x19Ethereum Signed Message:\\n\", Strings.toString(s.length), s));\n }\n\n /**\n * @dev Returns an Ethereum Signed Typed Data, created from a\n * `domainSeparator` and a `structHash`. This produces hash corresponding\n * to the one signed with the\n * https://eips.ethereum.org/EIPS/eip-712[`eth_signTypedData`]\n * JSON-RPC method as part of EIP-712.\n *\n * See {recover}.\n */\n function toTypedDataHash(bytes32 domainSeparator, bytes32 structHash) internal pure returns (bytes32 data) {\n /// @solidity memory-safe-assembly\n assembly {\n let ptr := mload(0x40)\n mstore(ptr, \"\\x19\\x01\")\n mstore(add(ptr, 0x02), domainSeparator)\n mstore(add(ptr, 0x22), structHash)\n data := keccak256(ptr, 0x42)\n }\n }\n\n /**\n * @dev Returns an Ethereum Signed Data with intended validator, created from a\n * `validator` and `data` according to the version 0 of EIP-191.\n *\n * See {recover}.\n */\n function toDataWithIntendedValidatorHash(address validator, bytes memory data) internal pure returns (bytes32) {\n return keccak256(abi.encodePacked(\"\\x19\\x00\", validator, data));\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/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/inbox/StatementInbox.sol\n\n// ══════════════════════════════ LIBRARY IMPORTS ══════════════════════════════\n\n// ═════════════════════════════ INTERNAL IMPORTS ══════════════════════════════\n\n// ═════════════════════════════ EXTERNAL IMPORTS ══════════════════════════════\n\n/// @notice `StatementInbox` is the entry point for all agent-signed statements. It verifies the\n/// agent signatures, and passes the unsigned statements to the contract to consume it via `acceptX` functions. Is is\n/// also used to verify the agent-signed statements and initiate the agent slashing, should the statement be invalid.\n/// `StatementInbox` is responsible for the following:\n/// - Accepting State and Receipt Reports to initiate a dispute between Guard and Notary.\n/// - Storing all the Guard Reports with the Guard signature leading to a dispute.\n/// - Verifying State/State Reports referencing the local chain and slashing the signer if statement is invalid.\n/// - Verifying Receipt/Receipt Reports referencing the local chain and slashing the signer if statement is invalid.\nabstract contract StatementInbox is MessagingBase, StatementInboxEvents, IStatementInbox {\n using AttestationLib for bytes;\n using ReceiptLib for bytes;\n using StateLib for bytes;\n using SnapshotLib for bytes;\n\n struct StoredReport {\n uint256 sigIndex;\n bytes statementPayload;\n }\n\n // ══════════════════════════════════════════════════ STORAGE ══════════════════════════════════════════════════════\n\n address public agentManager;\n address public origin;\n address public destination;\n\n // TODO: optimize this\n bytes[] internal _storedSignatures;\n StoredReport[] internal _storedReports;\n\n /// @dev gap for upgrade safety\n uint256[45] private __GAP; // solhint-disable-line var-name-mixedcase\n\n // ════════════════════════════════════════════════ INITIALIZER ════════════════════════════════════════════════════\n\n /// @dev Initializes the contract:\n /// - Sets up `msg.sender` as the owner of the contract.\n /// - Sets up `agentManager`, `origin`, and `destination`.\n // solhint-disable-next-line func-name-mixedcase\n function __StatementInbox_init(address agentManager_, address origin_, address destination_)\n internal\n onlyInitializing\n {\n agentManager = agentManager_;\n origin = origin_;\n destination = destination_;\n __Ownable2Step_init();\n }\n\n // ══════════════════════════════════════════ SUBMIT AGENT STATEMENTS ══════════════════════════════════════════════\n\n /// @inheritdoc IStatementInbox\n // solhint-disable-next-line ordering\n function submitStateReportWithSnapshot(\n uint8 stateIndex,\n bytes memory srSignature,\n bytes memory snapPayload,\n bytes memory snapSignature\n ) external returns (bool wasAccepted) {\n // This will revert if payload is not a snapshot\n Snapshot snapshot = snapPayload.castToSnapshot();\n // This will revert if the snapshot signer is not a known Notary\n (AgentStatus memory notaryStatus,) =\n _verifySnapshot({snapshot: snapshot, snapSignature: snapSignature, verifyNotary: true});\n // Notary needs to be Active/Unstaking\n notaryStatus.verifyActiveUnstaking();\n // Check if Notary is active on this chain\n _verifyNotaryDomain(notaryStatus.domain);\n // This will revert if state index is out of range\n State state = snapshot.state(stateIndex);\n // This will revert if the report signer is not an known Guard\n (AgentStatus memory guardStatus,) = _verifyStateReport(state, srSignature);\n // Check that Guard is active\n guardStatus.verifyActive();\n _saveReport(state.unwrap().clone(), srSignature);\n // This will revert if either actor is already in dispute\n IAgentManager(agentManager).openDispute(guardStatus.index, notaryStatus.index);\n return true;\n }\n\n /// @inheritdoc IStatementInbox\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 // This will revert if payload is not a snapshot\n Snapshot snapshot = snapPayload.castToSnapshot();\n // This will revert if state index is out of range\n State state = snapshot.state(stateIndex);\n // This will revert if the report signer is not an known Guard\n (AgentStatus memory guardStatus,) = _verifyStateReport(state, srSignature);\n // Check that Guard is active\n guardStatus.verifyActive();\n // This will revert if payload is not an attestation\n Attestation att = attPayload.castToAttestation();\n // This will revert if signer is not an known Notary\n (AgentStatus memory notaryStatus,) = _verifyAttestation(att, attSignature);\n // Notary needs to be Active/Unstaking\n notaryStatus.verifyActiveUnstaking();\n // Check if Notary is active on this chain\n _verifyNotaryDomain(notaryStatus.domain);\n if (snapshot.calculateRoot() != att.snapRoot()) revert IncorrectSnapshotRoot();\n _saveReport(state.unwrap().clone(), srSignature);\n // This will revert if either actor is already in dispute\n IAgentManager(agentManager).openDispute(guardStatus.index, notaryStatus.index);\n return true;\n }\n\n /// @inheritdoc IStatementInbox\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 // This will revert if payload is not a state\n State state = statePayload.castToState();\n // This will revert if the report signer is not an known Guard\n (AgentStatus memory guardStatus,) = _verifyStateReport(state, srSignature);\n // Check that Guard is active\n guardStatus.verifyActive();\n // This will revert if payload is not an attestation\n Attestation att = attPayload.castToAttestation();\n // This will revert if signer is not a known Notary\n (AgentStatus memory notaryStatus,) = _verifyAttestation(att, attSignature);\n // Notary needs to be Active/Unstaking\n notaryStatus.verifyActiveUnstaking();\n // Check if Notary is active on this chain\n _verifyNotaryDomain(notaryStatus.domain);\n // This will revert if any of these is true:\n // - Attestation root is not equal to Merkle Root derived from State and Snapshot Proof.\n // - Snapshot Proof's first element does not match the State metadata.\n // - Snapshot Proof length exceeds Snapshot tree Height.\n // - State index is out of range.\n _verifySnapshotMerkle(att, stateIndex, state, snapProof);\n _saveReport(statePayload, srSignature);\n // This will revert if either actor is already in dispute\n IAgentManager(agentManager).openDispute(guardStatus.index, notaryStatus.index);\n return true;\n }\n\n // ══════════════════════════════════════════ VERIFY AGENT STATEMENTS ══════════════════════════════════════════════\n\n /// @inheritdoc IStatementInbox\n function verifyReceipt(bytes memory rcptPayload, bytes memory rcptSignature)\n external\n returns (bool isValidReceipt)\n {\n // This will revert if payload is not a receipt\n Receipt rcpt = rcptPayload.castToReceipt();\n // This will revert if the attestation signer is not a known Notary\n (AgentStatus memory status, address notary) = _verifyReceipt(rcpt, rcptSignature);\n // Notary needs to be Active/Unstaking\n status.verifyActiveUnstaking();\n isValidReceipt = IExecutionHub(destination).isValidReceipt(rcptPayload);\n if (!isValidReceipt) {\n emit InvalidReceipt(rcptPayload, rcptSignature);\n IAgentManager(agentManager).slashAgent(status.domain, notary, msg.sender);\n }\n }\n\n /// @inheritdoc IStatementInbox\n function verifyReceiptReport(bytes memory rcptPayload, bytes memory rrSignature)\n external\n returns (bool isValidReport)\n {\n // This will revert if payload is not a receipt\n Receipt rcpt = rcptPayload.castToReceipt();\n // This will revert if the report signer is not a known Guard\n (AgentStatus memory status, address guard) = _verifyReceiptReport(rcpt, rrSignature);\n // Guard needs to be Active/Unstaking\n status.verifyActiveUnstaking();\n // Report is valid IF AND ONLY IF the reported receipt in invalid\n isValidReport = !IExecutionHub(destination).isValidReceipt(rcptPayload);\n if (!isValidReport) {\n emit InvalidReceiptReport(rcptPayload, rrSignature);\n IAgentManager(agentManager).slashAgent(status.domain, guard, msg.sender);\n }\n }\n\n /// @inheritdoc IStatementInbox\n function verifyStateWithAttestation(\n uint8 stateIndex,\n bytes memory snapPayload,\n bytes memory attPayload,\n bytes memory attSignature\n ) external returns (bool isValidState) {\n // This will revert if payload is not an attestation\n Attestation att = attPayload.castToAttestation();\n // This will revert if the attestation signer is not a known Notary\n (AgentStatus memory status, address notary) = _verifyAttestation(att, attSignature);\n // Notary needs to be Active/Unstaking\n status.verifyActiveUnstaking();\n // This will revert if payload is not a snapshot\n Snapshot snapshot = snapPayload.castToSnapshot();\n if (snapshot.calculateRoot() != att.snapRoot()) revert IncorrectSnapshotRoot();\n // This will revert if state does not refer to this chain\n bytes memory statePayload = snapshot.state(stateIndex).unwrap().clone();\n isValidState = IStateHub(origin).isValidState(statePayload);\n if (!isValidState) {\n emit InvalidStateWithAttestation(stateIndex, statePayload, attPayload, attSignature);\n IAgentManager(agentManager).slashAgent(status.domain, notary, msg.sender);\n }\n }\n\n /// @inheritdoc IStatementInbox\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 // This will revert if payload is not an attestation\n Attestation att = attPayload.castToAttestation();\n // This will revert if the attestation signer is not a known Notary\n (AgentStatus memory status, address notary) = _verifyAttestation(att, attSignature);\n // Notary needs to be Active/Unstaking\n status.verifyActiveUnstaking();\n // This will revert if payload is not a state\n State state = statePayload.castToState();\n // This will revert if any of these is true:\n // - Attestation root is not equal to Merkle Root derived from State and Snapshot Proof.\n // - Snapshot Proof's first element does not match the State metadata.\n // - Snapshot Proof length exceeds Snapshot tree Height.\n // - State index is out of range.\n _verifySnapshotMerkle(att, stateIndex, state, snapProof);\n // This will revert if state does not refer to this chain\n isValidState = IStateHub(origin).isValidState(statePayload);\n if (!isValidState) {\n emit InvalidStateWithAttestation(stateIndex, statePayload, attPayload, attSignature);\n IAgentManager(agentManager).slashAgent(status.domain, notary, msg.sender);\n }\n }\n\n /// @inheritdoc IStatementInbox\n function verifyStateWithSnapshot(uint8 stateIndex, bytes memory snapPayload, bytes memory snapSignature)\n external\n returns (bool isValidState)\n {\n // This will revert if payload is not a snapshot\n Snapshot snapshot = snapPayload.castToSnapshot();\n // This will revert if the snapshot signer is not a known Guard/Notary\n (AgentStatus memory status, address agent) =\n _verifySnapshot({snapshot: snapshot, snapSignature: snapSignature, verifyNotary: false});\n // Agent needs to be Active/Unstaking\n status.verifyActiveUnstaking();\n // This will revert if state does not refer to this chain\n isValidState = IStateHub(origin).isValidState(snapshot.state(stateIndex).unwrap().clone());\n if (!isValidState) {\n emit InvalidStateWithSnapshot(stateIndex, snapPayload, snapSignature);\n IAgentManager(agentManager).slashAgent(status.domain, agent, msg.sender);\n }\n }\n\n /// @inheritdoc IStatementInbox\n function verifyStateReport(bytes memory statePayload, bytes memory srSignature)\n external\n returns (bool isValidReport)\n {\n // This will revert if payload is not a state\n State state = statePayload.castToState();\n // This will revert if the report signer is not a known Guard\n (AgentStatus memory status, address guard) = _verifyStateReport(state, srSignature);\n // Guard needs to be Active/Unstaking\n status.verifyActiveUnstaking();\n // Report is valid IF AND ONLY IF the reported state in invalid\n // This will revert if the reported state does not refer to this chain\n isValidReport = !IStateHub(origin).isValidState(statePayload);\n if (!isValidReport) {\n emit InvalidStateReport(statePayload, srSignature);\n IAgentManager(agentManager).slashAgent(status.domain, guard, msg.sender);\n }\n }\n\n // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════\n\n /// @inheritdoc IStatementInbox\n function getReportsAmount() external view returns (uint256) {\n return _storedReports.length;\n }\n\n /// @inheritdoc IStatementInbox\n function getGuardReport(uint256 index)\n external\n view\n returns (bytes memory statementPayload, bytes memory reportSignature)\n {\n if (index \u003e= _storedReports.length) revert IndexOutOfRange();\n StoredReport memory storedReport = _storedReports[index];\n statementPayload = storedReport.statementPayload;\n reportSignature = _storedSignatures[storedReport.sigIndex];\n }\n\n /// @inheritdoc IStatementInbox\n function getStoredSignature(uint256 index) external view returns (bytes memory) {\n return _storedSignatures[index];\n }\n\n // ══════════════════════════════════════════════ INTERNAL LOGIC ═══════════════════════════════════════════════════\n\n /// @dev Saves the statement reported by Guard as invalid and the Guard Report signature.\n function _saveReport(bytes memory statementPayload, bytes memory reportSignature) internal {\n uint256 sigIndex = _saveSignature(reportSignature);\n _storedReports.push(StoredReport(sigIndex, statementPayload));\n }\n\n /// @dev Saves the signature and returns its index.\n function _saveSignature(bytes memory signature) internal returns (uint256 sigIndex) {\n sigIndex = _storedSignatures.length;\n _storedSignatures.push(signature);\n }\n\n // ═══════════════════════════════════════════════ AGENT CHECKS ════════════════════════════════════════════════════\n\n /**\n * @dev Recovers a signer from a hashed message, and a EIP-191 signature for it.\n * Will revert, if the signer is not a known agent.\n * @dev Agent flag could be any of these: Active/Unstaking/Resting/Fraudulent/Slashed\n * Further checks need to be performed in a caller function.\n * @param hashedStatement Hash of the statement that was signed by an Agent\n * @param signature Agent signature for the hashed statement\n * @return status Struct representing agent status:\n * - flag Unknown/Active/Unstaking/Resting/Fraudulent/Slashed\n * - domain Domain where agent is/was active\n * - index Index of agent in the Agent Merkle Tree\n * @return agent Agent that signed the statement\n */\n function _recoverAgent(bytes32 hashedStatement, bytes memory signature)\n internal\n view\n returns (AgentStatus memory status, address agent)\n {\n bytes32 ethSignedMsg = ECDSA.toEthSignedMessageHash(hashedStatement);\n agent = ECDSA.recover(ethSignedMsg, signature);\n status = IAgentManager(agentManager).agentStatus(agent);\n // Discard signature of unknown agents.\n // Further flag checks are supposed to be performed in a caller function.\n status.verifyKnown();\n }\n\n /// @dev Verifies that Notary signature is active on local domain.\n function _verifyNotaryDomain(uint32 notaryDomain) internal view {\n // Notary needs to be from the local domain (if contract is not deployed on Synapse Chain).\n // Or Notary could be from any domain (if contract is deployed on Synapse Chain).\n if (notaryDomain != localDomain \u0026\u0026 localDomain != synapseDomain) revert IncorrectAgentDomain();\n }\n\n // ════════════════════════════════════════ ATTESTATION RELATED CHECKS ═════════════════════════════════════════════\n\n /**\n * @dev Internal function to verify the signed attestation payload.\n * Reverts if any of these is true:\n * - Attestation signer is not a known Notary.\n * @param att Typed memory view over attestation payload\n * @param attSignature Notary signature for the attestation\n * @return status Struct representing agent status, see {_recoverAgent}\n * @return notary Notary that signed the snapshot\n */\n function _verifyAttestation(Attestation att, bytes memory attSignature)\n internal\n view\n returns (AgentStatus memory status, address notary)\n {\n // This will revert if signer is not a known agent\n (status, notary) = _recoverAgent(att.hashValid(), attSignature);\n // Attestation signer needs to be a Notary, not a Guard\n if (status.domain == 0) revert AgentNotNotary();\n }\n\n /**\n * @dev Internal function to verify the signed attestation report payload.\n * Reverts if any of these is true:\n * - Report signer is not a known Guard.\n * @param att Typed memory view over attestation payload that Guard reports as invalid\n * @param arSignature Guard signature for the \"invalid attestation\" report\n * @return status Struct representing guard status, see {_recoverAgent}\n * @return guard Guard that signed the report\n */\n function _verifyAttestationReport(Attestation att, bytes memory arSignature)\n internal\n view\n returns (AgentStatus memory status, address guard)\n {\n // This will revert if signer is not a known agent\n (status, guard) = _recoverAgent(att.hashInvalid(), arSignature);\n // Report signer needs to be a Guard, not a Notary\n if (status.domain != 0) revert AgentNotGuard();\n }\n\n // ══════════════════════════════════════════ RECEIPT RELATED CHECKS ═══════════════════════════════════════════════\n\n /**\n * @dev Internal function to verify the signed receipt payload.\n * Reverts if any of these is true:\n * - Receipt signer is not a known Notary.\n * @param rcpt Typed memory view over receipt payload\n * @param rcptSignature Notary signature for the receipt\n * @return status Struct representing agent status, see {_recoverAgent}\n * @return notary Notary that signed the snapshot\n */\n function _verifyReceipt(Receipt rcpt, bytes memory rcptSignature)\n internal\n view\n returns (AgentStatus memory status, address notary)\n {\n // This will revert if signer is not a known agent\n (status, notary) = _recoverAgent(rcpt.hashValid(), rcptSignature);\n // Receipt signer needs to be a Notary, not a Guard\n if (status.domain == 0) revert AgentNotNotary();\n }\n\n /**\n * @dev Internal function to verify the signed receipt report payload.\n * Reverts if any of these is true:\n * - Report signer is not a known Guard.\n * @param rcpt Typed memory view over receipt payload that Guard reports as invalid\n * @param rrSignature Guard signature for the \"invalid receipt\" report\n * @return status Struct representing guard status, see {_recoverAgent}\n * @return guard Guard that signed the report\n */\n function _verifyReceiptReport(Receipt rcpt, bytes memory rrSignature)\n internal\n view\n returns (AgentStatus memory status, address guard)\n {\n // This will revert if signer is not a known agent\n (status, guard) = _recoverAgent(rcpt.hashInvalid(), rrSignature);\n // Report signer needs to be a Guard, not a Notary\n if (status.domain != 0) revert AgentNotGuard();\n }\n\n // ═══════════════════════════════════════ STATE/SNAPSHOT RELATED CHECKS ═══════════════════════════════════════════\n\n /**\n * @dev Internal function to verify the signed snapshot report payload.\n * Reverts if any of these is true:\n * - Report signer is not a known Guard.\n * @param state Typed memory view over state payload that Guard reports as invalid\n * @param srSignature Guard signature for the report\n * @return status Struct representing guard status, see {_recoverAgent}\n * @return guard Guard that signed the report\n */\n function _verifyStateReport(State state, bytes memory srSignature)\n internal\n view\n returns (AgentStatus memory status, address guard)\n {\n // This will revert if signer is not a known agent\n (status, guard) = _recoverAgent(state.hashInvalid(), srSignature);\n // Report signer needs to be a Guard, not a Notary\n if (status.domain != 0) revert AgentNotGuard();\n }\n\n /**\n * @dev Internal function to verify the signed snapshot payload.\n * Reverts if any of these is true:\n * - Snapshot signer is not a known Agent.\n * - Snapshot signer is not a Notary (if verifyNotary is true).\n * @param snapshot Typed memory view over snapshot payload\n * @param snapSignature Agent signature for the snapshot\n * @param verifyNotary If true, snapshot signer needs to be a Notary, not a Guard\n * @return status Struct representing agent status, see {_recoverAgent}\n * @return agent Agent that signed the snapshot\n */\n function _verifySnapshot(Snapshot snapshot, bytes memory snapSignature, bool verifyNotary)\n internal\n view\n returns (AgentStatus memory status, address agent)\n {\n // This will revert if signer is not a known agent\n (status, agent) = _recoverAgent(snapshot.hashValid(), snapSignature);\n // If requested, snapshot signer needs to be a Notary, not a Guard\n if (verifyNotary \u0026\u0026 status.domain == 0) revert AgentNotNotary();\n }\n\n // ═══════════════════════════════════════════ MERKLE RELATED CHECKS ═══════════════════════════════════════════════\n\n /**\n * @dev Internal function to verify that snapshot roots match.\n * Reverts if any of these is true:\n * - Attestation root is not equal to Merkle Root derived from State and Snapshot Proof.\n * - Snapshot Proof's first element does not match the State metadata.\n * - Snapshot Proof length exceeds Snapshot tree Height.\n * - State index is out of range.\n * @param att Typed memory view over Attestation\n * @param stateIndex Index of state in the snapshot\n * @param state Typed memory view over the provided state payload\n * @param snapProof Raw payload with snapshot data\n */\n function _verifySnapshotMerkle(Attestation att, uint8 stateIndex, State state, bytes32[] memory snapProof)\n internal\n pure\n {\n // Snapshot proof first element should match State metadata (aka \"right sub-leaf\")\n (, bytes32 rightSubLeaf) = state.subLeafs();\n if (snapProof[0] != rightSubLeaf) revert IncorrectSnapshotProof();\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(state.root(), state.origin(), snapProof, stateIndex);\n // Snapshot root should match the attestation root\n if (att.snapRoot() != snapshotRoot) revert IncorrectSnapshotRoot();\n }\n}\n\n// contracts/inbox/Inbox.sol\n\n// ══════════════════════════════ LIBRARY IMPORTS ══════════════════════════════\n\n// ═════════════════════════════ INTERNAL IMPORTS ══════════════════════════════\n\n/// @notice `Inbox` is the child of `StatementInbox` contract, that is used on Synapse Chain.\n/// In addition to the functionality of `StatementInbox`, it also:\n/// - Accepts Guard and Notary Snapshots and passes them to `Summit` contract.\n/// - Accepts Notary-signed Receipts and passes them to `Summit` contract.\n/// - Accepts Receipt Reports to initiate a dispute between Guard and Notary.\n/// - Verifies Attestations and Attestation Reports, and slashes the signer if they are invalid.\ncontract Inbox is StatementInbox, InboxEvents, InterfaceInbox {\n using AttestationLib for bytes;\n using ReceiptLib for bytes;\n using SnapshotLib for bytes;\n\n // Struct to get around stack too deep error. TODO: revisit this\n struct ReceiptInfo {\n AgentStatus rcptNotaryStatus;\n address notary;\n uint32 attNonce;\n AgentStatus attNotaryStatus;\n }\n\n // ══════════════════════════════════════════════════ STORAGE ══════════════════════════════════════════════════════\n\n // The address of the Summit contract.\n address public summit;\n\n // ═════════════════════════════════════════ CONSTRUCTOR \u0026 INITIALIZER ═════════════════════════════════════════════\n\n constructor(uint32 synapseDomain_) MessagingBase(\"0.0.3\", synapseDomain_) {\n if (localDomain != synapseDomain) revert MustBeSynapseDomain();\n }\n\n /// @notice Initializes `Inbox` contract:\n /// - Sets `msg.sender` as the owner of the contract\n /// - Sets `agentManager`, `origin`, `destination` and `summit` addresses\n function initialize(address agentManager_, address origin_, address destination_, address summit_)\n external\n initializer\n {\n __StatementInbox_init(agentManager_, origin_, destination_);\n summit = summit_;\n }\n\n // ══════════════════════════════════════════ SUBMIT AGENT STATEMENTS ══════════════════════════════════════════════\n\n /// @inheritdoc InterfaceInbox\n function submitSnapshot(bytes memory snapPayload, bytes memory snapSignature)\n external\n returns (bytes memory attPayload, bytes32 agentRoot_, uint256[] memory snapGas)\n {\n // This will revert if payload is not a snapshot\n Snapshot snapshot = snapPayload.castToSnapshot();\n // This will revert if the signer is not a known Guard/Notary\n (AgentStatus memory status, address agent) =\n _verifySnapshot({snapshot: snapshot, snapSignature: snapSignature, verifyNotary: false});\n // Check that Agent is active\n status.verifyActive();\n // Store Agent signature for the Snapshot\n uint256 sigIndex = _saveSignature(snapSignature);\n if (status.domain == 0) {\n // Guard that is in Dispute could still submit new snapshots, so we don't check that\n InterfaceSummit(summit).acceptGuardSnapshot({\n guardIndex: status.index,\n sigIndex: sigIndex,\n snapPayload: snapPayload\n });\n } else {\n // Get current agentRoot from AgentManager\n agentRoot_ = IAgentManager(agentManager).agentRoot();\n // This will revert if Notary is in Dispute\n attPayload = InterfaceSummit(summit).acceptNotarySnapshot({\n notaryIndex: status.index,\n sigIndex: sigIndex,\n agentRoot: agentRoot_,\n snapPayload: snapPayload\n });\n ChainGas[] memory snapGas_ = snapshot.snapGas();\n // Pass created attestation to Destination to enable executing messages coming to Synapse Chain\n InterfaceDestination(destination).acceptAttestation(\n status.index, type(uint256).max, attPayload, agentRoot_, snapGas_\n );\n // Use assembly to cast ChainGas[] to uint256[] without copying. Highest bits are left zeroed.\n // solhint-disable-next-line no-inline-assembly\n assembly {\n snapGas := snapGas_\n }\n }\n emit SnapshotAccepted(status.domain, agent, snapPayload, snapSignature);\n }\n\n /// @inheritdoc InterfaceInbox\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 // Struct to get around stack too deep error.\n ReceiptInfo memory info;\n // This will revert if payload is not a receipt\n Receipt rcpt = rcptPayload.castToReceipt();\n // This will revert if the receipt signer is not a known Notary\n (info.rcptNotaryStatus, info.notary) = _verifyReceipt(rcpt, rcptSignature);\n // Receipt Notary needs to be Active\n info.rcptNotaryStatus.verifyActive();\n info.attNonce = IExecutionHub(destination).getAttestationNonce(rcpt.snapshotRoot());\n if (info.attNonce == 0) revert IncorrectSnapshotRoot();\n // Attestation Notary domain needs to match the destination domain\n info.attNotaryStatus = IAgentManager(agentManager).agentStatus(rcpt.attNotary());\n if (info.attNotaryStatus.domain != rcpt.destination()) revert IncorrectAgentDomain();\n // Check that the correct tip values for the message were provided\n _verifyReceiptTips(rcpt.messageHash(), paddedTips, headerHash, bodyHash);\n // Store Notary signature for the Receipt\n uint256 sigIndex = _saveSignature(rcptSignature);\n // This will revert if Receipt Notary is in Dispute\n wasAccepted = InterfaceSummit(summit).acceptReceipt({\n rcptNotaryIndex: info.rcptNotaryStatus.index,\n attNotaryIndex: info.attNotaryStatus.index,\n sigIndex: sigIndex,\n attNonce: info.attNonce,\n paddedTips: paddedTips,\n rcptPayload: rcptPayload\n });\n if (wasAccepted) {\n emit ReceiptAccepted(info.rcptNotaryStatus.domain, info.notary, rcptPayload, rcptSignature);\n }\n }\n\n /// @inheritdoc InterfaceInbox\n function submitReceiptReport(bytes memory rcptPayload, bytes memory rcptSignature, bytes memory rrSignature)\n external\n returns (bool wasAccepted)\n {\n // This will revert if payload is not a receipt\n Receipt rcpt = rcptPayload.castToReceipt();\n // This will revert if the receipt signer is not a known Guard\n (AgentStatus memory guardStatus,) = _verifyReceiptReport(rcpt, rrSignature);\n // Guard needs to be Active\n guardStatus.verifyActive();\n // This will revert if report signer is not a known Notary\n (AgentStatus memory notaryStatus,) = _verifyReceipt(rcpt, rcptSignature);\n // Notary needs to be Active/Unstaking\n notaryStatus.verifyActiveUnstaking();\n _saveReport(rcptPayload, rrSignature);\n // This will revert if either actor is already in dispute\n IAgentManager(agentManager).openDispute(guardStatus.index, notaryStatus.index);\n return true;\n }\n\n /// @inheritdoc InterfaceInbox\n function passReceipt(uint32 attNotaryIndex, uint32 attNonce, uint256 paddedTips, bytes memory rcptPayload)\n external\n returns (bool wasAccepted)\n {\n // Only Destination can pass receipts\n if (msg.sender != destination) revert CallerNotDestination();\n return InterfaceSummit(summit).acceptReceipt({\n rcptNotaryIndex: attNotaryIndex,\n attNotaryIndex: attNotaryIndex,\n sigIndex: type(uint256).max,\n attNonce: attNonce,\n paddedTips: paddedTips,\n rcptPayload: rcptPayload\n });\n }\n\n // ══════════════════════════════════════════ VERIFY AGENT STATEMENTS ══════════════════════════════════════════════\n\n /// @inheritdoc InterfaceInbox\n function verifyAttestation(bytes memory attPayload, bytes memory attSignature)\n external\n returns (bool isValidAttestation)\n {\n // This will revert if payload is not an attestation\n Attestation att = attPayload.castToAttestation();\n // This will revert if the attestation signer is not a known Notary\n (AgentStatus memory status, address notary) = _verifyAttestation(att, attSignature);\n // Notary needs to be Active/Unstaking\n status.verifyActiveUnstaking();\n isValidAttestation = ISnapshotHub(summit).isValidAttestation(attPayload);\n if (!isValidAttestation) {\n emit InvalidAttestation(attPayload, attSignature);\n IAgentManager(agentManager).slashAgent(status.domain, notary, msg.sender);\n }\n }\n\n /// @inheritdoc InterfaceInbox\n function verifyAttestationReport(bytes memory attPayload, bytes memory arSignature)\n external\n returns (bool isValidReport)\n {\n // This will revert if payload is not an attestation\n Attestation att = attPayload.castToAttestation();\n // This will revert if the report signer is not a known Guard\n (AgentStatus memory status, address guard) = _verifyAttestationReport(att, arSignature);\n // Guard needs to be Active/Unstaking\n status.verifyActiveUnstaking();\n // Report is valid IF AND ONLY IF the reported attestation in invalid\n isValidReport = !ISnapshotHub(summit).isValidAttestation(attPayload);\n if (!isValidReport) {\n emit InvalidAttestationReport(attPayload, arSignature);\n IAgentManager(agentManager).slashAgent(status.domain, guard, msg.sender);\n }\n }\n\n // ══════════════════════════════════════════════ INTERNAL VIEWS ═══════════════════════════════════════════════════\n\n /// @dev Verifies that tips proof matches the message hash.\n function _verifyReceiptTips(bytes32 msgHash, uint256 paddedTips, bytes32 headerHash, bytes32 bodyHash)\n internal\n pure\n {\n Tips tips = TipsLib.wrapPadded(paddedTips);\n // full message leaf is (header, baseMessage), while base message leaf is (tips, remainingBody).\n if (MerkleMath.getParent(headerHash, MerkleMath.getParent(tips.leaf(), bodyHash)) != msgHash) {\n revert IncorrectTipsProof();\n }\n }\n}\n","language":"Solidity","languageVersion":"0.8.17","compilerVersion":"0.8.17","compilerOptions":"--combined-json bin,bin-runtime,srcmap,srcmap-runtime,abi,userdoc,devdoc,metadata,hashes --optimize --optimize-runs 10000 --allow-paths ., ./, ../","srcMap":"","srcMapRuntime":"","abiDefinition":[{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint8","name":"version","type":"uint8"}],"name":"Initialized","type":"event"}],"userDoc":{"kind":"user","methods":{},"version":1},"developerDoc":{"details":"Provides information about the current execution context, including the sender of the transaction and its data. While these are generally available via msg.sender and msg.data, they should not be accessed in such a direct manner, since when dealing with meta-transactions the account sending and paying for execution may not be the actual sender (as far as an application is concerned). This contract is only required for intermediate, library-like contracts.","kind":"dev","methods":{},"stateVariables":{"__gap":{"details":"This empty reserved space is put in place to allow future versions to add new variables without shifting down storage in the inheritance chain. See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps"}},"version":1},"metadata":"{\"compiler\":{\"version\":\"0.8.17+commit.8df45f5f\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint8\",\"name\":\"version\",\"type\":\"uint8\"}],\"name\":\"Initialized\",\"type\":\"event\"}],\"devdoc\":{\"details\":\"Provides information about the current execution context, including the sender of the transaction and its data. While these are generally available via msg.sender and msg.data, they should not be accessed in such a direct manner, since when dealing with meta-transactions the account sending and paying for execution may not be the actual sender (as far as an application is concerned). This contract is only required for intermediate, library-like contracts.\",\"kind\":\"dev\",\"methods\":{},\"stateVariables\":{\"__gap\":{\"details\":\"This empty reserved space is put in place to allow future versions to add new variables without shifting down storage in the inheritance chain. See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\"}},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"solidity/Inbox.sol\":\"ContextUpgradeable\"},\"evmVersion\":\"london\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\"},\"optimizer\":{\"enabled\":true,\"runs\":10000},\"remappings\":[]},\"sources\":{\"solidity/Inbox.sol\":{\"keccak256\":\"0x9b516081a036814c0169e20e484d4a5499066b7a6f48fada952b5e844a1ca3e5\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://32bde393b3f24ef4307d9626d4143f337b3c0bd34e17bb969fd5a15221d96987\",\"dweb:/ipfs/QmTkt2XZRtgsbSpmsVQUM3c4ebETQoDVYbmEV9yheBghnr\"]}},\"version\":1}"},"hashes":{}},"solidity/Inbox.sol:ECDSA":{"code":"0x60566037600b82828239805160001a607314602a57634e487b7160e01b600052600060045260246000fd5b30600052607381538281f3fe73000000000000000000000000000000000000000030146080604052600080fdfea26469706673582212208903486d7eb0e47b44ab9cade338432c5098f8dbdb6e0cf01a7ddcd31eba837d64736f6c63430008110033","runtime-code":"0x73000000000000000000000000000000000000000030146080604052600080fdfea26469706673582212208903486d7eb0e47b44ab9cade338432c5098f8dbdb6e0cf01a7ddcd31eba837d64736f6c63430008110033","info":{"source":"// SPDX-License-Identifier: MIT\npragma solidity =0.8.17 ^0.8.0 ^0.8.1 ^0.8.2;\n\n// contracts/events/InboxEvents.sol\n\nabstract contract InboxEvents {\n /**\n * @notice Emitted when a snapshot is accepted by the Summit contract.\n * @param domain Domain where the signed Agent is active (ZERO for Guards)\n * @param agent Agent who signed the snapshot\n * @param snapPayload Raw payload with snapshot data\n * @param snapSignature Agent signature for the snapshot\n */\n event SnapshotAccepted(uint32 indexed domain, address indexed agent, bytes snapPayload, bytes snapSignature);\n\n /**\n * @notice Emitted when a snapshot is accepted by the Summit contract.\n * @param domain Domain where the signed Notary is active\n * @param notary Notary who signed the attestation\n * @param rcptPayload Raw payload with receipt data\n * @param rcptSignature Notary signature for the receipt\n */\n event ReceiptAccepted(uint32 domain, address notary, bytes rcptPayload, bytes rcptSignature);\n\n /**\n * @notice Emitted when a proof of invalid attestation is submitted.\n * @param attPayload Raw payload with Attestation data\n * @param attSignature Notary signature for the attestation\n */\n event InvalidAttestation(bytes attPayload, bytes attSignature);\n\n /**\n * @notice Emitted when a proof of invalid attestation report is submitted.\n * @param arPayload Raw payload with report data\n * @param arSignature Guard signature for the report\n */\n event InvalidAttestationReport(bytes arPayload, bytes arSignature);\n}\n\n// contracts/events/StatementInboxEvents.sol\n\nabstract contract StatementInboxEvents {\n // ════════════════════════════════════════════ STATEMENT ACCEPTED ═════════════════════════════════════════════════\n\n /**\n * @notice Emitted when a snapshot is accepted by the Destination contract.\n * @param domain Domain where the signed Notary is active\n * @param notary Notary who signed the attestation\n * @param attPayload Raw payload with attestation data\n * @param attSignature Notary signature for the attestation\n */\n event AttestationAccepted(uint32 domain, address notary, bytes attPayload, bytes attSignature);\n\n // ═════════════════════════════════════════ INVALID STATEMENT PROVED ══════════════════════════════════════════════\n\n /**\n * @notice Emitted when a proof of invalid receipt statement is submitted.\n * @param rcptPayload Raw payload with the receipt statement\n * @param rcptSignature Notary signature for the receipt statement\n */\n event InvalidReceipt(bytes rcptPayload, bytes rcptSignature);\n\n /**\n * @notice Emitted when a proof of invalid receipt report is submitted.\n * @param rrPayload Raw payload with report data\n * @param rrSignature Guard signature for the report\n */\n event InvalidReceiptReport(bytes rrPayload, bytes rrSignature);\n\n /**\n * @notice Emitted when a proof of invalid state in the signed attestation is submitted.\n * @param stateIndex Index of invalid state in the snapshot\n * @param statePayload Raw payload with state data\n * @param attPayload Raw payload with Attestation data for snapshot\n * @param attSignature Notary signature for the attestation\n */\n event InvalidStateWithAttestation(uint8 stateIndex, bytes statePayload, bytes attPayload, bytes attSignature);\n\n /**\n * @notice Emitted when a proof of invalid state in the signed snapshot is submitted.\n * @param stateIndex Index of invalid state in the snapshot\n * @param snapPayload Raw payload with snapshot data\n * @param snapSignature Agent signature for the snapshot\n */\n event InvalidStateWithSnapshot(uint8 stateIndex, bytes snapPayload, bytes snapSignature);\n\n /**\n * @notice Emitted when a proof of invalid state report is submitted.\n * @param srPayload Raw payload with report data\n * @param srSignature Guard signature for the report\n */\n event InvalidStateReport(bytes srPayload, bytes srSignature);\n}\n\n// contracts/interfaces/ISnapshotHub.sol\n\ninterface ISnapshotHub {\n /**\n * @notice Check that a given attestation is valid: matches the historical attestation\n * derived from an accepted Notary snapshot.\n * @dev Will revert if any of these is true:\n * - Attestation payload is not properly formatted.\n * @param attPayload Raw payload with attestation data\n * @return isValid Whether the provided attestation is valid\n */\n function isValidAttestation(bytes memory attPayload) external view returns (bool isValid);\n\n /**\n * @notice Returns saved attestation with the given nonce.\n * @dev Reverts if attestation with given nonce hasn't been created yet.\n * @param attNonce Nonce for the attestation\n * @return attPayload Raw payload with formatted Attestation data\n * @return agentRoot Agent root hash used for the attestation\n * @return snapGas Snapshot gas data used for the attestation\n */\n function getAttestation(uint32 attNonce)\n external\n view\n returns (bytes memory attPayload, bytes32 agentRoot, uint256[] memory snapGas);\n\n /**\n * @notice Returns the state with the highest known nonce submitted by a given Agent.\n * @param origin Domain of origin chain\n * @param agent Agent address\n * @return statePayload Raw payload with agent's latest state for origin\n */\n function getLatestAgentState(uint32 origin, address agent) external view returns (bytes memory statePayload);\n\n /**\n * @notice Returns latest saved attestation for a Notary.\n * @param notary Notary address\n * @return attPayload Raw payload with formatted Attestation data\n * @return agentRoot Agent root hash used for the attestation\n * @return snapGas Snapshot gas data used for the attestation\n */\n function getLatestNotaryAttestation(address notary)\n external\n view\n returns (bytes memory attPayload, bytes32 agentRoot, uint256[] memory snapGas);\n\n /**\n * @notice Returns Guard snapshot from the list of all accepted Guard snapshots.\n * @dev Reverts if snapshot with given index hasn't been accepted yet.\n * @param index Snapshot index in the list of all Guard snapshots\n * @return snapPayload Raw payload with Guard snapshot\n * @return snapSignature Raw payload with Guard signature for snapshot\n */\n function getGuardSnapshot(uint256 index)\n external\n view\n returns (bytes memory snapPayload, bytes memory snapSignature);\n\n /**\n * @notice Returns Notary snapshot from the list of all accepted Guard snapshots.\n * @dev Reverts if snapshot with given index hasn't been accepted yet.\n * @param index Snapshot index in the list of all Notary snapshots\n * @return snapPayload Raw payload with Notary snapshot\n * @return snapSignature Raw payload with Notary signature for snapshot\n */\n function getNotarySnapshot(uint256 index)\n external\n view\n returns (bytes memory snapPayload, bytes memory snapSignature);\n\n /**\n * @notice Returns Notary snapshot that was used for creating a given attestation.\n * @dev Reverts if any of these is true:\n * - Attestation payload is not properly formatted.\n * - Attestation is invalid (doesn't have a matching Notary snapshot).\n * @param attPayload Raw payload with attestation data\n * @return snapPayload Raw payload with Notary snapshot\n * @return snapSignature Raw payload with Notary signature for snapshot\n */\n function getNotarySnapshot(bytes memory attPayload)\n external\n view\n returns (bytes memory snapPayload, bytes memory snapSignature);\n\n /**\n * @notice Returns proof of inclusion of (root, origin) fields of a given snapshot's state\n * into the Snapshot Merkle Tree for a given attestation.\n * @dev Reverts if any of these is true:\n * - Attestation with given nonce hasn't been created yet.\n * - State index is out of range of snapshot list.\n * @param attNonce Nonce for the attestation\n * @param stateIndex Index of state in the attestation's snapshot\n * @return snapProof The snapshot proof\n */\n function getSnapshotProof(uint32 attNonce, uint8 stateIndex) external view returns (bytes32[] memory snapProof);\n}\n\n// contracts/interfaces/IStateHub.sol\n\ninterface IStateHub {\n /**\n * @notice Check that a given state is valid: matches the historical state of Origin contract.\n * Note: any Agent including an invalid state in their snapshot will be slashed\n * upon providing the snapshot and agent signature for it to Origin contract.\n * @dev Will revert if any of these is true:\n * - State payload is not properly formatted.\n * @param statePayload Raw payload with state data\n * @return isValid Whether the provided state is valid\n */\n function isValidState(bytes memory statePayload) external view returns (bool isValid);\n\n /**\n * @notice Returns the amount of saved states so far.\n * @dev This includes the initial state of \"empty Origin Merkle Tree\".\n */\n function statesAmount() external view returns (uint256);\n\n /**\n * @notice Suggest the data (state after latest sent message) to sign for an Agent.\n * Note: signing the suggested state data will will never lead to slashing of the actor,\n * assuming they have confirmed that the block, which number is included in the data,\n * is not subject to reorganization (which is different for every observed chain).\n * @return statePayload Raw payload with the latest state data\n */\n function suggestLatestState() external view returns (bytes memory statePayload);\n\n /**\n * @notice Given the historical nonce, suggest the state data to sign for an Agent.\n * Note: signing the suggested state data will will never lead to slashing of the actor,\n * assuming they have confirmed that the block, which number is included in the data,\n * is not subject to reorganization (which is different for every observed chain).\n * @param nonce Historical nonce to form a state\n * @return statePayload Raw payload with historical state data\n */\n function suggestState(uint32 nonce) external view returns (bytes memory statePayload);\n}\n\n// contracts/interfaces/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/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// node_modules/@openzeppelin/contracts/utils/math/Math.sol\n\n// OpenZeppelin Contracts (last updated v4.9.0) (utils/math/Math.sol)\n\n/**\n * @dev Standard math utilities missing in the Solidity language.\n */\nlibrary Math {\n enum Rounding {\n Down, // Toward negative infinity\n Up, // Toward infinity\n Zero // Toward zero\n }\n\n /**\n * @dev Returns the largest of two numbers.\n */\n function max(uint256 a, uint256 b) internal pure returns (uint256) {\n return a \u003e b ? a : b;\n }\n\n /**\n * @dev Returns the smallest of two numbers.\n */\n function min(uint256 a, uint256 b) internal pure returns (uint256) {\n return a \u003c b ? a : b;\n }\n\n /**\n * @dev Returns the average of two numbers. The result is rounded towards\n * zero.\n */\n function average(uint256 a, uint256 b) internal pure returns (uint256) {\n // (a + b) / 2 can overflow.\n return (a \u0026 b) + (a ^ b) / 2;\n }\n\n /**\n * @dev Returns the ceiling of the division of two numbers.\n *\n * This differs from standard division with `/` in that it rounds up instead\n * of rounding down.\n */\n function ceilDiv(uint256 a, uint256 b) internal pure returns (uint256) {\n // (a + b - 1) / b can overflow on addition, so we distribute.\n return a == 0 ? 0 : (a - 1) / b + 1;\n }\n\n /**\n * @notice Calculates floor(x * y / denominator) with full precision. Throws if result overflows a uint256 or denominator == 0\n * @dev Original credit to Remco Bloemen under MIT license (https://xn--2-umb.com/21/muldiv)\n * with further edits by Uniswap Labs also under MIT license.\n */\n function mulDiv(uint256 x, uint256 y, uint256 denominator) internal pure returns (uint256 result) {\n unchecked {\n // 512-bit multiply [prod1 prod0] = x * y. Compute the product mod 2^256 and mod 2^256 - 1, then use\n // use the Chinese Remainder Theorem to reconstruct the 512 bit result. The result is stored in two 256\n // variables such that product = prod1 * 2^256 + prod0.\n uint256 prod0; // Least significant 256 bits of the product\n uint256 prod1; // Most significant 256 bits of the product\n assembly {\n let mm := mulmod(x, y, not(0))\n prod0 := mul(x, y)\n prod1 := sub(sub(mm, prod0), lt(mm, prod0))\n }\n\n // Handle non-overflow cases, 256 by 256 division.\n if (prod1 == 0) {\n // Solidity will revert if denominator == 0, unlike the div opcode on its own.\n // The surrounding unchecked block does not change this fact.\n // See https://docs.soliditylang.org/en/latest/control-structures.html#checked-or-unchecked-arithmetic.\n return prod0 / denominator;\n }\n\n // Make sure the result is less than 2^256. Also prevents denominator == 0.\n require(denominator \u003e prod1, \"Math: mulDiv overflow\");\n\n ///////////////////////////////////////////////\n // 512 by 256 division.\n ///////////////////////////////////////////////\n\n // Make division exact by subtracting the remainder from [prod1 prod0].\n uint256 remainder;\n assembly {\n // Compute remainder using mulmod.\n remainder := mulmod(x, y, denominator)\n\n // Subtract 256 bit number from 512 bit number.\n prod1 := sub(prod1, gt(remainder, prod0))\n prod0 := sub(prod0, remainder)\n }\n\n // Factor powers of two out of denominator and compute largest power of two divisor of denominator. Always \u003e= 1.\n // See https://cs.stackexchange.com/q/138556/92363.\n\n // Does not overflow because the denominator cannot be zero at this stage in the function.\n uint256 twos = denominator \u0026 (~denominator + 1);\n assembly {\n // Divide denominator by twos.\n denominator := div(denominator, twos)\n\n // Divide [prod1 prod0] by twos.\n prod0 := div(prod0, twos)\n\n // Flip twos such that it is 2^256 / twos. If twos is zero, then it becomes one.\n twos := add(div(sub(0, twos), twos), 1)\n }\n\n // Shift in bits from prod1 into prod0.\n prod0 |= prod1 * twos;\n\n // Invert denominator mod 2^256. Now that denominator is an odd number, it has an inverse modulo 2^256 such\n // that denominator * inv = 1 mod 2^256. Compute the inverse by starting with a seed that is correct for\n // four bits. That is, denominator * inv = 1 mod 2^4.\n uint256 inverse = (3 * denominator) ^ 2;\n\n // Use the Newton-Raphson iteration to improve the precision. Thanks to Hensel's lifting lemma, this also works\n // in modular arithmetic, doubling the correct bits in each step.\n inverse *= 2 - denominator * inverse; // inverse mod 2^8\n inverse *= 2 - denominator * inverse; // inverse mod 2^16\n inverse *= 2 - denominator * inverse; // inverse mod 2^32\n inverse *= 2 - denominator * inverse; // inverse mod 2^64\n inverse *= 2 - denominator * inverse; // inverse mod 2^128\n inverse *= 2 - denominator * inverse; // inverse mod 2^256\n\n // Because the division is now exact we can divide by multiplying with the modular inverse of denominator.\n // This will give us the correct result modulo 2^256. Since the preconditions guarantee that the outcome is\n // less than 2^256, this is the final result. We don't need to compute the high bits of the result and prod1\n // is no longer required.\n result = prod0 * inverse;\n return result;\n }\n }\n\n /**\n * @notice Calculates x * y / denominator with full precision, following the selected rounding direction.\n */\n function mulDiv(uint256 x, uint256 y, uint256 denominator, Rounding rounding) internal pure returns (uint256) {\n uint256 result = mulDiv(x, y, denominator);\n if (rounding == Rounding.Up \u0026\u0026 mulmod(x, y, denominator) \u003e 0) {\n result += 1;\n }\n return result;\n }\n\n /**\n * @dev Returns the square root of a number. If the number is not a perfect square, the value is rounded down.\n *\n * Inspired by Henry S. Warren, Jr.'s \"Hacker's Delight\" (Chapter 11).\n */\n function sqrt(uint256 a) internal pure returns (uint256) {\n if (a == 0) {\n return 0;\n }\n\n // For our first guess, we get the biggest power of 2 which is smaller than the square root of the target.\n //\n // We know that the \"msb\" (most significant bit) of our target number `a` is a power of 2 such that we have\n // `msb(a) \u003c= a \u003c 2*msb(a)`. This value can be written `msb(a)=2**k` with `k=log2(a)`.\n //\n // This can be rewritten `2**log2(a) \u003c= a \u003c 2**(log2(a) + 1)`\n // → `sqrt(2**k) \u003c= sqrt(a) \u003c sqrt(2**(k+1))`\n // → `2**(k/2) \u003c= sqrt(a) \u003c 2**((k+1)/2) \u003c= 2**(k/2 + 1)`\n //\n // Consequently, `2**(log2(a) / 2)` is a good first approximation of `sqrt(a)` with at least 1 correct bit.\n uint256 result = 1 \u003c\u003c (log2(a) \u003e\u003e 1);\n\n // At this point `result` is an estimation with one bit of precision. We know the true value is a uint128,\n // since it is the square root of a uint256. Newton's method converges quadratically (precision doubles at\n // every iteration). We thus need at most 7 iteration to turn our partial result with one bit of precision\n // into the expected uint128 result.\n unchecked {\n result = (result + a / result) \u003e\u003e 1;\n result = (result + a / result) \u003e\u003e 1;\n result = (result + a / result) \u003e\u003e 1;\n result = (result + a / result) \u003e\u003e 1;\n result = (result + a / result) \u003e\u003e 1;\n result = (result + a / result) \u003e\u003e 1;\n result = (result + a / result) \u003e\u003e 1;\n return min(result, a / result);\n }\n }\n\n /**\n * @notice Calculates sqrt(a), following the selected rounding direction.\n */\n function sqrt(uint256 a, Rounding rounding) internal pure returns (uint256) {\n unchecked {\n uint256 result = sqrt(a);\n return result + (rounding == Rounding.Up \u0026\u0026 result * result \u003c a ? 1 : 0);\n }\n }\n\n /**\n * @dev Return the log in base 2, rounded down, of a positive value.\n * Returns 0 if given 0.\n */\n function log2(uint256 value) internal pure returns (uint256) {\n uint256 result = 0;\n unchecked {\n if (value \u003e\u003e 128 \u003e 0) {\n value \u003e\u003e= 128;\n result += 128;\n }\n if (value \u003e\u003e 64 \u003e 0) {\n value \u003e\u003e= 64;\n result += 64;\n }\n if (value \u003e\u003e 32 \u003e 0) {\n value \u003e\u003e= 32;\n result += 32;\n }\n if (value \u003e\u003e 16 \u003e 0) {\n value \u003e\u003e= 16;\n result += 16;\n }\n if (value \u003e\u003e 8 \u003e 0) {\n value \u003e\u003e= 8;\n result += 8;\n }\n if (value \u003e\u003e 4 \u003e 0) {\n value \u003e\u003e= 4;\n result += 4;\n }\n if (value \u003e\u003e 2 \u003e 0) {\n value \u003e\u003e= 2;\n result += 2;\n }\n if (value \u003e\u003e 1 \u003e 0) {\n result += 1;\n }\n }\n return result;\n }\n\n /**\n * @dev Return the log in base 2, following the selected rounding direction, of a positive value.\n * Returns 0 if given 0.\n */\n function log2(uint256 value, Rounding rounding) internal pure returns (uint256) {\n unchecked {\n uint256 result = log2(value);\n return result + (rounding == Rounding.Up \u0026\u0026 1 \u003c\u003c result \u003c value ? 1 : 0);\n }\n }\n\n /**\n * @dev Return the log in base 10, rounded down, of a positive value.\n * Returns 0 if given 0.\n */\n function log10(uint256 value) internal pure returns (uint256) {\n uint256 result = 0;\n unchecked {\n if (value \u003e= 10 ** 64) {\n value /= 10 ** 64;\n result += 64;\n }\n if (value \u003e= 10 ** 32) {\n value /= 10 ** 32;\n result += 32;\n }\n if (value \u003e= 10 ** 16) {\n value /= 10 ** 16;\n result += 16;\n }\n if (value \u003e= 10 ** 8) {\n value /= 10 ** 8;\n result += 8;\n }\n if (value \u003e= 10 ** 4) {\n value /= 10 ** 4;\n result += 4;\n }\n if (value \u003e= 10 ** 2) {\n value /= 10 ** 2;\n result += 2;\n }\n if (value \u003e= 10 ** 1) {\n result += 1;\n }\n }\n return result;\n }\n\n /**\n * @dev Return the log in base 10, following the selected rounding direction, of a positive value.\n * Returns 0 if given 0.\n */\n function log10(uint256 value, Rounding rounding) internal pure returns (uint256) {\n unchecked {\n uint256 result = log10(value);\n return result + (rounding == Rounding.Up \u0026\u0026 10 ** result \u003c value ? 1 : 0);\n }\n }\n\n /**\n * @dev Return the log in base 256, rounded down, of a positive value.\n * Returns 0 if given 0.\n *\n * Adding one to the result gives the number of pairs of hex symbols needed to represent `value` as a hex string.\n */\n function log256(uint256 value) internal pure returns (uint256) {\n uint256 result = 0;\n unchecked {\n if (value \u003e\u003e 128 \u003e 0) {\n value \u003e\u003e= 128;\n result += 16;\n }\n if (value \u003e\u003e 64 \u003e 0) {\n value \u003e\u003e= 64;\n result += 8;\n }\n if (value \u003e\u003e 32 \u003e 0) {\n value \u003e\u003e= 32;\n result += 4;\n }\n if (value \u003e\u003e 16 \u003e 0) {\n value \u003e\u003e= 16;\n result += 2;\n }\n if (value \u003e\u003e 8 \u003e 0) {\n result += 1;\n }\n }\n return result;\n }\n\n /**\n * @dev Return the log in base 256, following the selected rounding direction, of a positive value.\n * Returns 0 if given 0.\n */\n function log256(uint256 value, Rounding rounding) internal pure returns (uint256) {\n unchecked {\n uint256 result = log256(value);\n return result + (rounding == Rounding.Up \u0026\u0026 1 \u003c\u003c (result \u003c\u003c 3) \u003c value ? 1 : 0);\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/utils/math/SignedMath.sol\n\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/math/SignedMath.sol)\n\n/**\n * @dev Standard signed math utilities missing in the Solidity language.\n */\nlibrary SignedMath {\n /**\n * @dev Returns the largest of two signed numbers.\n */\n function max(int256 a, int256 b) internal pure returns (int256) {\n return a \u003e b ? a : b;\n }\n\n /**\n * @dev Returns the smallest of two signed numbers.\n */\n function min(int256 a, int256 b) internal pure returns (int256) {\n return a \u003c b ? a : b;\n }\n\n /**\n * @dev Returns the average of two signed numbers without overflow.\n * The result is rounded towards zero.\n */\n function average(int256 a, int256 b) internal pure returns (int256) {\n // Formula from the book \"Hacker's Delight\"\n int256 x = (a \u0026 b) + ((a ^ b) \u003e\u003e 1);\n return x + (int256(uint256(x) \u003e\u003e 255) \u0026 (a ^ b));\n }\n\n /**\n * @dev Returns the absolute unsigned value of a signed value.\n */\n function abs(int256 n) internal pure returns (uint256) {\n unchecked {\n // must be unchecked in order to support `n = type(int256).min`\n return uint256(n \u003e= 0 ? n : -n);\n }\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// 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/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/InterfaceSummit.sol\n\ninterface InterfaceSummit {\n // ══════════════════════════════════════════ ACCEPT AGENT STATEMENTS ══════════════════════════════════════════════\n\n /**\n * @notice Accepts a receipt, which local `AgentManager` verified to have been signed by an active Notary.\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 * - Notary who signed the receipt is referenced as the \"Receipt Notary\".\n * - Notary who signed the attestation on destination chain is referenced as the \"Attestation Notary\".\n * \u003e Will revert if any of these is true:\n * \u003e - Called by anyone other than local `AgentManager`.\n * \u003e - Receipt body payload is not properly formatted.\n * \u003e - Receipt signer is in Dispute.\n * \u003e - Receipt's snapshot root is unknown.\n * @param rcptNotaryIndex Index of Receipt Notary in Agent Merkle Tree\n * @param attNotaryIndex Index of Attestation Notary in Agent Merkle Tree\n * @param sigIndex Index of stored Notary signature\n * @param attNonce Nonce of the attestation used for proving the executed message\n * @param paddedTips Padded encoded paid tips information\n * @param rcptPayload Raw payload with message execution receipt\n * @return wasAccepted Whether the receipt was accepted\n */\n function acceptReceipt(\n uint32 rcptNotaryIndex,\n uint32 attNotaryIndex,\n uint256 sigIndex,\n uint32 attNonce,\n uint256 paddedTips,\n bytes memory rcptPayload\n ) external returns (bool wasAccepted);\n\n /**\n * @notice Accepts a snapshot, which local `AgentManager` verified to have been signed by an active Guard.\n * \u003e Snapshot is a list of states for a set of Origin contracts residing on any of the chains.\n * All the states in the Guard-signed snapshot become available for Notary signing.\n * \u003e Will revert if any of these is true:\n * \u003e - Called by anyone other than local `AgentManager`.\n * \u003e - Snapshot payload is not properly formatted.\n * \u003e - Snapshot contains a state older then the Guard has previously submitted.\n * @param guardIndex Index of Guard in Agent Merkle Tree\n * @param sigIndex Index of stored Agent signature\n * @param snapPayload Raw payload with snapshot data\n */\n function acceptGuardSnapshot(uint32 guardIndex, uint256 sigIndex, bytes memory snapPayload) external;\n\n /**\n * @notice Accepts a snapshot, which local `AgentManager` verified to have been signed by an active Notary.\n * \u003e Snapshot is a list of states for a set of Origin contracts residing on any of the chains.\n * Snapshot Merkle Root is calculated and saved for valid snapshots, i.e.\n * snapshots which are only using states previously submitted by any of the Guards.\n * - Notary could use states singed by the same of different Guards 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 - Called by anyone other than local `AgentManager`.\n * \u003e - Snapshot payload is not properly formatted.\n * \u003e - Snapshot contains a state older then the Notary has previously submitted.\n * \u003e - Snapshot contains a state that no Guard has previously submitted.\n * @param notaryIndex Index of Notary in Agent Merkle Tree\n * @param sigIndex Index of stored Agent signature\n * @param agentRoot Current root of the Agent Merkle Tree\n * @param snapPayload Raw payload with snapshot data\n * @return attPayload Raw payload with data for attestation derived from Notary snapshot.\n */\n function acceptNotarySnapshot(uint32 notaryIndex, uint256 sigIndex, bytes32 agentRoot, bytes memory snapPayload)\n external\n returns (bytes memory attPayload);\n\n // ════════════════════════════════════════════════ TIPS LOGIC ═════════════════════════════════════════════════════\n\n /**\n * @notice Distributes tips using the first Receipt from the \"receipt quarantine queue\".\n * Possible scenarios:\n * - Receipt queue is empty =\u003e does nothing\n * - Receipt optimistic period is not over =\u003e does nothing\n * - Either of Notaries present in Receipt was slashed =\u003e receipt is deleted from the queue\n * - Either of Notaries present in Receipt in Dispute =\u003e receipt is moved to the end of queue\n * - None of the above =\u003e receipt tips are distributed\n * @dev Returned value makes it possible to do the following: `while (distributeTips()) {}`\n * @return queuePopped Whether the first element was popped from the queue\n */\n function distributeTips() external returns (bool queuePopped);\n\n /**\n * @notice Withdraws locked base message tips from requested domain Origin to the recipient.\n * This is done by a call to a local Origin contract, or by a manager message to the remote chain.\n * @dev This will revert, if the pending balance of origin tips (earned-claimed) is lower than requested.\n * @param origin Domain of chain to withdraw tips on\n * @param amount Amount of tips to withdraw\n */\n function withdrawTips(uint32 origin, uint256 amount) external;\n\n // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════\n\n /**\n * @notice Returns earned and claimed tips for the actor.\n * Note: Tips for address(0) belong to the Treasury.\n * @param actor Address of the actor\n * @param origin Domain where the tips were initially paid\n * @return earned Total amount of origin tips the actor has earned so far\n * @return claimed Total amount of origin tips the actor has claimed so far\n */\n function actorTips(address actor, uint32 origin) external view returns (uint128 earned, uint128 claimed);\n\n /**\n * @notice Returns the amount of receipts in the \"Receipt Quarantine Queue\".\n */\n function receiptQueueLength() external view returns (uint256);\n\n /**\n * @notice Returns the state with the highest known nonce\n * submitted by any of the currently active Guards.\n * @param origin Domain of origin chain\n * @return statePayload Raw payload with latest active Guard state for origin\n */\n function getLatestState(uint32 origin) external view returns (bytes memory statePayload);\n}\n\n// node_modules/@openzeppelin/contracts/utils/Strings.sol\n\n// OpenZeppelin Contracts (last updated v4.9.0) (utils/Strings.sol)\n\n/**\n * @dev String operations.\n */\nlibrary Strings {\n bytes16 private constant _SYMBOLS = \"0123456789abcdef\";\n uint8 private constant _ADDRESS_LENGTH = 20;\n\n /**\n * @dev Converts a `uint256` to its ASCII `string` decimal representation.\n */\n function toString(uint256 value) internal pure returns (string memory) {\n unchecked {\n uint256 length = Math.log10(value) + 1;\n string memory buffer = new string(length);\n uint256 ptr;\n /// @solidity memory-safe-assembly\n assembly {\n ptr := add(buffer, add(32, length))\n }\n while (true) {\n ptr--;\n /// @solidity memory-safe-assembly\n assembly {\n mstore8(ptr, byte(mod(value, 10), _SYMBOLS))\n }\n value /= 10;\n if (value == 0) break;\n }\n return buffer;\n }\n }\n\n /**\n * @dev Converts a `int256` to its ASCII `string` decimal representation.\n */\n function toString(int256 value) internal pure returns (string memory) {\n return string(abi.encodePacked(value \u003c 0 ? \"-\" : \"\", toString(SignedMath.abs(value))));\n }\n\n /**\n * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation.\n */\n function toHexString(uint256 value) internal pure returns (string memory) {\n unchecked {\n return toHexString(value, Math.log256(value) + 1);\n }\n }\n\n /**\n * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length.\n */\n function toHexString(uint256 value, uint256 length) internal pure returns (string memory) {\n bytes memory buffer = new bytes(2 * length + 2);\n buffer[0] = \"0\";\n buffer[1] = \"x\";\n for (uint256 i = 2 * length + 1; i \u003e 1; --i) {\n buffer[i] = _SYMBOLS[value \u0026 0xf];\n value \u003e\u003e= 4;\n }\n require(value == 0, \"Strings: hex length insufficient\");\n return string(buffer);\n }\n\n /**\n * @dev Converts an `address` with fixed length of 20 bytes to its not checksummed ASCII `string` hexadecimal representation.\n */\n function toHexString(address addr) internal pure returns (string memory) {\n return toHexString(uint256(uint160(addr)), _ADDRESS_LENGTH);\n }\n\n /**\n * @dev Returns true if the two strings are equal.\n */\n function equal(string memory a, string memory b) internal pure returns (bool) {\n return keccak256(bytes(a)) == keccak256(bytes(b));\n }\n}\n\n// node_modules/@openzeppelin/contracts-upgradeable/utils/ContextUpgradeable.sol\n\n// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)\n\n/**\n * @dev Provides information about the current execution context, including the\n * sender of the transaction and its data. While these are generally available\n * via msg.sender and msg.data, they should not be accessed in such a direct\n * manner, since when dealing with meta-transactions the account sending and\n * paying for execution may not be the actual sender (as far as an application\n * is concerned).\n *\n * This contract is only required for intermediate, library-like contracts.\n */\nabstract contract ContextUpgradeable is Initializable {\n function __Context_init() internal onlyInitializing {\n }\n\n function __Context_init_unchained() internal onlyInitializing {\n }\n function _msgSender() internal view virtual returns (address) {\n return msg.sender;\n }\n\n function _msgData() internal view virtual returns (bytes calldata) {\n return msg.data;\n }\n\n /**\n * @dev This empty reserved space is put in place to allow future versions to add new\n * variables without shifting down storage in the inheritance chain.\n * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\n */\n uint256[50] private __gap;\n}\n\n// contracts/libs/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/utils/cryptography/ECDSA.sol\n\n// OpenZeppelin Contracts (last updated v4.9.0) (utils/cryptography/ECDSA.sol)\n\n/**\n * @dev Elliptic Curve Digital Signature Algorithm (ECDSA) operations.\n *\n * These functions can be used to verify that a message was signed by the holder\n * of the private keys of a given address.\n */\nlibrary ECDSA {\n enum RecoverError {\n NoError,\n InvalidSignature,\n InvalidSignatureLength,\n InvalidSignatureS,\n InvalidSignatureV // Deprecated in v4.8\n }\n\n function _throwError(RecoverError error) private pure {\n if (error == RecoverError.NoError) {\n return; // no error: do nothing\n } else if (error == RecoverError.InvalidSignature) {\n revert(\"ECDSA: invalid signature\");\n } else if (error == RecoverError.InvalidSignatureLength) {\n revert(\"ECDSA: invalid signature length\");\n } else if (error == RecoverError.InvalidSignatureS) {\n revert(\"ECDSA: invalid signature 's' value\");\n }\n }\n\n /**\n * @dev Returns the address that signed a hashed message (`hash`) with\n * `signature` or error string. This address can then be used for verification purposes.\n *\n * The `ecrecover` EVM opcode allows for malleable (non-unique) signatures:\n * this function rejects them by requiring the `s` value to be in the lower\n * half order, and the `v` value to be either 27 or 28.\n *\n * IMPORTANT: `hash` _must_ be the result of a hash operation for the\n * verification to be secure: it is possible to craft signatures that\n * recover to arbitrary addresses for non-hashed data. A safe way to ensure\n * this is by receiving a hash of the original message (which may otherwise\n * be too long), and then calling {toEthSignedMessageHash} on it.\n *\n * Documentation for signature generation:\n * - with https://web3js.readthedocs.io/en/v1.3.4/web3-eth-accounts.html#sign[Web3.js]\n * - with https://docs.ethers.io/v5/api/signer/#Signer-signMessage[ethers]\n *\n * _Available since v4.3._\n */\n function tryRecover(bytes32 hash, bytes memory signature) internal pure returns (address, RecoverError) {\n if (signature.length == 65) {\n bytes32 r;\n bytes32 s;\n uint8 v;\n // ecrecover takes the signature parameters, and the only way to get them\n // currently is to use assembly.\n /// @solidity memory-safe-assembly\n assembly {\n r := mload(add(signature, 0x20))\n s := mload(add(signature, 0x40))\n v := byte(0, mload(add(signature, 0x60)))\n }\n return tryRecover(hash, v, r, s);\n } else {\n return (address(0), RecoverError.InvalidSignatureLength);\n }\n }\n\n /**\n * @dev Returns the address that signed a hashed message (`hash`) with\n * `signature`. This address can then be used for verification purposes.\n *\n * The `ecrecover` EVM opcode allows for malleable (non-unique) signatures:\n * this function rejects them by requiring the `s` value to be in the lower\n * half order, and the `v` value to be either 27 or 28.\n *\n * IMPORTANT: `hash` _must_ be the result of a hash operation for the\n * verification to be secure: it is possible to craft signatures that\n * recover to arbitrary addresses for non-hashed data. A safe way to ensure\n * this is by receiving a hash of the original message (which may otherwise\n * be too long), and then calling {toEthSignedMessageHash} on it.\n */\n function recover(bytes32 hash, bytes memory signature) internal pure returns (address) {\n (address recovered, RecoverError error) = tryRecover(hash, signature);\n _throwError(error);\n return recovered;\n }\n\n /**\n * @dev Overload of {ECDSA-tryRecover} that receives the `r` and `vs` short-signature fields separately.\n *\n * See https://eips.ethereum.org/EIPS/eip-2098[EIP-2098 short signatures]\n *\n * _Available since v4.3._\n */\n function tryRecover(bytes32 hash, bytes32 r, bytes32 vs) internal pure returns (address, RecoverError) {\n bytes32 s = vs \u0026 bytes32(0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff);\n uint8 v = uint8((uint256(vs) \u003e\u003e 255) + 27);\n return tryRecover(hash, v, r, s);\n }\n\n /**\n * @dev Overload of {ECDSA-recover} that receives the `r and `vs` short-signature fields separately.\n *\n * _Available since v4.2._\n */\n function recover(bytes32 hash, bytes32 r, bytes32 vs) internal pure returns (address) {\n (address recovered, RecoverError error) = tryRecover(hash, r, vs);\n _throwError(error);\n return recovered;\n }\n\n /**\n * @dev Overload of {ECDSA-tryRecover} that receives the `v`,\n * `r` and `s` signature fields separately.\n *\n * _Available since v4.3._\n */\n function tryRecover(bytes32 hash, uint8 v, bytes32 r, bytes32 s) internal pure returns (address, RecoverError) {\n // EIP-2 still allows signature malleability for ecrecover(). Remove this possibility and make the signature\n // unique. Appendix F in the Ethereum Yellow paper (https://ethereum.github.io/yellowpaper/paper.pdf), defines\n // the valid range for s in (301): 0 \u003c s \u003c secp256k1n ÷ 2 + 1, and for v in (302): v ∈ {27, 28}. Most\n // signatures from current libraries generate a unique signature with an s-value in the lower half order.\n //\n // If your library generates malleable signatures, such as s-values in the upper range, calculate a new s-value\n // with 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141 - s1 and flip v from 27 to 28 or\n // vice versa. If your library also generates signatures with 0/1 for v instead 27/28, add 27 to v to accept\n // these malleable signatures as well.\n if (uint256(s) \u003e 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0) {\n return (address(0), RecoverError.InvalidSignatureS);\n }\n\n // If the signature is valid (and not malleable), return the signer address\n address signer = ecrecover(hash, v, r, s);\n if (signer == address(0)) {\n return (address(0), RecoverError.InvalidSignature);\n }\n\n return (signer, RecoverError.NoError);\n }\n\n /**\n * @dev Overload of {ECDSA-recover} that receives the `v`,\n * `r` and `s` signature fields separately.\n */\n function recover(bytes32 hash, uint8 v, bytes32 r, bytes32 s) internal pure returns (address) {\n (address recovered, RecoverError error) = tryRecover(hash, v, r, s);\n _throwError(error);\n return recovered;\n }\n\n /**\n * @dev Returns an Ethereum Signed Message, created from a `hash`. This\n * produces hash corresponding to the one signed with the\n * https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`]\n * JSON-RPC method as part of EIP-191.\n *\n * See {recover}.\n */\n function toEthSignedMessageHash(bytes32 hash) internal pure returns (bytes32 message) {\n // 32 is the length in bytes of hash,\n // enforced by the type signature above\n /// @solidity memory-safe-assembly\n assembly {\n mstore(0x00, \"\\x19Ethereum Signed Message:\\n32\")\n mstore(0x1c, hash)\n message := keccak256(0x00, 0x3c)\n }\n }\n\n /**\n * @dev Returns an Ethereum Signed Message, created from `s`. This\n * produces hash corresponding to the one signed with the\n * https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`]\n * JSON-RPC method as part of EIP-191.\n *\n * See {recover}.\n */\n function toEthSignedMessageHash(bytes memory s) internal pure returns (bytes32) {\n return keccak256(abi.encodePacked(\"\\x19Ethereum Signed Message:\\n\", Strings.toString(s.length), s));\n }\n\n /**\n * @dev Returns an Ethereum Signed Typed Data, created from a\n * `domainSeparator` and a `structHash`. This produces hash corresponding\n * to the one signed with the\n * https://eips.ethereum.org/EIPS/eip-712[`eth_signTypedData`]\n * JSON-RPC method as part of EIP-712.\n *\n * See {recover}.\n */\n function toTypedDataHash(bytes32 domainSeparator, bytes32 structHash) internal pure returns (bytes32 data) {\n /// @solidity memory-safe-assembly\n assembly {\n let ptr := mload(0x40)\n mstore(ptr, \"\\x19\\x01\")\n mstore(add(ptr, 0x02), domainSeparator)\n mstore(add(ptr, 0x22), structHash)\n data := keccak256(ptr, 0x42)\n }\n }\n\n /**\n * @dev Returns an Ethereum Signed Data with intended validator, created from a\n * `validator` and `data` according to the version 0 of EIP-191.\n *\n * See {recover}.\n */\n function toDataWithIntendedValidatorHash(address validator, bytes memory data) internal pure returns (bytes32) {\n return keccak256(abi.encodePacked(\"\\x19\\x00\", validator, data));\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/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/inbox/StatementInbox.sol\n\n// ══════════════════════════════ LIBRARY IMPORTS ══════════════════════════════\n\n// ═════════════════════════════ INTERNAL IMPORTS ══════════════════════════════\n\n// ═════════════════════════════ EXTERNAL IMPORTS ══════════════════════════════\n\n/// @notice `StatementInbox` is the entry point for all agent-signed statements. It verifies the\n/// agent signatures, and passes the unsigned statements to the contract to consume it via `acceptX` functions. Is is\n/// also used to verify the agent-signed statements and initiate the agent slashing, should the statement be invalid.\n/// `StatementInbox` is responsible for the following:\n/// - Accepting State and Receipt Reports to initiate a dispute between Guard and Notary.\n/// - Storing all the Guard Reports with the Guard signature leading to a dispute.\n/// - Verifying State/State Reports referencing the local chain and slashing the signer if statement is invalid.\n/// - Verifying Receipt/Receipt Reports referencing the local chain and slashing the signer if statement is invalid.\nabstract contract StatementInbox is MessagingBase, StatementInboxEvents, IStatementInbox {\n using AttestationLib for bytes;\n using ReceiptLib for bytes;\n using StateLib for bytes;\n using SnapshotLib for bytes;\n\n struct StoredReport {\n uint256 sigIndex;\n bytes statementPayload;\n }\n\n // ══════════════════════════════════════════════════ STORAGE ══════════════════════════════════════════════════════\n\n address public agentManager;\n address public origin;\n address public destination;\n\n // TODO: optimize this\n bytes[] internal _storedSignatures;\n StoredReport[] internal _storedReports;\n\n /// @dev gap for upgrade safety\n uint256[45] private __GAP; // solhint-disable-line var-name-mixedcase\n\n // ════════════════════════════════════════════════ INITIALIZER ════════════════════════════════════════════════════\n\n /// @dev Initializes the contract:\n /// - Sets up `msg.sender` as the owner of the contract.\n /// - Sets up `agentManager`, `origin`, and `destination`.\n // solhint-disable-next-line func-name-mixedcase\n function __StatementInbox_init(address agentManager_, address origin_, address destination_)\n internal\n onlyInitializing\n {\n agentManager = agentManager_;\n origin = origin_;\n destination = destination_;\n __Ownable2Step_init();\n }\n\n // ══════════════════════════════════════════ SUBMIT AGENT STATEMENTS ══════════════════════════════════════════════\n\n /// @inheritdoc IStatementInbox\n // solhint-disable-next-line ordering\n function submitStateReportWithSnapshot(\n uint8 stateIndex,\n bytes memory srSignature,\n bytes memory snapPayload,\n bytes memory snapSignature\n ) external returns (bool wasAccepted) {\n // This will revert if payload is not a snapshot\n Snapshot snapshot = snapPayload.castToSnapshot();\n // This will revert if the snapshot signer is not a known Notary\n (AgentStatus memory notaryStatus,) =\n _verifySnapshot({snapshot: snapshot, snapSignature: snapSignature, verifyNotary: true});\n // Notary needs to be Active/Unstaking\n notaryStatus.verifyActiveUnstaking();\n // Check if Notary is active on this chain\n _verifyNotaryDomain(notaryStatus.domain);\n // This will revert if state index is out of range\n State state = snapshot.state(stateIndex);\n // This will revert if the report signer is not an known Guard\n (AgentStatus memory guardStatus,) = _verifyStateReport(state, srSignature);\n // Check that Guard is active\n guardStatus.verifyActive();\n _saveReport(state.unwrap().clone(), srSignature);\n // This will revert if either actor is already in dispute\n IAgentManager(agentManager).openDispute(guardStatus.index, notaryStatus.index);\n return true;\n }\n\n /// @inheritdoc IStatementInbox\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 // This will revert if payload is not a snapshot\n Snapshot snapshot = snapPayload.castToSnapshot();\n // This will revert if state index is out of range\n State state = snapshot.state(stateIndex);\n // This will revert if the report signer is not an known Guard\n (AgentStatus memory guardStatus,) = _verifyStateReport(state, srSignature);\n // Check that Guard is active\n guardStatus.verifyActive();\n // This will revert if payload is not an attestation\n Attestation att = attPayload.castToAttestation();\n // This will revert if signer is not an known Notary\n (AgentStatus memory notaryStatus,) = _verifyAttestation(att, attSignature);\n // Notary needs to be Active/Unstaking\n notaryStatus.verifyActiveUnstaking();\n // Check if Notary is active on this chain\n _verifyNotaryDomain(notaryStatus.domain);\n if (snapshot.calculateRoot() != att.snapRoot()) revert IncorrectSnapshotRoot();\n _saveReport(state.unwrap().clone(), srSignature);\n // This will revert if either actor is already in dispute\n IAgentManager(agentManager).openDispute(guardStatus.index, notaryStatus.index);\n return true;\n }\n\n /// @inheritdoc IStatementInbox\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 // This will revert if payload is not a state\n State state = statePayload.castToState();\n // This will revert if the report signer is not an known Guard\n (AgentStatus memory guardStatus,) = _verifyStateReport(state, srSignature);\n // Check that Guard is active\n guardStatus.verifyActive();\n // This will revert if payload is not an attestation\n Attestation att = attPayload.castToAttestation();\n // This will revert if signer is not a known Notary\n (AgentStatus memory notaryStatus,) = _verifyAttestation(att, attSignature);\n // Notary needs to be Active/Unstaking\n notaryStatus.verifyActiveUnstaking();\n // Check if Notary is active on this chain\n _verifyNotaryDomain(notaryStatus.domain);\n // This will revert if any of these is true:\n // - Attestation root is not equal to Merkle Root derived from State and Snapshot Proof.\n // - Snapshot Proof's first element does not match the State metadata.\n // - Snapshot Proof length exceeds Snapshot tree Height.\n // - State index is out of range.\n _verifySnapshotMerkle(att, stateIndex, state, snapProof);\n _saveReport(statePayload, srSignature);\n // This will revert if either actor is already in dispute\n IAgentManager(agentManager).openDispute(guardStatus.index, notaryStatus.index);\n return true;\n }\n\n // ══════════════════════════════════════════ VERIFY AGENT STATEMENTS ══════════════════════════════════════════════\n\n /// @inheritdoc IStatementInbox\n function verifyReceipt(bytes memory rcptPayload, bytes memory rcptSignature)\n external\n returns (bool isValidReceipt)\n {\n // This will revert if payload is not a receipt\n Receipt rcpt = rcptPayload.castToReceipt();\n // This will revert if the attestation signer is not a known Notary\n (AgentStatus memory status, address notary) = _verifyReceipt(rcpt, rcptSignature);\n // Notary needs to be Active/Unstaking\n status.verifyActiveUnstaking();\n isValidReceipt = IExecutionHub(destination).isValidReceipt(rcptPayload);\n if (!isValidReceipt) {\n emit InvalidReceipt(rcptPayload, rcptSignature);\n IAgentManager(agentManager).slashAgent(status.domain, notary, msg.sender);\n }\n }\n\n /// @inheritdoc IStatementInbox\n function verifyReceiptReport(bytes memory rcptPayload, bytes memory rrSignature)\n external\n returns (bool isValidReport)\n {\n // This will revert if payload is not a receipt\n Receipt rcpt = rcptPayload.castToReceipt();\n // This will revert if the report signer is not a known Guard\n (AgentStatus memory status, address guard) = _verifyReceiptReport(rcpt, rrSignature);\n // Guard needs to be Active/Unstaking\n status.verifyActiveUnstaking();\n // Report is valid IF AND ONLY IF the reported receipt in invalid\n isValidReport = !IExecutionHub(destination).isValidReceipt(rcptPayload);\n if (!isValidReport) {\n emit InvalidReceiptReport(rcptPayload, rrSignature);\n IAgentManager(agentManager).slashAgent(status.domain, guard, msg.sender);\n }\n }\n\n /// @inheritdoc IStatementInbox\n function verifyStateWithAttestation(\n uint8 stateIndex,\n bytes memory snapPayload,\n bytes memory attPayload,\n bytes memory attSignature\n ) external returns (bool isValidState) {\n // This will revert if payload is not an attestation\n Attestation att = attPayload.castToAttestation();\n // This will revert if the attestation signer is not a known Notary\n (AgentStatus memory status, address notary) = _verifyAttestation(att, attSignature);\n // Notary needs to be Active/Unstaking\n status.verifyActiveUnstaking();\n // This will revert if payload is not a snapshot\n Snapshot snapshot = snapPayload.castToSnapshot();\n if (snapshot.calculateRoot() != att.snapRoot()) revert IncorrectSnapshotRoot();\n // This will revert if state does not refer to this chain\n bytes memory statePayload = snapshot.state(stateIndex).unwrap().clone();\n isValidState = IStateHub(origin).isValidState(statePayload);\n if (!isValidState) {\n emit InvalidStateWithAttestation(stateIndex, statePayload, attPayload, attSignature);\n IAgentManager(agentManager).slashAgent(status.domain, notary, msg.sender);\n }\n }\n\n /// @inheritdoc IStatementInbox\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 // This will revert if payload is not an attestation\n Attestation att = attPayload.castToAttestation();\n // This will revert if the attestation signer is not a known Notary\n (AgentStatus memory status, address notary) = _verifyAttestation(att, attSignature);\n // Notary needs to be Active/Unstaking\n status.verifyActiveUnstaking();\n // This will revert if payload is not a state\n State state = statePayload.castToState();\n // This will revert if any of these is true:\n // - Attestation root is not equal to Merkle Root derived from State and Snapshot Proof.\n // - Snapshot Proof's first element does not match the State metadata.\n // - Snapshot Proof length exceeds Snapshot tree Height.\n // - State index is out of range.\n _verifySnapshotMerkle(att, stateIndex, state, snapProof);\n // This will revert if state does not refer to this chain\n isValidState = IStateHub(origin).isValidState(statePayload);\n if (!isValidState) {\n emit InvalidStateWithAttestation(stateIndex, statePayload, attPayload, attSignature);\n IAgentManager(agentManager).slashAgent(status.domain, notary, msg.sender);\n }\n }\n\n /// @inheritdoc IStatementInbox\n function verifyStateWithSnapshot(uint8 stateIndex, bytes memory snapPayload, bytes memory snapSignature)\n external\n returns (bool isValidState)\n {\n // This will revert if payload is not a snapshot\n Snapshot snapshot = snapPayload.castToSnapshot();\n // This will revert if the snapshot signer is not a known Guard/Notary\n (AgentStatus memory status, address agent) =\n _verifySnapshot({snapshot: snapshot, snapSignature: snapSignature, verifyNotary: false});\n // Agent needs to be Active/Unstaking\n status.verifyActiveUnstaking();\n // This will revert if state does not refer to this chain\n isValidState = IStateHub(origin).isValidState(snapshot.state(stateIndex).unwrap().clone());\n if (!isValidState) {\n emit InvalidStateWithSnapshot(stateIndex, snapPayload, snapSignature);\n IAgentManager(agentManager).slashAgent(status.domain, agent, msg.sender);\n }\n }\n\n /// @inheritdoc IStatementInbox\n function verifyStateReport(bytes memory statePayload, bytes memory srSignature)\n external\n returns (bool isValidReport)\n {\n // This will revert if payload is not a state\n State state = statePayload.castToState();\n // This will revert if the report signer is not a known Guard\n (AgentStatus memory status, address guard) = _verifyStateReport(state, srSignature);\n // Guard needs to be Active/Unstaking\n status.verifyActiveUnstaking();\n // Report is valid IF AND ONLY IF the reported state in invalid\n // This will revert if the reported state does not refer to this chain\n isValidReport = !IStateHub(origin).isValidState(statePayload);\n if (!isValidReport) {\n emit InvalidStateReport(statePayload, srSignature);\n IAgentManager(agentManager).slashAgent(status.domain, guard, msg.sender);\n }\n }\n\n // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════\n\n /// @inheritdoc IStatementInbox\n function getReportsAmount() external view returns (uint256) {\n return _storedReports.length;\n }\n\n /// @inheritdoc IStatementInbox\n function getGuardReport(uint256 index)\n external\n view\n returns (bytes memory statementPayload, bytes memory reportSignature)\n {\n if (index \u003e= _storedReports.length) revert IndexOutOfRange();\n StoredReport memory storedReport = _storedReports[index];\n statementPayload = storedReport.statementPayload;\n reportSignature = _storedSignatures[storedReport.sigIndex];\n }\n\n /// @inheritdoc IStatementInbox\n function getStoredSignature(uint256 index) external view returns (bytes memory) {\n return _storedSignatures[index];\n }\n\n // ══════════════════════════════════════════════ INTERNAL LOGIC ═══════════════════════════════════════════════════\n\n /// @dev Saves the statement reported by Guard as invalid and the Guard Report signature.\n function _saveReport(bytes memory statementPayload, bytes memory reportSignature) internal {\n uint256 sigIndex = _saveSignature(reportSignature);\n _storedReports.push(StoredReport(sigIndex, statementPayload));\n }\n\n /// @dev Saves the signature and returns its index.\n function _saveSignature(bytes memory signature) internal returns (uint256 sigIndex) {\n sigIndex = _storedSignatures.length;\n _storedSignatures.push(signature);\n }\n\n // ═══════════════════════════════════════════════ AGENT CHECKS ════════════════════════════════════════════════════\n\n /**\n * @dev Recovers a signer from a hashed message, and a EIP-191 signature for it.\n * Will revert, if the signer is not a known agent.\n * @dev Agent flag could be any of these: Active/Unstaking/Resting/Fraudulent/Slashed\n * Further checks need to be performed in a caller function.\n * @param hashedStatement Hash of the statement that was signed by an Agent\n * @param signature Agent signature for the hashed statement\n * @return status Struct representing agent status:\n * - flag Unknown/Active/Unstaking/Resting/Fraudulent/Slashed\n * - domain Domain where agent is/was active\n * - index Index of agent in the Agent Merkle Tree\n * @return agent Agent that signed the statement\n */\n function _recoverAgent(bytes32 hashedStatement, bytes memory signature)\n internal\n view\n returns (AgentStatus memory status, address agent)\n {\n bytes32 ethSignedMsg = ECDSA.toEthSignedMessageHash(hashedStatement);\n agent = ECDSA.recover(ethSignedMsg, signature);\n status = IAgentManager(agentManager).agentStatus(agent);\n // Discard signature of unknown agents.\n // Further flag checks are supposed to be performed in a caller function.\n status.verifyKnown();\n }\n\n /// @dev Verifies that Notary signature is active on local domain.\n function _verifyNotaryDomain(uint32 notaryDomain) internal view {\n // Notary needs to be from the local domain (if contract is not deployed on Synapse Chain).\n // Or Notary could be from any domain (if contract is deployed on Synapse Chain).\n if (notaryDomain != localDomain \u0026\u0026 localDomain != synapseDomain) revert IncorrectAgentDomain();\n }\n\n // ════════════════════════════════════════ ATTESTATION RELATED CHECKS ═════════════════════════════════════════════\n\n /**\n * @dev Internal function to verify the signed attestation payload.\n * Reverts if any of these is true:\n * - Attestation signer is not a known Notary.\n * @param att Typed memory view over attestation payload\n * @param attSignature Notary signature for the attestation\n * @return status Struct representing agent status, see {_recoverAgent}\n * @return notary Notary that signed the snapshot\n */\n function _verifyAttestation(Attestation att, bytes memory attSignature)\n internal\n view\n returns (AgentStatus memory status, address notary)\n {\n // This will revert if signer is not a known agent\n (status, notary) = _recoverAgent(att.hashValid(), attSignature);\n // Attestation signer needs to be a Notary, not a Guard\n if (status.domain == 0) revert AgentNotNotary();\n }\n\n /**\n * @dev Internal function to verify the signed attestation report payload.\n * Reverts if any of these is true:\n * - Report signer is not a known Guard.\n * @param att Typed memory view over attestation payload that Guard reports as invalid\n * @param arSignature Guard signature for the \"invalid attestation\" report\n * @return status Struct representing guard status, see {_recoverAgent}\n * @return guard Guard that signed the report\n */\n function _verifyAttestationReport(Attestation att, bytes memory arSignature)\n internal\n view\n returns (AgentStatus memory status, address guard)\n {\n // This will revert if signer is not a known agent\n (status, guard) = _recoverAgent(att.hashInvalid(), arSignature);\n // Report signer needs to be a Guard, not a Notary\n if (status.domain != 0) revert AgentNotGuard();\n }\n\n // ══════════════════════════════════════════ RECEIPT RELATED CHECKS ═══════════════════════════════════════════════\n\n /**\n * @dev Internal function to verify the signed receipt payload.\n * Reverts if any of these is true:\n * - Receipt signer is not a known Notary.\n * @param rcpt Typed memory view over receipt payload\n * @param rcptSignature Notary signature for the receipt\n * @return status Struct representing agent status, see {_recoverAgent}\n * @return notary Notary that signed the snapshot\n */\n function _verifyReceipt(Receipt rcpt, bytes memory rcptSignature)\n internal\n view\n returns (AgentStatus memory status, address notary)\n {\n // This will revert if signer is not a known agent\n (status, notary) = _recoverAgent(rcpt.hashValid(), rcptSignature);\n // Receipt signer needs to be a Notary, not a Guard\n if (status.domain == 0) revert AgentNotNotary();\n }\n\n /**\n * @dev Internal function to verify the signed receipt report payload.\n * Reverts if any of these is true:\n * - Report signer is not a known Guard.\n * @param rcpt Typed memory view over receipt payload that Guard reports as invalid\n * @param rrSignature Guard signature for the \"invalid receipt\" report\n * @return status Struct representing guard status, see {_recoverAgent}\n * @return guard Guard that signed the report\n */\n function _verifyReceiptReport(Receipt rcpt, bytes memory rrSignature)\n internal\n view\n returns (AgentStatus memory status, address guard)\n {\n // This will revert if signer is not a known agent\n (status, guard) = _recoverAgent(rcpt.hashInvalid(), rrSignature);\n // Report signer needs to be a Guard, not a Notary\n if (status.domain != 0) revert AgentNotGuard();\n }\n\n // ═══════════════════════════════════════ STATE/SNAPSHOT RELATED CHECKS ═══════════════════════════════════════════\n\n /**\n * @dev Internal function to verify the signed snapshot report payload.\n * Reverts if any of these is true:\n * - Report signer is not a known Guard.\n * @param state Typed memory view over state payload that Guard reports as invalid\n * @param srSignature Guard signature for the report\n * @return status Struct representing guard status, see {_recoverAgent}\n * @return guard Guard that signed the report\n */\n function _verifyStateReport(State state, bytes memory srSignature)\n internal\n view\n returns (AgentStatus memory status, address guard)\n {\n // This will revert if signer is not a known agent\n (status, guard) = _recoverAgent(state.hashInvalid(), srSignature);\n // Report signer needs to be a Guard, not a Notary\n if (status.domain != 0) revert AgentNotGuard();\n }\n\n /**\n * @dev Internal function to verify the signed snapshot payload.\n * Reverts if any of these is true:\n * - Snapshot signer is not a known Agent.\n * - Snapshot signer is not a Notary (if verifyNotary is true).\n * @param snapshot Typed memory view over snapshot payload\n * @param snapSignature Agent signature for the snapshot\n * @param verifyNotary If true, snapshot signer needs to be a Notary, not a Guard\n * @return status Struct representing agent status, see {_recoverAgent}\n * @return agent Agent that signed the snapshot\n */\n function _verifySnapshot(Snapshot snapshot, bytes memory snapSignature, bool verifyNotary)\n internal\n view\n returns (AgentStatus memory status, address agent)\n {\n // This will revert if signer is not a known agent\n (status, agent) = _recoverAgent(snapshot.hashValid(), snapSignature);\n // If requested, snapshot signer needs to be a Notary, not a Guard\n if (verifyNotary \u0026\u0026 status.domain == 0) revert AgentNotNotary();\n }\n\n // ═══════════════════════════════════════════ MERKLE RELATED CHECKS ═══════════════════════════════════════════════\n\n /**\n * @dev Internal function to verify that snapshot roots match.\n * Reverts if any of these is true:\n * - Attestation root is not equal to Merkle Root derived from State and Snapshot Proof.\n * - Snapshot Proof's first element does not match the State metadata.\n * - Snapshot Proof length exceeds Snapshot tree Height.\n * - State index is out of range.\n * @param att Typed memory view over Attestation\n * @param stateIndex Index of state in the snapshot\n * @param state Typed memory view over the provided state payload\n * @param snapProof Raw payload with snapshot data\n */\n function _verifySnapshotMerkle(Attestation att, uint8 stateIndex, State state, bytes32[] memory snapProof)\n internal\n pure\n {\n // Snapshot proof first element should match State metadata (aka \"right sub-leaf\")\n (, bytes32 rightSubLeaf) = state.subLeafs();\n if (snapProof[0] != rightSubLeaf) revert IncorrectSnapshotProof();\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(state.root(), state.origin(), snapProof, stateIndex);\n // Snapshot root should match the attestation root\n if (att.snapRoot() != snapshotRoot) revert IncorrectSnapshotRoot();\n }\n}\n\n// contracts/inbox/Inbox.sol\n\n// ══════════════════════════════ LIBRARY IMPORTS ══════════════════════════════\n\n// ═════════════════════════════ INTERNAL IMPORTS ══════════════════════════════\n\n/// @notice `Inbox` is the child of `StatementInbox` contract, that is used on Synapse Chain.\n/// In addition to the functionality of `StatementInbox`, it also:\n/// - Accepts Guard and Notary Snapshots and passes them to `Summit` contract.\n/// - Accepts Notary-signed Receipts and passes them to `Summit` contract.\n/// - Accepts Receipt Reports to initiate a dispute between Guard and Notary.\n/// - Verifies Attestations and Attestation Reports, and slashes the signer if they are invalid.\ncontract Inbox is StatementInbox, InboxEvents, InterfaceInbox {\n using AttestationLib for bytes;\n using ReceiptLib for bytes;\n using SnapshotLib for bytes;\n\n // Struct to get around stack too deep error. TODO: revisit this\n struct ReceiptInfo {\n AgentStatus rcptNotaryStatus;\n address notary;\n uint32 attNonce;\n AgentStatus attNotaryStatus;\n }\n\n // ══════════════════════════════════════════════════ STORAGE ══════════════════════════════════════════════════════\n\n // The address of the Summit contract.\n address public summit;\n\n // ═════════════════════════════════════════ CONSTRUCTOR \u0026 INITIALIZER ═════════════════════════════════════════════\n\n constructor(uint32 synapseDomain_) MessagingBase(\"0.0.3\", synapseDomain_) {\n if (localDomain != synapseDomain) revert MustBeSynapseDomain();\n }\n\n /// @notice Initializes `Inbox` contract:\n /// - Sets `msg.sender` as the owner of the contract\n /// - Sets `agentManager`, `origin`, `destination` and `summit` addresses\n function initialize(address agentManager_, address origin_, address destination_, address summit_)\n external\n initializer\n {\n __StatementInbox_init(agentManager_, origin_, destination_);\n summit = summit_;\n }\n\n // ══════════════════════════════════════════ SUBMIT AGENT STATEMENTS ══════════════════════════════════════════════\n\n /// @inheritdoc InterfaceInbox\n function submitSnapshot(bytes memory snapPayload, bytes memory snapSignature)\n external\n returns (bytes memory attPayload, bytes32 agentRoot_, uint256[] memory snapGas)\n {\n // This will revert if payload is not a snapshot\n Snapshot snapshot = snapPayload.castToSnapshot();\n // This will revert if the signer is not a known Guard/Notary\n (AgentStatus memory status, address agent) =\n _verifySnapshot({snapshot: snapshot, snapSignature: snapSignature, verifyNotary: false});\n // Check that Agent is active\n status.verifyActive();\n // Store Agent signature for the Snapshot\n uint256 sigIndex = _saveSignature(snapSignature);\n if (status.domain == 0) {\n // Guard that is in Dispute could still submit new snapshots, so we don't check that\n InterfaceSummit(summit).acceptGuardSnapshot({\n guardIndex: status.index,\n sigIndex: sigIndex,\n snapPayload: snapPayload\n });\n } else {\n // Get current agentRoot from AgentManager\n agentRoot_ = IAgentManager(agentManager).agentRoot();\n // This will revert if Notary is in Dispute\n attPayload = InterfaceSummit(summit).acceptNotarySnapshot({\n notaryIndex: status.index,\n sigIndex: sigIndex,\n agentRoot: agentRoot_,\n snapPayload: snapPayload\n });\n ChainGas[] memory snapGas_ = snapshot.snapGas();\n // Pass created attestation to Destination to enable executing messages coming to Synapse Chain\n InterfaceDestination(destination).acceptAttestation(\n status.index, type(uint256).max, attPayload, agentRoot_, snapGas_\n );\n // Use assembly to cast ChainGas[] to uint256[] without copying. Highest bits are left zeroed.\n // solhint-disable-next-line no-inline-assembly\n assembly {\n snapGas := snapGas_\n }\n }\n emit SnapshotAccepted(status.domain, agent, snapPayload, snapSignature);\n }\n\n /// @inheritdoc InterfaceInbox\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 // Struct to get around stack too deep error.\n ReceiptInfo memory info;\n // This will revert if payload is not a receipt\n Receipt rcpt = rcptPayload.castToReceipt();\n // This will revert if the receipt signer is not a known Notary\n (info.rcptNotaryStatus, info.notary) = _verifyReceipt(rcpt, rcptSignature);\n // Receipt Notary needs to be Active\n info.rcptNotaryStatus.verifyActive();\n info.attNonce = IExecutionHub(destination).getAttestationNonce(rcpt.snapshotRoot());\n if (info.attNonce == 0) revert IncorrectSnapshotRoot();\n // Attestation Notary domain needs to match the destination domain\n info.attNotaryStatus = IAgentManager(agentManager).agentStatus(rcpt.attNotary());\n if (info.attNotaryStatus.domain != rcpt.destination()) revert IncorrectAgentDomain();\n // Check that the correct tip values for the message were provided\n _verifyReceiptTips(rcpt.messageHash(), paddedTips, headerHash, bodyHash);\n // Store Notary signature for the Receipt\n uint256 sigIndex = _saveSignature(rcptSignature);\n // This will revert if Receipt Notary is in Dispute\n wasAccepted = InterfaceSummit(summit).acceptReceipt({\n rcptNotaryIndex: info.rcptNotaryStatus.index,\n attNotaryIndex: info.attNotaryStatus.index,\n sigIndex: sigIndex,\n attNonce: info.attNonce,\n paddedTips: paddedTips,\n rcptPayload: rcptPayload\n });\n if (wasAccepted) {\n emit ReceiptAccepted(info.rcptNotaryStatus.domain, info.notary, rcptPayload, rcptSignature);\n }\n }\n\n /// @inheritdoc InterfaceInbox\n function submitReceiptReport(bytes memory rcptPayload, bytes memory rcptSignature, bytes memory rrSignature)\n external\n returns (bool wasAccepted)\n {\n // This will revert if payload is not a receipt\n Receipt rcpt = rcptPayload.castToReceipt();\n // This will revert if the receipt signer is not a known Guard\n (AgentStatus memory guardStatus,) = _verifyReceiptReport(rcpt, rrSignature);\n // Guard needs to be Active\n guardStatus.verifyActive();\n // This will revert if report signer is not a known Notary\n (AgentStatus memory notaryStatus,) = _verifyReceipt(rcpt, rcptSignature);\n // Notary needs to be Active/Unstaking\n notaryStatus.verifyActiveUnstaking();\n _saveReport(rcptPayload, rrSignature);\n // This will revert if either actor is already in dispute\n IAgentManager(agentManager).openDispute(guardStatus.index, notaryStatus.index);\n return true;\n }\n\n /// @inheritdoc InterfaceInbox\n function passReceipt(uint32 attNotaryIndex, uint32 attNonce, uint256 paddedTips, bytes memory rcptPayload)\n external\n returns (bool wasAccepted)\n {\n // Only Destination can pass receipts\n if (msg.sender != destination) revert CallerNotDestination();\n return InterfaceSummit(summit).acceptReceipt({\n rcptNotaryIndex: attNotaryIndex,\n attNotaryIndex: attNotaryIndex,\n sigIndex: type(uint256).max,\n attNonce: attNonce,\n paddedTips: paddedTips,\n rcptPayload: rcptPayload\n });\n }\n\n // ══════════════════════════════════════════ VERIFY AGENT STATEMENTS ══════════════════════════════════════════════\n\n /// @inheritdoc InterfaceInbox\n function verifyAttestation(bytes memory attPayload, bytes memory attSignature)\n external\n returns (bool isValidAttestation)\n {\n // This will revert if payload is not an attestation\n Attestation att = attPayload.castToAttestation();\n // This will revert if the attestation signer is not a known Notary\n (AgentStatus memory status, address notary) = _verifyAttestation(att, attSignature);\n // Notary needs to be Active/Unstaking\n status.verifyActiveUnstaking();\n isValidAttestation = ISnapshotHub(summit).isValidAttestation(attPayload);\n if (!isValidAttestation) {\n emit InvalidAttestation(attPayload, attSignature);\n IAgentManager(agentManager).slashAgent(status.domain, notary, msg.sender);\n }\n }\n\n /// @inheritdoc InterfaceInbox\n function verifyAttestationReport(bytes memory attPayload, bytes memory arSignature)\n external\n returns (bool isValidReport)\n {\n // This will revert if payload is not an attestation\n Attestation att = attPayload.castToAttestation();\n // This will revert if the report signer is not a known Guard\n (AgentStatus memory status, address guard) = _verifyAttestationReport(att, arSignature);\n // Guard needs to be Active/Unstaking\n status.verifyActiveUnstaking();\n // Report is valid IF AND ONLY IF the reported attestation in invalid\n isValidReport = !ISnapshotHub(summit).isValidAttestation(attPayload);\n if (!isValidReport) {\n emit InvalidAttestationReport(attPayload, arSignature);\n IAgentManager(agentManager).slashAgent(status.domain, guard, msg.sender);\n }\n }\n\n // ══════════════════════════════════════════════ INTERNAL VIEWS ═══════════════════════════════════════════════════\n\n /// @dev Verifies that tips proof matches the message hash.\n function _verifyReceiptTips(bytes32 msgHash, uint256 paddedTips, bytes32 headerHash, bytes32 bodyHash)\n internal\n pure\n {\n Tips tips = TipsLib.wrapPadded(paddedTips);\n // full message leaf is (header, baseMessage), while base message leaf is (tips, remainingBody).\n if (MerkleMath.getParent(headerHash, MerkleMath.getParent(tips.leaf(), bodyHash)) != msgHash) {\n revert IncorrectTipsProof();\n }\n }\n}\n","language":"Solidity","languageVersion":"0.8.17","compilerVersion":"0.8.17","compilerOptions":"--combined-json bin,bin-runtime,srcmap,srcmap-runtime,abi,userdoc,devdoc,metadata,hashes --optimize --optimize-runs 10000 --allow-paths ., ./, ../","srcMap":"212461:8761:0:-:0;;;;;;;;;;;;;;;-1:-1:-1;;;212461:8761:0;;;;;;;;;;;;;;;;;","srcMapRuntime":"212461:8761:0:-:0;;;;;;;;","abiDefinition":[],"userDoc":{"kind":"user","methods":{},"version":1},"developerDoc":{"details":"Elliptic Curve Digital Signature Algorithm (ECDSA) operations. These functions can be used to verify that a message was signed by the holder of the private keys of a given address.","kind":"dev","methods":{},"version":1},"metadata":"{\"compiler\":{\"version\":\"0.8.17+commit.8df45f5f\"},\"language\":\"Solidity\",\"output\":{\"abi\":[],\"devdoc\":{\"details\":\"Elliptic Curve Digital Signature Algorithm (ECDSA) operations. These functions can be used to verify that a message was signed by the holder of the private keys of a given address.\",\"kind\":\"dev\",\"methods\":{},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"solidity/Inbox.sol\":\"ECDSA\"},\"evmVersion\":\"london\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\"},\"optimizer\":{\"enabled\":true,\"runs\":10000},\"remappings\":[]},\"sources\":{\"solidity/Inbox.sol\":{\"keccak256\":\"0x9b516081a036814c0169e20e484d4a5499066b7a6f48fada952b5e844a1ca3e5\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://32bde393b3f24ef4307d9626d4143f337b3c0bd34e17bb969fd5a15221d96987\",\"dweb:/ipfs/QmTkt2XZRtgsbSpmsVQUM3c4ebETQoDVYbmEV9yheBghnr\"]}},\"version\":1}"},"hashes":{}},"solidity/Inbox.sol:GasDataLib":{"code":"0x60566037600b82828239805160001a607314602a57634e487b7160e01b600052600060045260246000fd5b30600052607381538281f3fe73000000000000000000000000000000000000000030146080604052600080fdfea2646970667358221220b55a0518994c5506ebe14b08a21233e581d6e644b5a4174c0cc28ca4e48763e264736f6c63430008110033","runtime-code":"0x73000000000000000000000000000000000000000030146080604052600080fdfea2646970667358221220b55a0518994c5506ebe14b08a21233e581d6e644b5a4174c0cc28ca4e48763e264736f6c63430008110033","info":{"source":"// SPDX-License-Identifier: MIT\npragma solidity =0.8.17 ^0.8.0 ^0.8.1 ^0.8.2;\n\n// contracts/events/InboxEvents.sol\n\nabstract contract InboxEvents {\n /**\n * @notice Emitted when a snapshot is accepted by the Summit contract.\n * @param domain Domain where the signed Agent is active (ZERO for Guards)\n * @param agent Agent who signed the snapshot\n * @param snapPayload Raw payload with snapshot data\n * @param snapSignature Agent signature for the snapshot\n */\n event SnapshotAccepted(uint32 indexed domain, address indexed agent, bytes snapPayload, bytes snapSignature);\n\n /**\n * @notice Emitted when a snapshot is accepted by the Summit contract.\n * @param domain Domain where the signed Notary is active\n * @param notary Notary who signed the attestation\n * @param rcptPayload Raw payload with receipt data\n * @param rcptSignature Notary signature for the receipt\n */\n event ReceiptAccepted(uint32 domain, address notary, bytes rcptPayload, bytes rcptSignature);\n\n /**\n * @notice Emitted when a proof of invalid attestation is submitted.\n * @param attPayload Raw payload with Attestation data\n * @param attSignature Notary signature for the attestation\n */\n event InvalidAttestation(bytes attPayload, bytes attSignature);\n\n /**\n * @notice Emitted when a proof of invalid attestation report is submitted.\n * @param arPayload Raw payload with report data\n * @param arSignature Guard signature for the report\n */\n event InvalidAttestationReport(bytes arPayload, bytes arSignature);\n}\n\n// contracts/events/StatementInboxEvents.sol\n\nabstract contract StatementInboxEvents {\n // ════════════════════════════════════════════ STATEMENT ACCEPTED ═════════════════════════════════════════════════\n\n /**\n * @notice Emitted when a snapshot is accepted by the Destination contract.\n * @param domain Domain where the signed Notary is active\n * @param notary Notary who signed the attestation\n * @param attPayload Raw payload with attestation data\n * @param attSignature Notary signature for the attestation\n */\n event AttestationAccepted(uint32 domain, address notary, bytes attPayload, bytes attSignature);\n\n // ═════════════════════════════════════════ INVALID STATEMENT PROVED ══════════════════════════════════════════════\n\n /**\n * @notice Emitted when a proof of invalid receipt statement is submitted.\n * @param rcptPayload Raw payload with the receipt statement\n * @param rcptSignature Notary signature for the receipt statement\n */\n event InvalidReceipt(bytes rcptPayload, bytes rcptSignature);\n\n /**\n * @notice Emitted when a proof of invalid receipt report is submitted.\n * @param rrPayload Raw payload with report data\n * @param rrSignature Guard signature for the report\n */\n event InvalidReceiptReport(bytes rrPayload, bytes rrSignature);\n\n /**\n * @notice Emitted when a proof of invalid state in the signed attestation is submitted.\n * @param stateIndex Index of invalid state in the snapshot\n * @param statePayload Raw payload with state data\n * @param attPayload Raw payload with Attestation data for snapshot\n * @param attSignature Notary signature for the attestation\n */\n event InvalidStateWithAttestation(uint8 stateIndex, bytes statePayload, bytes attPayload, bytes attSignature);\n\n /**\n * @notice Emitted when a proof of invalid state in the signed snapshot is submitted.\n * @param stateIndex Index of invalid state in the snapshot\n * @param snapPayload Raw payload with snapshot data\n * @param snapSignature Agent signature for the snapshot\n */\n event InvalidStateWithSnapshot(uint8 stateIndex, bytes snapPayload, bytes snapSignature);\n\n /**\n * @notice Emitted when a proof of invalid state report is submitted.\n * @param srPayload Raw payload with report data\n * @param srSignature Guard signature for the report\n */\n event InvalidStateReport(bytes srPayload, bytes srSignature);\n}\n\n// contracts/interfaces/ISnapshotHub.sol\n\ninterface ISnapshotHub {\n /**\n * @notice Check that a given attestation is valid: matches the historical attestation\n * derived from an accepted Notary snapshot.\n * @dev Will revert if any of these is true:\n * - Attestation payload is not properly formatted.\n * @param attPayload Raw payload with attestation data\n * @return isValid Whether the provided attestation is valid\n */\n function isValidAttestation(bytes memory attPayload) external view returns (bool isValid);\n\n /**\n * @notice Returns saved attestation with the given nonce.\n * @dev Reverts if attestation with given nonce hasn't been created yet.\n * @param attNonce Nonce for the attestation\n * @return attPayload Raw payload with formatted Attestation data\n * @return agentRoot Agent root hash used for the attestation\n * @return snapGas Snapshot gas data used for the attestation\n */\n function getAttestation(uint32 attNonce)\n external\n view\n returns (bytes memory attPayload, bytes32 agentRoot, uint256[] memory snapGas);\n\n /**\n * @notice Returns the state with the highest known nonce submitted by a given Agent.\n * @param origin Domain of origin chain\n * @param agent Agent address\n * @return statePayload Raw payload with agent's latest state for origin\n */\n function getLatestAgentState(uint32 origin, address agent) external view returns (bytes memory statePayload);\n\n /**\n * @notice Returns latest saved attestation for a Notary.\n * @param notary Notary address\n * @return attPayload Raw payload with formatted Attestation data\n * @return agentRoot Agent root hash used for the attestation\n * @return snapGas Snapshot gas data used for the attestation\n */\n function getLatestNotaryAttestation(address notary)\n external\n view\n returns (bytes memory attPayload, bytes32 agentRoot, uint256[] memory snapGas);\n\n /**\n * @notice Returns Guard snapshot from the list of all accepted Guard snapshots.\n * @dev Reverts if snapshot with given index hasn't been accepted yet.\n * @param index Snapshot index in the list of all Guard snapshots\n * @return snapPayload Raw payload with Guard snapshot\n * @return snapSignature Raw payload with Guard signature for snapshot\n */\n function getGuardSnapshot(uint256 index)\n external\n view\n returns (bytes memory snapPayload, bytes memory snapSignature);\n\n /**\n * @notice Returns Notary snapshot from the list of all accepted Guard snapshots.\n * @dev Reverts if snapshot with given index hasn't been accepted yet.\n * @param index Snapshot index in the list of all Notary snapshots\n * @return snapPayload Raw payload with Notary snapshot\n * @return snapSignature Raw payload with Notary signature for snapshot\n */\n function getNotarySnapshot(uint256 index)\n external\n view\n returns (bytes memory snapPayload, bytes memory snapSignature);\n\n /**\n * @notice Returns Notary snapshot that was used for creating a given attestation.\n * @dev Reverts if any of these is true:\n * - Attestation payload is not properly formatted.\n * - Attestation is invalid (doesn't have a matching Notary snapshot).\n * @param attPayload Raw payload with attestation data\n * @return snapPayload Raw payload with Notary snapshot\n * @return snapSignature Raw payload with Notary signature for snapshot\n */\n function getNotarySnapshot(bytes memory attPayload)\n external\n view\n returns (bytes memory snapPayload, bytes memory snapSignature);\n\n /**\n * @notice Returns proof of inclusion of (root, origin) fields of a given snapshot's state\n * into the Snapshot Merkle Tree for a given attestation.\n * @dev Reverts if any of these is true:\n * - Attestation with given nonce hasn't been created yet.\n * - State index is out of range of snapshot list.\n * @param attNonce Nonce for the attestation\n * @param stateIndex Index of state in the attestation's snapshot\n * @return snapProof The snapshot proof\n */\n function getSnapshotProof(uint32 attNonce, uint8 stateIndex) external view returns (bytes32[] memory snapProof);\n}\n\n// contracts/interfaces/IStateHub.sol\n\ninterface IStateHub {\n /**\n * @notice Check that a given state is valid: matches the historical state of Origin contract.\n * Note: any Agent including an invalid state in their snapshot will be slashed\n * upon providing the snapshot and agent signature for it to Origin contract.\n * @dev Will revert if any of these is true:\n * - State payload is not properly formatted.\n * @param statePayload Raw payload with state data\n * @return isValid Whether the provided state is valid\n */\n function isValidState(bytes memory statePayload) external view returns (bool isValid);\n\n /**\n * @notice Returns the amount of saved states so far.\n * @dev This includes the initial state of \"empty Origin Merkle Tree\".\n */\n function statesAmount() external view returns (uint256);\n\n /**\n * @notice Suggest the data (state after latest sent message) to sign for an Agent.\n * Note: signing the suggested state data will will never lead to slashing of the actor,\n * assuming they have confirmed that the block, which number is included in the data,\n * is not subject to reorganization (which is different for every observed chain).\n * @return statePayload Raw payload with the latest state data\n */\n function suggestLatestState() external view returns (bytes memory statePayload);\n\n /**\n * @notice Given the historical nonce, suggest the state data to sign for an Agent.\n * Note: signing the suggested state data will will never lead to slashing of the actor,\n * assuming they have confirmed that the block, which number is included in the data,\n * is not subject to reorganization (which is different for every observed chain).\n * @param nonce Historical nonce to form a state\n * @return statePayload Raw payload with historical state data\n */\n function suggestState(uint32 nonce) external view returns (bytes memory statePayload);\n}\n\n// contracts/interfaces/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/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// node_modules/@openzeppelin/contracts/utils/math/Math.sol\n\n// OpenZeppelin Contracts (last updated v4.9.0) (utils/math/Math.sol)\n\n/**\n * @dev Standard math utilities missing in the Solidity language.\n */\nlibrary Math {\n enum Rounding {\n Down, // Toward negative infinity\n Up, // Toward infinity\n Zero // Toward zero\n }\n\n /**\n * @dev Returns the largest of two numbers.\n */\n function max(uint256 a, uint256 b) internal pure returns (uint256) {\n return a \u003e b ? a : b;\n }\n\n /**\n * @dev Returns the smallest of two numbers.\n */\n function min(uint256 a, uint256 b) internal pure returns (uint256) {\n return a \u003c b ? a : b;\n }\n\n /**\n * @dev Returns the average of two numbers. The result is rounded towards\n * zero.\n */\n function average(uint256 a, uint256 b) internal pure returns (uint256) {\n // (a + b) / 2 can overflow.\n return (a \u0026 b) + (a ^ b) / 2;\n }\n\n /**\n * @dev Returns the ceiling of the division of two numbers.\n *\n * This differs from standard division with `/` in that it rounds up instead\n * of rounding down.\n */\n function ceilDiv(uint256 a, uint256 b) internal pure returns (uint256) {\n // (a + b - 1) / b can overflow on addition, so we distribute.\n return a == 0 ? 0 : (a - 1) / b + 1;\n }\n\n /**\n * @notice Calculates floor(x * y / denominator) with full precision. Throws if result overflows a uint256 or denominator == 0\n * @dev Original credit to Remco Bloemen under MIT license (https://xn--2-umb.com/21/muldiv)\n * with further edits by Uniswap Labs also under MIT license.\n */\n function mulDiv(uint256 x, uint256 y, uint256 denominator) internal pure returns (uint256 result) {\n unchecked {\n // 512-bit multiply [prod1 prod0] = x * y. Compute the product mod 2^256 and mod 2^256 - 1, then use\n // use the Chinese Remainder Theorem to reconstruct the 512 bit result. The result is stored in two 256\n // variables such that product = prod1 * 2^256 + prod0.\n uint256 prod0; // Least significant 256 bits of the product\n uint256 prod1; // Most significant 256 bits of the product\n assembly {\n let mm := mulmod(x, y, not(0))\n prod0 := mul(x, y)\n prod1 := sub(sub(mm, prod0), lt(mm, prod0))\n }\n\n // Handle non-overflow cases, 256 by 256 division.\n if (prod1 == 0) {\n // Solidity will revert if denominator == 0, unlike the div opcode on its own.\n // The surrounding unchecked block does not change this fact.\n // See https://docs.soliditylang.org/en/latest/control-structures.html#checked-or-unchecked-arithmetic.\n return prod0 / denominator;\n }\n\n // Make sure the result is less than 2^256. Also prevents denominator == 0.\n require(denominator \u003e prod1, \"Math: mulDiv overflow\");\n\n ///////////////////////////////////////////////\n // 512 by 256 division.\n ///////////////////////////////////////////////\n\n // Make division exact by subtracting the remainder from [prod1 prod0].\n uint256 remainder;\n assembly {\n // Compute remainder using mulmod.\n remainder := mulmod(x, y, denominator)\n\n // Subtract 256 bit number from 512 bit number.\n prod1 := sub(prod1, gt(remainder, prod0))\n prod0 := sub(prod0, remainder)\n }\n\n // Factor powers of two out of denominator and compute largest power of two divisor of denominator. Always \u003e= 1.\n // See https://cs.stackexchange.com/q/138556/92363.\n\n // Does not overflow because the denominator cannot be zero at this stage in the function.\n uint256 twos = denominator \u0026 (~denominator + 1);\n assembly {\n // Divide denominator by twos.\n denominator := div(denominator, twos)\n\n // Divide [prod1 prod0] by twos.\n prod0 := div(prod0, twos)\n\n // Flip twos such that it is 2^256 / twos. If twos is zero, then it becomes one.\n twos := add(div(sub(0, twos), twos), 1)\n }\n\n // Shift in bits from prod1 into prod0.\n prod0 |= prod1 * twos;\n\n // Invert denominator mod 2^256. Now that denominator is an odd number, it has an inverse modulo 2^256 such\n // that denominator * inv = 1 mod 2^256. Compute the inverse by starting with a seed that is correct for\n // four bits. That is, denominator * inv = 1 mod 2^4.\n uint256 inverse = (3 * denominator) ^ 2;\n\n // Use the Newton-Raphson iteration to improve the precision. Thanks to Hensel's lifting lemma, this also works\n // in modular arithmetic, doubling the correct bits in each step.\n inverse *= 2 - denominator * inverse; // inverse mod 2^8\n inverse *= 2 - denominator * inverse; // inverse mod 2^16\n inverse *= 2 - denominator * inverse; // inverse mod 2^32\n inverse *= 2 - denominator * inverse; // inverse mod 2^64\n inverse *= 2 - denominator * inverse; // inverse mod 2^128\n inverse *= 2 - denominator * inverse; // inverse mod 2^256\n\n // Because the division is now exact we can divide by multiplying with the modular inverse of denominator.\n // This will give us the correct result modulo 2^256. Since the preconditions guarantee that the outcome is\n // less than 2^256, this is the final result. We don't need to compute the high bits of the result and prod1\n // is no longer required.\n result = prod0 * inverse;\n return result;\n }\n }\n\n /**\n * @notice Calculates x * y / denominator with full precision, following the selected rounding direction.\n */\n function mulDiv(uint256 x, uint256 y, uint256 denominator, Rounding rounding) internal pure returns (uint256) {\n uint256 result = mulDiv(x, y, denominator);\n if (rounding == Rounding.Up \u0026\u0026 mulmod(x, y, denominator) \u003e 0) {\n result += 1;\n }\n return result;\n }\n\n /**\n * @dev Returns the square root of a number. If the number is not a perfect square, the value is rounded down.\n *\n * Inspired by Henry S. Warren, Jr.'s \"Hacker's Delight\" (Chapter 11).\n */\n function sqrt(uint256 a) internal pure returns (uint256) {\n if (a == 0) {\n return 0;\n }\n\n // For our first guess, we get the biggest power of 2 which is smaller than the square root of the target.\n //\n // We know that the \"msb\" (most significant bit) of our target number `a` is a power of 2 such that we have\n // `msb(a) \u003c= a \u003c 2*msb(a)`. This value can be written `msb(a)=2**k` with `k=log2(a)`.\n //\n // This can be rewritten `2**log2(a) \u003c= a \u003c 2**(log2(a) + 1)`\n // → `sqrt(2**k) \u003c= sqrt(a) \u003c sqrt(2**(k+1))`\n // → `2**(k/2) \u003c= sqrt(a) \u003c 2**((k+1)/2) \u003c= 2**(k/2 + 1)`\n //\n // Consequently, `2**(log2(a) / 2)` is a good first approximation of `sqrt(a)` with at least 1 correct bit.\n uint256 result = 1 \u003c\u003c (log2(a) \u003e\u003e 1);\n\n // At this point `result` is an estimation with one bit of precision. We know the true value is a uint128,\n // since it is the square root of a uint256. Newton's method converges quadratically (precision doubles at\n // every iteration). We thus need at most 7 iteration to turn our partial result with one bit of precision\n // into the expected uint128 result.\n unchecked {\n result = (result + a / result) \u003e\u003e 1;\n result = (result + a / result) \u003e\u003e 1;\n result = (result + a / result) \u003e\u003e 1;\n result = (result + a / result) \u003e\u003e 1;\n result = (result + a / result) \u003e\u003e 1;\n result = (result + a / result) \u003e\u003e 1;\n result = (result + a / result) \u003e\u003e 1;\n return min(result, a / result);\n }\n }\n\n /**\n * @notice Calculates sqrt(a), following the selected rounding direction.\n */\n function sqrt(uint256 a, Rounding rounding) internal pure returns (uint256) {\n unchecked {\n uint256 result = sqrt(a);\n return result + (rounding == Rounding.Up \u0026\u0026 result * result \u003c a ? 1 : 0);\n }\n }\n\n /**\n * @dev Return the log in base 2, rounded down, of a positive value.\n * Returns 0 if given 0.\n */\n function log2(uint256 value) internal pure returns (uint256) {\n uint256 result = 0;\n unchecked {\n if (value \u003e\u003e 128 \u003e 0) {\n value \u003e\u003e= 128;\n result += 128;\n }\n if (value \u003e\u003e 64 \u003e 0) {\n value \u003e\u003e= 64;\n result += 64;\n }\n if (value \u003e\u003e 32 \u003e 0) {\n value \u003e\u003e= 32;\n result += 32;\n }\n if (value \u003e\u003e 16 \u003e 0) {\n value \u003e\u003e= 16;\n result += 16;\n }\n if (value \u003e\u003e 8 \u003e 0) {\n value \u003e\u003e= 8;\n result += 8;\n }\n if (value \u003e\u003e 4 \u003e 0) {\n value \u003e\u003e= 4;\n result += 4;\n }\n if (value \u003e\u003e 2 \u003e 0) {\n value \u003e\u003e= 2;\n result += 2;\n }\n if (value \u003e\u003e 1 \u003e 0) {\n result += 1;\n }\n }\n return result;\n }\n\n /**\n * @dev Return the log in base 2, following the selected rounding direction, of a positive value.\n * Returns 0 if given 0.\n */\n function log2(uint256 value, Rounding rounding) internal pure returns (uint256) {\n unchecked {\n uint256 result = log2(value);\n return result + (rounding == Rounding.Up \u0026\u0026 1 \u003c\u003c result \u003c value ? 1 : 0);\n }\n }\n\n /**\n * @dev Return the log in base 10, rounded down, of a positive value.\n * Returns 0 if given 0.\n */\n function log10(uint256 value) internal pure returns (uint256) {\n uint256 result = 0;\n unchecked {\n if (value \u003e= 10 ** 64) {\n value /= 10 ** 64;\n result += 64;\n }\n if (value \u003e= 10 ** 32) {\n value /= 10 ** 32;\n result += 32;\n }\n if (value \u003e= 10 ** 16) {\n value /= 10 ** 16;\n result += 16;\n }\n if (value \u003e= 10 ** 8) {\n value /= 10 ** 8;\n result += 8;\n }\n if (value \u003e= 10 ** 4) {\n value /= 10 ** 4;\n result += 4;\n }\n if (value \u003e= 10 ** 2) {\n value /= 10 ** 2;\n result += 2;\n }\n if (value \u003e= 10 ** 1) {\n result += 1;\n }\n }\n return result;\n }\n\n /**\n * @dev Return the log in base 10, following the selected rounding direction, of a positive value.\n * Returns 0 if given 0.\n */\n function log10(uint256 value, Rounding rounding) internal pure returns (uint256) {\n unchecked {\n uint256 result = log10(value);\n return result + (rounding == Rounding.Up \u0026\u0026 10 ** result \u003c value ? 1 : 0);\n }\n }\n\n /**\n * @dev Return the log in base 256, rounded down, of a positive value.\n * Returns 0 if given 0.\n *\n * Adding one to the result gives the number of pairs of hex symbols needed to represent `value` as a hex string.\n */\n function log256(uint256 value) internal pure returns (uint256) {\n uint256 result = 0;\n unchecked {\n if (value \u003e\u003e 128 \u003e 0) {\n value \u003e\u003e= 128;\n result += 16;\n }\n if (value \u003e\u003e 64 \u003e 0) {\n value \u003e\u003e= 64;\n result += 8;\n }\n if (value \u003e\u003e 32 \u003e 0) {\n value \u003e\u003e= 32;\n result += 4;\n }\n if (value \u003e\u003e 16 \u003e 0) {\n value \u003e\u003e= 16;\n result += 2;\n }\n if (value \u003e\u003e 8 \u003e 0) {\n result += 1;\n }\n }\n return result;\n }\n\n /**\n * @dev Return the log in base 256, following the selected rounding direction, of a positive value.\n * Returns 0 if given 0.\n */\n function log256(uint256 value, Rounding rounding) internal pure returns (uint256) {\n unchecked {\n uint256 result = log256(value);\n return result + (rounding == Rounding.Up \u0026\u0026 1 \u003c\u003c (result \u003c\u003c 3) \u003c value ? 1 : 0);\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/utils/math/SignedMath.sol\n\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/math/SignedMath.sol)\n\n/**\n * @dev Standard signed math utilities missing in the Solidity language.\n */\nlibrary SignedMath {\n /**\n * @dev Returns the largest of two signed numbers.\n */\n function max(int256 a, int256 b) internal pure returns (int256) {\n return a \u003e b ? a : b;\n }\n\n /**\n * @dev Returns the smallest of two signed numbers.\n */\n function min(int256 a, int256 b) internal pure returns (int256) {\n return a \u003c b ? a : b;\n }\n\n /**\n * @dev Returns the average of two signed numbers without overflow.\n * The result is rounded towards zero.\n */\n function average(int256 a, int256 b) internal pure returns (int256) {\n // Formula from the book \"Hacker's Delight\"\n int256 x = (a \u0026 b) + ((a ^ b) \u003e\u003e 1);\n return x + (int256(uint256(x) \u003e\u003e 255) \u0026 (a ^ b));\n }\n\n /**\n * @dev Returns the absolute unsigned value of a signed value.\n */\n function abs(int256 n) internal pure returns (uint256) {\n unchecked {\n // must be unchecked in order to support `n = type(int256).min`\n return uint256(n \u003e= 0 ? n : -n);\n }\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// 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/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/InterfaceSummit.sol\n\ninterface InterfaceSummit {\n // ══════════════════════════════════════════ ACCEPT AGENT STATEMENTS ══════════════════════════════════════════════\n\n /**\n * @notice Accepts a receipt, which local `AgentManager` verified to have been signed by an active Notary.\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 * - Notary who signed the receipt is referenced as the \"Receipt Notary\".\n * - Notary who signed the attestation on destination chain is referenced as the \"Attestation Notary\".\n * \u003e Will revert if any of these is true:\n * \u003e - Called by anyone other than local `AgentManager`.\n * \u003e - Receipt body payload is not properly formatted.\n * \u003e - Receipt signer is in Dispute.\n * \u003e - Receipt's snapshot root is unknown.\n * @param rcptNotaryIndex Index of Receipt Notary in Agent Merkle Tree\n * @param attNotaryIndex Index of Attestation Notary in Agent Merkle Tree\n * @param sigIndex Index of stored Notary signature\n * @param attNonce Nonce of the attestation used for proving the executed message\n * @param paddedTips Padded encoded paid tips information\n * @param rcptPayload Raw payload with message execution receipt\n * @return wasAccepted Whether the receipt was accepted\n */\n function acceptReceipt(\n uint32 rcptNotaryIndex,\n uint32 attNotaryIndex,\n uint256 sigIndex,\n uint32 attNonce,\n uint256 paddedTips,\n bytes memory rcptPayload\n ) external returns (bool wasAccepted);\n\n /**\n * @notice Accepts a snapshot, which local `AgentManager` verified to have been signed by an active Guard.\n * \u003e Snapshot is a list of states for a set of Origin contracts residing on any of the chains.\n * All the states in the Guard-signed snapshot become available for Notary signing.\n * \u003e Will revert if any of these is true:\n * \u003e - Called by anyone other than local `AgentManager`.\n * \u003e - Snapshot payload is not properly formatted.\n * \u003e - Snapshot contains a state older then the Guard has previously submitted.\n * @param guardIndex Index of Guard in Agent Merkle Tree\n * @param sigIndex Index of stored Agent signature\n * @param snapPayload Raw payload with snapshot data\n */\n function acceptGuardSnapshot(uint32 guardIndex, uint256 sigIndex, bytes memory snapPayload) external;\n\n /**\n * @notice Accepts a snapshot, which local `AgentManager` verified to have been signed by an active Notary.\n * \u003e Snapshot is a list of states for a set of Origin contracts residing on any of the chains.\n * Snapshot Merkle Root is calculated and saved for valid snapshots, i.e.\n * snapshots which are only using states previously submitted by any of the Guards.\n * - Notary could use states singed by the same of different Guards 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 - Called by anyone other than local `AgentManager`.\n * \u003e - Snapshot payload is not properly formatted.\n * \u003e - Snapshot contains a state older then the Notary has previously submitted.\n * \u003e - Snapshot contains a state that no Guard has previously submitted.\n * @param notaryIndex Index of Notary in Agent Merkle Tree\n * @param sigIndex Index of stored Agent signature\n * @param agentRoot Current root of the Agent Merkle Tree\n * @param snapPayload Raw payload with snapshot data\n * @return attPayload Raw payload with data for attestation derived from Notary snapshot.\n */\n function acceptNotarySnapshot(uint32 notaryIndex, uint256 sigIndex, bytes32 agentRoot, bytes memory snapPayload)\n external\n returns (bytes memory attPayload);\n\n // ════════════════════════════════════════════════ TIPS LOGIC ═════════════════════════════════════════════════════\n\n /**\n * @notice Distributes tips using the first Receipt from the \"receipt quarantine queue\".\n * Possible scenarios:\n * - Receipt queue is empty =\u003e does nothing\n * - Receipt optimistic period is not over =\u003e does nothing\n * - Either of Notaries present in Receipt was slashed =\u003e receipt is deleted from the queue\n * - Either of Notaries present in Receipt in Dispute =\u003e receipt is moved to the end of queue\n * - None of the above =\u003e receipt tips are distributed\n * @dev Returned value makes it possible to do the following: `while (distributeTips()) {}`\n * @return queuePopped Whether the first element was popped from the queue\n */\n function distributeTips() external returns (bool queuePopped);\n\n /**\n * @notice Withdraws locked base message tips from requested domain Origin to the recipient.\n * This is done by a call to a local Origin contract, or by a manager message to the remote chain.\n * @dev This will revert, if the pending balance of origin tips (earned-claimed) is lower than requested.\n * @param origin Domain of chain to withdraw tips on\n * @param amount Amount of tips to withdraw\n */\n function withdrawTips(uint32 origin, uint256 amount) external;\n\n // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════\n\n /**\n * @notice Returns earned and claimed tips for the actor.\n * Note: Tips for address(0) belong to the Treasury.\n * @param actor Address of the actor\n * @param origin Domain where the tips were initially paid\n * @return earned Total amount of origin tips the actor has earned so far\n * @return claimed Total amount of origin tips the actor has claimed so far\n */\n function actorTips(address actor, uint32 origin) external view returns (uint128 earned, uint128 claimed);\n\n /**\n * @notice Returns the amount of receipts in the \"Receipt Quarantine Queue\".\n */\n function receiptQueueLength() external view returns (uint256);\n\n /**\n * @notice Returns the state with the highest known nonce\n * submitted by any of the currently active Guards.\n * @param origin Domain of origin chain\n * @return statePayload Raw payload with latest active Guard state for origin\n */\n function getLatestState(uint32 origin) external view returns (bytes memory statePayload);\n}\n\n// node_modules/@openzeppelin/contracts/utils/Strings.sol\n\n// OpenZeppelin Contracts (last updated v4.9.0) (utils/Strings.sol)\n\n/**\n * @dev String operations.\n */\nlibrary Strings {\n bytes16 private constant _SYMBOLS = \"0123456789abcdef\";\n uint8 private constant _ADDRESS_LENGTH = 20;\n\n /**\n * @dev Converts a `uint256` to its ASCII `string` decimal representation.\n */\n function toString(uint256 value) internal pure returns (string memory) {\n unchecked {\n uint256 length = Math.log10(value) + 1;\n string memory buffer = new string(length);\n uint256 ptr;\n /// @solidity memory-safe-assembly\n assembly {\n ptr := add(buffer, add(32, length))\n }\n while (true) {\n ptr--;\n /// @solidity memory-safe-assembly\n assembly {\n mstore8(ptr, byte(mod(value, 10), _SYMBOLS))\n }\n value /= 10;\n if (value == 0) break;\n }\n return buffer;\n }\n }\n\n /**\n * @dev Converts a `int256` to its ASCII `string` decimal representation.\n */\n function toString(int256 value) internal pure returns (string memory) {\n return string(abi.encodePacked(value \u003c 0 ? \"-\" : \"\", toString(SignedMath.abs(value))));\n }\n\n /**\n * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation.\n */\n function toHexString(uint256 value) internal pure returns (string memory) {\n unchecked {\n return toHexString(value, Math.log256(value) + 1);\n }\n }\n\n /**\n * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length.\n */\n function toHexString(uint256 value, uint256 length) internal pure returns (string memory) {\n bytes memory buffer = new bytes(2 * length + 2);\n buffer[0] = \"0\";\n buffer[1] = \"x\";\n for (uint256 i = 2 * length + 1; i \u003e 1; --i) {\n buffer[i] = _SYMBOLS[value \u0026 0xf];\n value \u003e\u003e= 4;\n }\n require(value == 0, \"Strings: hex length insufficient\");\n return string(buffer);\n }\n\n /**\n * @dev Converts an `address` with fixed length of 20 bytes to its not checksummed ASCII `string` hexadecimal representation.\n */\n function toHexString(address addr) internal pure returns (string memory) {\n return toHexString(uint256(uint160(addr)), _ADDRESS_LENGTH);\n }\n\n /**\n * @dev Returns true if the two strings are equal.\n */\n function equal(string memory a, string memory b) internal pure returns (bool) {\n return keccak256(bytes(a)) == keccak256(bytes(b));\n }\n}\n\n// node_modules/@openzeppelin/contracts-upgradeable/utils/ContextUpgradeable.sol\n\n// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)\n\n/**\n * @dev Provides information about the current execution context, including the\n * sender of the transaction and its data. While these are generally available\n * via msg.sender and msg.data, they should not be accessed in such a direct\n * manner, since when dealing with meta-transactions the account sending and\n * paying for execution may not be the actual sender (as far as an application\n * is concerned).\n *\n * This contract is only required for intermediate, library-like contracts.\n */\nabstract contract ContextUpgradeable is Initializable {\n function __Context_init() internal onlyInitializing {\n }\n\n function __Context_init_unchained() internal onlyInitializing {\n }\n function _msgSender() internal view virtual returns (address) {\n return msg.sender;\n }\n\n function _msgData() internal view virtual returns (bytes calldata) {\n return msg.data;\n }\n\n /**\n * @dev This empty reserved space is put in place to allow future versions to add new\n * variables without shifting down storage in the inheritance chain.\n * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\n */\n uint256[50] private __gap;\n}\n\n// contracts/libs/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/utils/cryptography/ECDSA.sol\n\n// OpenZeppelin Contracts (last updated v4.9.0) (utils/cryptography/ECDSA.sol)\n\n/**\n * @dev Elliptic Curve Digital Signature Algorithm (ECDSA) operations.\n *\n * These functions can be used to verify that a message was signed by the holder\n * of the private keys of a given address.\n */\nlibrary ECDSA {\n enum RecoverError {\n NoError,\n InvalidSignature,\n InvalidSignatureLength,\n InvalidSignatureS,\n InvalidSignatureV // Deprecated in v4.8\n }\n\n function _throwError(RecoverError error) private pure {\n if (error == RecoverError.NoError) {\n return; // no error: do nothing\n } else if (error == RecoverError.InvalidSignature) {\n revert(\"ECDSA: invalid signature\");\n } else if (error == RecoverError.InvalidSignatureLength) {\n revert(\"ECDSA: invalid signature length\");\n } else if (error == RecoverError.InvalidSignatureS) {\n revert(\"ECDSA: invalid signature 's' value\");\n }\n }\n\n /**\n * @dev Returns the address that signed a hashed message (`hash`) with\n * `signature` or error string. This address can then be used for verification purposes.\n *\n * The `ecrecover` EVM opcode allows for malleable (non-unique) signatures:\n * this function rejects them by requiring the `s` value to be in the lower\n * half order, and the `v` value to be either 27 or 28.\n *\n * IMPORTANT: `hash` _must_ be the result of a hash operation for the\n * verification to be secure: it is possible to craft signatures that\n * recover to arbitrary addresses for non-hashed data. A safe way to ensure\n * this is by receiving a hash of the original message (which may otherwise\n * be too long), and then calling {toEthSignedMessageHash} on it.\n *\n * Documentation for signature generation:\n * - with https://web3js.readthedocs.io/en/v1.3.4/web3-eth-accounts.html#sign[Web3.js]\n * - with https://docs.ethers.io/v5/api/signer/#Signer-signMessage[ethers]\n *\n * _Available since v4.3._\n */\n function tryRecover(bytes32 hash, bytes memory signature) internal pure returns (address, RecoverError) {\n if (signature.length == 65) {\n bytes32 r;\n bytes32 s;\n uint8 v;\n // ecrecover takes the signature parameters, and the only way to get them\n // currently is to use assembly.\n /// @solidity memory-safe-assembly\n assembly {\n r := mload(add(signature, 0x20))\n s := mload(add(signature, 0x40))\n v := byte(0, mload(add(signature, 0x60)))\n }\n return tryRecover(hash, v, r, s);\n } else {\n return (address(0), RecoverError.InvalidSignatureLength);\n }\n }\n\n /**\n * @dev Returns the address that signed a hashed message (`hash`) with\n * `signature`. This address can then be used for verification purposes.\n *\n * The `ecrecover` EVM opcode allows for malleable (non-unique) signatures:\n * this function rejects them by requiring the `s` value to be in the lower\n * half order, and the `v` value to be either 27 or 28.\n *\n * IMPORTANT: `hash` _must_ be the result of a hash operation for the\n * verification to be secure: it is possible to craft signatures that\n * recover to arbitrary addresses for non-hashed data. A safe way to ensure\n * this is by receiving a hash of the original message (which may otherwise\n * be too long), and then calling {toEthSignedMessageHash} on it.\n */\n function recover(bytes32 hash, bytes memory signature) internal pure returns (address) {\n (address recovered, RecoverError error) = tryRecover(hash, signature);\n _throwError(error);\n return recovered;\n }\n\n /**\n * @dev Overload of {ECDSA-tryRecover} that receives the `r` and `vs` short-signature fields separately.\n *\n * See https://eips.ethereum.org/EIPS/eip-2098[EIP-2098 short signatures]\n *\n * _Available since v4.3._\n */\n function tryRecover(bytes32 hash, bytes32 r, bytes32 vs) internal pure returns (address, RecoverError) {\n bytes32 s = vs \u0026 bytes32(0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff);\n uint8 v = uint8((uint256(vs) \u003e\u003e 255) + 27);\n return tryRecover(hash, v, r, s);\n }\n\n /**\n * @dev Overload of {ECDSA-recover} that receives the `r and `vs` short-signature fields separately.\n *\n * _Available since v4.2._\n */\n function recover(bytes32 hash, bytes32 r, bytes32 vs) internal pure returns (address) {\n (address recovered, RecoverError error) = tryRecover(hash, r, vs);\n _throwError(error);\n return recovered;\n }\n\n /**\n * @dev Overload of {ECDSA-tryRecover} that receives the `v`,\n * `r` and `s` signature fields separately.\n *\n * _Available since v4.3._\n */\n function tryRecover(bytes32 hash, uint8 v, bytes32 r, bytes32 s) internal pure returns (address, RecoverError) {\n // EIP-2 still allows signature malleability for ecrecover(). Remove this possibility and make the signature\n // unique. Appendix F in the Ethereum Yellow paper (https://ethereum.github.io/yellowpaper/paper.pdf), defines\n // the valid range for s in (301): 0 \u003c s \u003c secp256k1n ÷ 2 + 1, and for v in (302): v ∈ {27, 28}. Most\n // signatures from current libraries generate a unique signature with an s-value in the lower half order.\n //\n // If your library generates malleable signatures, such as s-values in the upper range, calculate a new s-value\n // with 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141 - s1 and flip v from 27 to 28 or\n // vice versa. If your library also generates signatures with 0/1 for v instead 27/28, add 27 to v to accept\n // these malleable signatures as well.\n if (uint256(s) \u003e 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0) {\n return (address(0), RecoverError.InvalidSignatureS);\n }\n\n // If the signature is valid (and not malleable), return the signer address\n address signer = ecrecover(hash, v, r, s);\n if (signer == address(0)) {\n return (address(0), RecoverError.InvalidSignature);\n }\n\n return (signer, RecoverError.NoError);\n }\n\n /**\n * @dev Overload of {ECDSA-recover} that receives the `v`,\n * `r` and `s` signature fields separately.\n */\n function recover(bytes32 hash, uint8 v, bytes32 r, bytes32 s) internal pure returns (address) {\n (address recovered, RecoverError error) = tryRecover(hash, v, r, s);\n _throwError(error);\n return recovered;\n }\n\n /**\n * @dev Returns an Ethereum Signed Message, created from a `hash`. This\n * produces hash corresponding to the one signed with the\n * https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`]\n * JSON-RPC method as part of EIP-191.\n *\n * See {recover}.\n */\n function toEthSignedMessageHash(bytes32 hash) internal pure returns (bytes32 message) {\n // 32 is the length in bytes of hash,\n // enforced by the type signature above\n /// @solidity memory-safe-assembly\n assembly {\n mstore(0x00, \"\\x19Ethereum Signed Message:\\n32\")\n mstore(0x1c, hash)\n message := keccak256(0x00, 0x3c)\n }\n }\n\n /**\n * @dev Returns an Ethereum Signed Message, created from `s`. This\n * produces hash corresponding to the one signed with the\n * https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`]\n * JSON-RPC method as part of EIP-191.\n *\n * See {recover}.\n */\n function toEthSignedMessageHash(bytes memory s) internal pure returns (bytes32) {\n return keccak256(abi.encodePacked(\"\\x19Ethereum Signed Message:\\n\", Strings.toString(s.length), s));\n }\n\n /**\n * @dev Returns an Ethereum Signed Typed Data, created from a\n * `domainSeparator` and a `structHash`. This produces hash corresponding\n * to the one signed with the\n * https://eips.ethereum.org/EIPS/eip-712[`eth_signTypedData`]\n * JSON-RPC method as part of EIP-712.\n *\n * See {recover}.\n */\n function toTypedDataHash(bytes32 domainSeparator, bytes32 structHash) internal pure returns (bytes32 data) {\n /// @solidity memory-safe-assembly\n assembly {\n let ptr := mload(0x40)\n mstore(ptr, \"\\x19\\x01\")\n mstore(add(ptr, 0x02), domainSeparator)\n mstore(add(ptr, 0x22), structHash)\n data := keccak256(ptr, 0x42)\n }\n }\n\n /**\n * @dev Returns an Ethereum Signed Data with intended validator, created from a\n * `validator` and `data` according to the version 0 of EIP-191.\n *\n * See {recover}.\n */\n function toDataWithIntendedValidatorHash(address validator, bytes memory data) internal pure returns (bytes32) {\n return keccak256(abi.encodePacked(\"\\x19\\x00\", validator, data));\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/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/inbox/StatementInbox.sol\n\n// ══════════════════════════════ LIBRARY IMPORTS ══════════════════════════════\n\n// ═════════════════════════════ INTERNAL IMPORTS ══════════════════════════════\n\n// ═════════════════════════════ EXTERNAL IMPORTS ══════════════════════════════\n\n/// @notice `StatementInbox` is the entry point for all agent-signed statements. It verifies the\n/// agent signatures, and passes the unsigned statements to the contract to consume it via `acceptX` functions. Is is\n/// also used to verify the agent-signed statements and initiate the agent slashing, should the statement be invalid.\n/// `StatementInbox` is responsible for the following:\n/// - Accepting State and Receipt Reports to initiate a dispute between Guard and Notary.\n/// - Storing all the Guard Reports with the Guard signature leading to a dispute.\n/// - Verifying State/State Reports referencing the local chain and slashing the signer if statement is invalid.\n/// - Verifying Receipt/Receipt Reports referencing the local chain and slashing the signer if statement is invalid.\nabstract contract StatementInbox is MessagingBase, StatementInboxEvents, IStatementInbox {\n using AttestationLib for bytes;\n using ReceiptLib for bytes;\n using StateLib for bytes;\n using SnapshotLib for bytes;\n\n struct StoredReport {\n uint256 sigIndex;\n bytes statementPayload;\n }\n\n // ══════════════════════════════════════════════════ STORAGE ══════════════════════════════════════════════════════\n\n address public agentManager;\n address public origin;\n address public destination;\n\n // TODO: optimize this\n bytes[] internal _storedSignatures;\n StoredReport[] internal _storedReports;\n\n /// @dev gap for upgrade safety\n uint256[45] private __GAP; // solhint-disable-line var-name-mixedcase\n\n // ════════════════════════════════════════════════ INITIALIZER ════════════════════════════════════════════════════\n\n /// @dev Initializes the contract:\n /// - Sets up `msg.sender` as the owner of the contract.\n /// - Sets up `agentManager`, `origin`, and `destination`.\n // solhint-disable-next-line func-name-mixedcase\n function __StatementInbox_init(address agentManager_, address origin_, address destination_)\n internal\n onlyInitializing\n {\n agentManager = agentManager_;\n origin = origin_;\n destination = destination_;\n __Ownable2Step_init();\n }\n\n // ══════════════════════════════════════════ SUBMIT AGENT STATEMENTS ══════════════════════════════════════════════\n\n /// @inheritdoc IStatementInbox\n // solhint-disable-next-line ordering\n function submitStateReportWithSnapshot(\n uint8 stateIndex,\n bytes memory srSignature,\n bytes memory snapPayload,\n bytes memory snapSignature\n ) external returns (bool wasAccepted) {\n // This will revert if payload is not a snapshot\n Snapshot snapshot = snapPayload.castToSnapshot();\n // This will revert if the snapshot signer is not a known Notary\n (AgentStatus memory notaryStatus,) =\n _verifySnapshot({snapshot: snapshot, snapSignature: snapSignature, verifyNotary: true});\n // Notary needs to be Active/Unstaking\n notaryStatus.verifyActiveUnstaking();\n // Check if Notary is active on this chain\n _verifyNotaryDomain(notaryStatus.domain);\n // This will revert if state index is out of range\n State state = snapshot.state(stateIndex);\n // This will revert if the report signer is not an known Guard\n (AgentStatus memory guardStatus,) = _verifyStateReport(state, srSignature);\n // Check that Guard is active\n guardStatus.verifyActive();\n _saveReport(state.unwrap().clone(), srSignature);\n // This will revert if either actor is already in dispute\n IAgentManager(agentManager).openDispute(guardStatus.index, notaryStatus.index);\n return true;\n }\n\n /// @inheritdoc IStatementInbox\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 // This will revert if payload is not a snapshot\n Snapshot snapshot = snapPayload.castToSnapshot();\n // This will revert if state index is out of range\n State state = snapshot.state(stateIndex);\n // This will revert if the report signer is not an known Guard\n (AgentStatus memory guardStatus,) = _verifyStateReport(state, srSignature);\n // Check that Guard is active\n guardStatus.verifyActive();\n // This will revert if payload is not an attestation\n Attestation att = attPayload.castToAttestation();\n // This will revert if signer is not an known Notary\n (AgentStatus memory notaryStatus,) = _verifyAttestation(att, attSignature);\n // Notary needs to be Active/Unstaking\n notaryStatus.verifyActiveUnstaking();\n // Check if Notary is active on this chain\n _verifyNotaryDomain(notaryStatus.domain);\n if (snapshot.calculateRoot() != att.snapRoot()) revert IncorrectSnapshotRoot();\n _saveReport(state.unwrap().clone(), srSignature);\n // This will revert if either actor is already in dispute\n IAgentManager(agentManager).openDispute(guardStatus.index, notaryStatus.index);\n return true;\n }\n\n /// @inheritdoc IStatementInbox\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 // This will revert if payload is not a state\n State state = statePayload.castToState();\n // This will revert if the report signer is not an known Guard\n (AgentStatus memory guardStatus,) = _verifyStateReport(state, srSignature);\n // Check that Guard is active\n guardStatus.verifyActive();\n // This will revert if payload is not an attestation\n Attestation att = attPayload.castToAttestation();\n // This will revert if signer is not a known Notary\n (AgentStatus memory notaryStatus,) = _verifyAttestation(att, attSignature);\n // Notary needs to be Active/Unstaking\n notaryStatus.verifyActiveUnstaking();\n // Check if Notary is active on this chain\n _verifyNotaryDomain(notaryStatus.domain);\n // This will revert if any of these is true:\n // - Attestation root is not equal to Merkle Root derived from State and Snapshot Proof.\n // - Snapshot Proof's first element does not match the State metadata.\n // - Snapshot Proof length exceeds Snapshot tree Height.\n // - State index is out of range.\n _verifySnapshotMerkle(att, stateIndex, state, snapProof);\n _saveReport(statePayload, srSignature);\n // This will revert if either actor is already in dispute\n IAgentManager(agentManager).openDispute(guardStatus.index, notaryStatus.index);\n return true;\n }\n\n // ══════════════════════════════════════════ VERIFY AGENT STATEMENTS ══════════════════════════════════════════════\n\n /// @inheritdoc IStatementInbox\n function verifyReceipt(bytes memory rcptPayload, bytes memory rcptSignature)\n external\n returns (bool isValidReceipt)\n {\n // This will revert if payload is not a receipt\n Receipt rcpt = rcptPayload.castToReceipt();\n // This will revert if the attestation signer is not a known Notary\n (AgentStatus memory status, address notary) = _verifyReceipt(rcpt, rcptSignature);\n // Notary needs to be Active/Unstaking\n status.verifyActiveUnstaking();\n isValidReceipt = IExecutionHub(destination).isValidReceipt(rcptPayload);\n if (!isValidReceipt) {\n emit InvalidReceipt(rcptPayload, rcptSignature);\n IAgentManager(agentManager).slashAgent(status.domain, notary, msg.sender);\n }\n }\n\n /// @inheritdoc IStatementInbox\n function verifyReceiptReport(bytes memory rcptPayload, bytes memory rrSignature)\n external\n returns (bool isValidReport)\n {\n // This will revert if payload is not a receipt\n Receipt rcpt = rcptPayload.castToReceipt();\n // This will revert if the report signer is not a known Guard\n (AgentStatus memory status, address guard) = _verifyReceiptReport(rcpt, rrSignature);\n // Guard needs to be Active/Unstaking\n status.verifyActiveUnstaking();\n // Report is valid IF AND ONLY IF the reported receipt in invalid\n isValidReport = !IExecutionHub(destination).isValidReceipt(rcptPayload);\n if (!isValidReport) {\n emit InvalidReceiptReport(rcptPayload, rrSignature);\n IAgentManager(agentManager).slashAgent(status.domain, guard, msg.sender);\n }\n }\n\n /// @inheritdoc IStatementInbox\n function verifyStateWithAttestation(\n uint8 stateIndex,\n bytes memory snapPayload,\n bytes memory attPayload,\n bytes memory attSignature\n ) external returns (bool isValidState) {\n // This will revert if payload is not an attestation\n Attestation att = attPayload.castToAttestation();\n // This will revert if the attestation signer is not a known Notary\n (AgentStatus memory status, address notary) = _verifyAttestation(att, attSignature);\n // Notary needs to be Active/Unstaking\n status.verifyActiveUnstaking();\n // This will revert if payload is not a snapshot\n Snapshot snapshot = snapPayload.castToSnapshot();\n if (snapshot.calculateRoot() != att.snapRoot()) revert IncorrectSnapshotRoot();\n // This will revert if state does not refer to this chain\n bytes memory statePayload = snapshot.state(stateIndex).unwrap().clone();\n isValidState = IStateHub(origin).isValidState(statePayload);\n if (!isValidState) {\n emit InvalidStateWithAttestation(stateIndex, statePayload, attPayload, attSignature);\n IAgentManager(agentManager).slashAgent(status.domain, notary, msg.sender);\n }\n }\n\n /// @inheritdoc IStatementInbox\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 // This will revert if payload is not an attestation\n Attestation att = attPayload.castToAttestation();\n // This will revert if the attestation signer is not a known Notary\n (AgentStatus memory status, address notary) = _verifyAttestation(att, attSignature);\n // Notary needs to be Active/Unstaking\n status.verifyActiveUnstaking();\n // This will revert if payload is not a state\n State state = statePayload.castToState();\n // This will revert if any of these is true:\n // - Attestation root is not equal to Merkle Root derived from State and Snapshot Proof.\n // - Snapshot Proof's first element does not match the State metadata.\n // - Snapshot Proof length exceeds Snapshot tree Height.\n // - State index is out of range.\n _verifySnapshotMerkle(att, stateIndex, state, snapProof);\n // This will revert if state does not refer to this chain\n isValidState = IStateHub(origin).isValidState(statePayload);\n if (!isValidState) {\n emit InvalidStateWithAttestation(stateIndex, statePayload, attPayload, attSignature);\n IAgentManager(agentManager).slashAgent(status.domain, notary, msg.sender);\n }\n }\n\n /// @inheritdoc IStatementInbox\n function verifyStateWithSnapshot(uint8 stateIndex, bytes memory snapPayload, bytes memory snapSignature)\n external\n returns (bool isValidState)\n {\n // This will revert if payload is not a snapshot\n Snapshot snapshot = snapPayload.castToSnapshot();\n // This will revert if the snapshot signer is not a known Guard/Notary\n (AgentStatus memory status, address agent) =\n _verifySnapshot({snapshot: snapshot, snapSignature: snapSignature, verifyNotary: false});\n // Agent needs to be Active/Unstaking\n status.verifyActiveUnstaking();\n // This will revert if state does not refer to this chain\n isValidState = IStateHub(origin).isValidState(snapshot.state(stateIndex).unwrap().clone());\n if (!isValidState) {\n emit InvalidStateWithSnapshot(stateIndex, snapPayload, snapSignature);\n IAgentManager(agentManager).slashAgent(status.domain, agent, msg.sender);\n }\n }\n\n /// @inheritdoc IStatementInbox\n function verifyStateReport(bytes memory statePayload, bytes memory srSignature)\n external\n returns (bool isValidReport)\n {\n // This will revert if payload is not a state\n State state = statePayload.castToState();\n // This will revert if the report signer is not a known Guard\n (AgentStatus memory status, address guard) = _verifyStateReport(state, srSignature);\n // Guard needs to be Active/Unstaking\n status.verifyActiveUnstaking();\n // Report is valid IF AND ONLY IF the reported state in invalid\n // This will revert if the reported state does not refer to this chain\n isValidReport = !IStateHub(origin).isValidState(statePayload);\n if (!isValidReport) {\n emit InvalidStateReport(statePayload, srSignature);\n IAgentManager(agentManager).slashAgent(status.domain, guard, msg.sender);\n }\n }\n\n // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════\n\n /// @inheritdoc IStatementInbox\n function getReportsAmount() external view returns (uint256) {\n return _storedReports.length;\n }\n\n /// @inheritdoc IStatementInbox\n function getGuardReport(uint256 index)\n external\n view\n returns (bytes memory statementPayload, bytes memory reportSignature)\n {\n if (index \u003e= _storedReports.length) revert IndexOutOfRange();\n StoredReport memory storedReport = _storedReports[index];\n statementPayload = storedReport.statementPayload;\n reportSignature = _storedSignatures[storedReport.sigIndex];\n }\n\n /// @inheritdoc IStatementInbox\n function getStoredSignature(uint256 index) external view returns (bytes memory) {\n return _storedSignatures[index];\n }\n\n // ══════════════════════════════════════════════ INTERNAL LOGIC ═══════════════════════════════════════════════════\n\n /// @dev Saves the statement reported by Guard as invalid and the Guard Report signature.\n function _saveReport(bytes memory statementPayload, bytes memory reportSignature) internal {\n uint256 sigIndex = _saveSignature(reportSignature);\n _storedReports.push(StoredReport(sigIndex, statementPayload));\n }\n\n /// @dev Saves the signature and returns its index.\n function _saveSignature(bytes memory signature) internal returns (uint256 sigIndex) {\n sigIndex = _storedSignatures.length;\n _storedSignatures.push(signature);\n }\n\n // ═══════════════════════════════════════════════ AGENT CHECKS ════════════════════════════════════════════════════\n\n /**\n * @dev Recovers a signer from a hashed message, and a EIP-191 signature for it.\n * Will revert, if the signer is not a known agent.\n * @dev Agent flag could be any of these: Active/Unstaking/Resting/Fraudulent/Slashed\n * Further checks need to be performed in a caller function.\n * @param hashedStatement Hash of the statement that was signed by an Agent\n * @param signature Agent signature for the hashed statement\n * @return status Struct representing agent status:\n * - flag Unknown/Active/Unstaking/Resting/Fraudulent/Slashed\n * - domain Domain where agent is/was active\n * - index Index of agent in the Agent Merkle Tree\n * @return agent Agent that signed the statement\n */\n function _recoverAgent(bytes32 hashedStatement, bytes memory signature)\n internal\n view\n returns (AgentStatus memory status, address agent)\n {\n bytes32 ethSignedMsg = ECDSA.toEthSignedMessageHash(hashedStatement);\n agent = ECDSA.recover(ethSignedMsg, signature);\n status = IAgentManager(agentManager).agentStatus(agent);\n // Discard signature of unknown agents.\n // Further flag checks are supposed to be performed in a caller function.\n status.verifyKnown();\n }\n\n /// @dev Verifies that Notary signature is active on local domain.\n function _verifyNotaryDomain(uint32 notaryDomain) internal view {\n // Notary needs to be from the local domain (if contract is not deployed on Synapse Chain).\n // Or Notary could be from any domain (if contract is deployed on Synapse Chain).\n if (notaryDomain != localDomain \u0026\u0026 localDomain != synapseDomain) revert IncorrectAgentDomain();\n }\n\n // ════════════════════════════════════════ ATTESTATION RELATED CHECKS ═════════════════════════════════════════════\n\n /**\n * @dev Internal function to verify the signed attestation payload.\n * Reverts if any of these is true:\n * - Attestation signer is not a known Notary.\n * @param att Typed memory view over attestation payload\n * @param attSignature Notary signature for the attestation\n * @return status Struct representing agent status, see {_recoverAgent}\n * @return notary Notary that signed the snapshot\n */\n function _verifyAttestation(Attestation att, bytes memory attSignature)\n internal\n view\n returns (AgentStatus memory status, address notary)\n {\n // This will revert if signer is not a known agent\n (status, notary) = _recoverAgent(att.hashValid(), attSignature);\n // Attestation signer needs to be a Notary, not a Guard\n if (status.domain == 0) revert AgentNotNotary();\n }\n\n /**\n * @dev Internal function to verify the signed attestation report payload.\n * Reverts if any of these is true:\n * - Report signer is not a known Guard.\n * @param att Typed memory view over attestation payload that Guard reports as invalid\n * @param arSignature Guard signature for the \"invalid attestation\" report\n * @return status Struct representing guard status, see {_recoverAgent}\n * @return guard Guard that signed the report\n */\n function _verifyAttestationReport(Attestation att, bytes memory arSignature)\n internal\n view\n returns (AgentStatus memory status, address guard)\n {\n // This will revert if signer is not a known agent\n (status, guard) = _recoverAgent(att.hashInvalid(), arSignature);\n // Report signer needs to be a Guard, not a Notary\n if (status.domain != 0) revert AgentNotGuard();\n }\n\n // ══════════════════════════════════════════ RECEIPT RELATED CHECKS ═══════════════════════════════════════════════\n\n /**\n * @dev Internal function to verify the signed receipt payload.\n * Reverts if any of these is true:\n * - Receipt signer is not a known Notary.\n * @param rcpt Typed memory view over receipt payload\n * @param rcptSignature Notary signature for the receipt\n * @return status Struct representing agent status, see {_recoverAgent}\n * @return notary Notary that signed the snapshot\n */\n function _verifyReceipt(Receipt rcpt, bytes memory rcptSignature)\n internal\n view\n returns (AgentStatus memory status, address notary)\n {\n // This will revert if signer is not a known agent\n (status, notary) = _recoverAgent(rcpt.hashValid(), rcptSignature);\n // Receipt signer needs to be a Notary, not a Guard\n if (status.domain == 0) revert AgentNotNotary();\n }\n\n /**\n * @dev Internal function to verify the signed receipt report payload.\n * Reverts if any of these is true:\n * - Report signer is not a known Guard.\n * @param rcpt Typed memory view over receipt payload that Guard reports as invalid\n * @param rrSignature Guard signature for the \"invalid receipt\" report\n * @return status Struct representing guard status, see {_recoverAgent}\n * @return guard Guard that signed the report\n */\n function _verifyReceiptReport(Receipt rcpt, bytes memory rrSignature)\n internal\n view\n returns (AgentStatus memory status, address guard)\n {\n // This will revert if signer is not a known agent\n (status, guard) = _recoverAgent(rcpt.hashInvalid(), rrSignature);\n // Report signer needs to be a Guard, not a Notary\n if (status.domain != 0) revert AgentNotGuard();\n }\n\n // ═══════════════════════════════════════ STATE/SNAPSHOT RELATED CHECKS ═══════════════════════════════════════════\n\n /**\n * @dev Internal function to verify the signed snapshot report payload.\n * Reverts if any of these is true:\n * - Report signer is not a known Guard.\n * @param state Typed memory view over state payload that Guard reports as invalid\n * @param srSignature Guard signature for the report\n * @return status Struct representing guard status, see {_recoverAgent}\n * @return guard Guard that signed the report\n */\n function _verifyStateReport(State state, bytes memory srSignature)\n internal\n view\n returns (AgentStatus memory status, address guard)\n {\n // This will revert if signer is not a known agent\n (status, guard) = _recoverAgent(state.hashInvalid(), srSignature);\n // Report signer needs to be a Guard, not a Notary\n if (status.domain != 0) revert AgentNotGuard();\n }\n\n /**\n * @dev Internal function to verify the signed snapshot payload.\n * Reverts if any of these is true:\n * - Snapshot signer is not a known Agent.\n * - Snapshot signer is not a Notary (if verifyNotary is true).\n * @param snapshot Typed memory view over snapshot payload\n * @param snapSignature Agent signature for the snapshot\n * @param verifyNotary If true, snapshot signer needs to be a Notary, not a Guard\n * @return status Struct representing agent status, see {_recoverAgent}\n * @return agent Agent that signed the snapshot\n */\n function _verifySnapshot(Snapshot snapshot, bytes memory snapSignature, bool verifyNotary)\n internal\n view\n returns (AgentStatus memory status, address agent)\n {\n // This will revert if signer is not a known agent\n (status, agent) = _recoverAgent(snapshot.hashValid(), snapSignature);\n // If requested, snapshot signer needs to be a Notary, not a Guard\n if (verifyNotary \u0026\u0026 status.domain == 0) revert AgentNotNotary();\n }\n\n // ═══════════════════════════════════════════ MERKLE RELATED CHECKS ═══════════════════════════════════════════════\n\n /**\n * @dev Internal function to verify that snapshot roots match.\n * Reverts if any of these is true:\n * - Attestation root is not equal to Merkle Root derived from State and Snapshot Proof.\n * - Snapshot Proof's first element does not match the State metadata.\n * - Snapshot Proof length exceeds Snapshot tree Height.\n * - State index is out of range.\n * @param att Typed memory view over Attestation\n * @param stateIndex Index of state in the snapshot\n * @param state Typed memory view over the provided state payload\n * @param snapProof Raw payload with snapshot data\n */\n function _verifySnapshotMerkle(Attestation att, uint8 stateIndex, State state, bytes32[] memory snapProof)\n internal\n pure\n {\n // Snapshot proof first element should match State metadata (aka \"right sub-leaf\")\n (, bytes32 rightSubLeaf) = state.subLeafs();\n if (snapProof[0] != rightSubLeaf) revert IncorrectSnapshotProof();\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(state.root(), state.origin(), snapProof, stateIndex);\n // Snapshot root should match the attestation root\n if (att.snapRoot() != snapshotRoot) revert IncorrectSnapshotRoot();\n }\n}\n\n// contracts/inbox/Inbox.sol\n\n// ══════════════════════════════ LIBRARY IMPORTS ══════════════════════════════\n\n// ═════════════════════════════ INTERNAL IMPORTS ══════════════════════════════\n\n/// @notice `Inbox` is the child of `StatementInbox` contract, that is used on Synapse Chain.\n/// In addition to the functionality of `StatementInbox`, it also:\n/// - Accepts Guard and Notary Snapshots and passes them to `Summit` contract.\n/// - Accepts Notary-signed Receipts and passes them to `Summit` contract.\n/// - Accepts Receipt Reports to initiate a dispute between Guard and Notary.\n/// - Verifies Attestations and Attestation Reports, and slashes the signer if they are invalid.\ncontract Inbox is StatementInbox, InboxEvents, InterfaceInbox {\n using AttestationLib for bytes;\n using ReceiptLib for bytes;\n using SnapshotLib for bytes;\n\n // Struct to get around stack too deep error. TODO: revisit this\n struct ReceiptInfo {\n AgentStatus rcptNotaryStatus;\n address notary;\n uint32 attNonce;\n AgentStatus attNotaryStatus;\n }\n\n // ══════════════════════════════════════════════════ STORAGE ══════════════════════════════════════════════════════\n\n // The address of the Summit contract.\n address public summit;\n\n // ═════════════════════════════════════════ CONSTRUCTOR \u0026 INITIALIZER ═════════════════════════════════════════════\n\n constructor(uint32 synapseDomain_) MessagingBase(\"0.0.3\", synapseDomain_) {\n if (localDomain != synapseDomain) revert MustBeSynapseDomain();\n }\n\n /// @notice Initializes `Inbox` contract:\n /// - Sets `msg.sender` as the owner of the contract\n /// - Sets `agentManager`, `origin`, `destination` and `summit` addresses\n function initialize(address agentManager_, address origin_, address destination_, address summit_)\n external\n initializer\n {\n __StatementInbox_init(agentManager_, origin_, destination_);\n summit = summit_;\n }\n\n // ══════════════════════════════════════════ SUBMIT AGENT STATEMENTS ══════════════════════════════════════════════\n\n /// @inheritdoc InterfaceInbox\n function submitSnapshot(bytes memory snapPayload, bytes memory snapSignature)\n external\n returns (bytes memory attPayload, bytes32 agentRoot_, uint256[] memory snapGas)\n {\n // This will revert if payload is not a snapshot\n Snapshot snapshot = snapPayload.castToSnapshot();\n // This will revert if the signer is not a known Guard/Notary\n (AgentStatus memory status, address agent) =\n _verifySnapshot({snapshot: snapshot, snapSignature: snapSignature, verifyNotary: false});\n // Check that Agent is active\n status.verifyActive();\n // Store Agent signature for the Snapshot\n uint256 sigIndex = _saveSignature(snapSignature);\n if (status.domain == 0) {\n // Guard that is in Dispute could still submit new snapshots, so we don't check that\n InterfaceSummit(summit).acceptGuardSnapshot({\n guardIndex: status.index,\n sigIndex: sigIndex,\n snapPayload: snapPayload\n });\n } else {\n // Get current agentRoot from AgentManager\n agentRoot_ = IAgentManager(agentManager).agentRoot();\n // This will revert if Notary is in Dispute\n attPayload = InterfaceSummit(summit).acceptNotarySnapshot({\n notaryIndex: status.index,\n sigIndex: sigIndex,\n agentRoot: agentRoot_,\n snapPayload: snapPayload\n });\n ChainGas[] memory snapGas_ = snapshot.snapGas();\n // Pass created attestation to Destination to enable executing messages coming to Synapse Chain\n InterfaceDestination(destination).acceptAttestation(\n status.index, type(uint256).max, attPayload, agentRoot_, snapGas_\n );\n // Use assembly to cast ChainGas[] to uint256[] without copying. Highest bits are left zeroed.\n // solhint-disable-next-line no-inline-assembly\n assembly {\n snapGas := snapGas_\n }\n }\n emit SnapshotAccepted(status.domain, agent, snapPayload, snapSignature);\n }\n\n /// @inheritdoc InterfaceInbox\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 // Struct to get around stack too deep error.\n ReceiptInfo memory info;\n // This will revert if payload is not a receipt\n Receipt rcpt = rcptPayload.castToReceipt();\n // This will revert if the receipt signer is not a known Notary\n (info.rcptNotaryStatus, info.notary) = _verifyReceipt(rcpt, rcptSignature);\n // Receipt Notary needs to be Active\n info.rcptNotaryStatus.verifyActive();\n info.attNonce = IExecutionHub(destination).getAttestationNonce(rcpt.snapshotRoot());\n if (info.attNonce == 0) revert IncorrectSnapshotRoot();\n // Attestation Notary domain needs to match the destination domain\n info.attNotaryStatus = IAgentManager(agentManager).agentStatus(rcpt.attNotary());\n if (info.attNotaryStatus.domain != rcpt.destination()) revert IncorrectAgentDomain();\n // Check that the correct tip values for the message were provided\n _verifyReceiptTips(rcpt.messageHash(), paddedTips, headerHash, bodyHash);\n // Store Notary signature for the Receipt\n uint256 sigIndex = _saveSignature(rcptSignature);\n // This will revert if Receipt Notary is in Dispute\n wasAccepted = InterfaceSummit(summit).acceptReceipt({\n rcptNotaryIndex: info.rcptNotaryStatus.index,\n attNotaryIndex: info.attNotaryStatus.index,\n sigIndex: sigIndex,\n attNonce: info.attNonce,\n paddedTips: paddedTips,\n rcptPayload: rcptPayload\n });\n if (wasAccepted) {\n emit ReceiptAccepted(info.rcptNotaryStatus.domain, info.notary, rcptPayload, rcptSignature);\n }\n }\n\n /// @inheritdoc InterfaceInbox\n function submitReceiptReport(bytes memory rcptPayload, bytes memory rcptSignature, bytes memory rrSignature)\n external\n returns (bool wasAccepted)\n {\n // This will revert if payload is not a receipt\n Receipt rcpt = rcptPayload.castToReceipt();\n // This will revert if the receipt signer is not a known Guard\n (AgentStatus memory guardStatus,) = _verifyReceiptReport(rcpt, rrSignature);\n // Guard needs to be Active\n guardStatus.verifyActive();\n // This will revert if report signer is not a known Notary\n (AgentStatus memory notaryStatus,) = _verifyReceipt(rcpt, rcptSignature);\n // Notary needs to be Active/Unstaking\n notaryStatus.verifyActiveUnstaking();\n _saveReport(rcptPayload, rrSignature);\n // This will revert if either actor is already in dispute\n IAgentManager(agentManager).openDispute(guardStatus.index, notaryStatus.index);\n return true;\n }\n\n /// @inheritdoc InterfaceInbox\n function passReceipt(uint32 attNotaryIndex, uint32 attNonce, uint256 paddedTips, bytes memory rcptPayload)\n external\n returns (bool wasAccepted)\n {\n // Only Destination can pass receipts\n if (msg.sender != destination) revert CallerNotDestination();\n return InterfaceSummit(summit).acceptReceipt({\n rcptNotaryIndex: attNotaryIndex,\n attNotaryIndex: attNotaryIndex,\n sigIndex: type(uint256).max,\n attNonce: attNonce,\n paddedTips: paddedTips,\n rcptPayload: rcptPayload\n });\n }\n\n // ══════════════════════════════════════════ VERIFY AGENT STATEMENTS ══════════════════════════════════════════════\n\n /// @inheritdoc InterfaceInbox\n function verifyAttestation(bytes memory attPayload, bytes memory attSignature)\n external\n returns (bool isValidAttestation)\n {\n // This will revert if payload is not an attestation\n Attestation att = attPayload.castToAttestation();\n // This will revert if the attestation signer is not a known Notary\n (AgentStatus memory status, address notary) = _verifyAttestation(att, attSignature);\n // Notary needs to be Active/Unstaking\n status.verifyActiveUnstaking();\n isValidAttestation = ISnapshotHub(summit).isValidAttestation(attPayload);\n if (!isValidAttestation) {\n emit InvalidAttestation(attPayload, attSignature);\n IAgentManager(agentManager).slashAgent(status.domain, notary, msg.sender);\n }\n }\n\n /// @inheritdoc InterfaceInbox\n function verifyAttestationReport(bytes memory attPayload, bytes memory arSignature)\n external\n returns (bool isValidReport)\n {\n // This will revert if payload is not an attestation\n Attestation att = attPayload.castToAttestation();\n // This will revert if the report signer is not a known Guard\n (AgentStatus memory status, address guard) = _verifyAttestationReport(att, arSignature);\n // Guard needs to be Active/Unstaking\n status.verifyActiveUnstaking();\n // Report is valid IF AND ONLY IF the reported attestation in invalid\n isValidReport = !ISnapshotHub(summit).isValidAttestation(attPayload);\n if (!isValidReport) {\n emit InvalidAttestationReport(attPayload, arSignature);\n IAgentManager(agentManager).slashAgent(status.domain, guard, msg.sender);\n }\n }\n\n // ══════════════════════════════════════════════ INTERNAL VIEWS ═══════════════════════════════════════════════════\n\n /// @dev Verifies that tips proof matches the message hash.\n function _verifyReceiptTips(bytes32 msgHash, uint256 paddedTips, bytes32 headerHash, bytes32 bodyHash)\n internal\n pure\n {\n Tips tips = TipsLib.wrapPadded(paddedTips);\n // full message leaf is (header, baseMessage), while base message leaf is (tips, remainingBody).\n if (MerkleMath.getParent(headerHash, MerkleMath.getParent(tips.leaf(), bodyHash)) != msgHash) {\n revert IncorrectTipsProof();\n }\n }\n}\n","language":"Solidity","languageVersion":"0.8.17","compilerVersion":"0.8.17","compilerOptions":"--combined-json bin,bin-runtime,srcmap,srcmap-runtime,abi,userdoc,devdoc,metadata,hashes --optimize --optimize-runs 10000 --allow-paths ., ./, ../","srcMap":"147918:7222:0:-:0;;;;;;;;;;;;;;;-1:-1:-1;;;147918:7222:0;;;;;;;;;;;;;;;;;","srcMapRuntime":"147918: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/Inbox.sol\":\"GasDataLib\"},\"evmVersion\":\"london\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\"},\"optimizer\":{\"enabled\":true,\"runs\":10000},\"remappings\":[]},\"sources\":{\"solidity/Inbox.sol\":{\"keccak256\":\"0x9b516081a036814c0169e20e484d4a5499066b7a6f48fada952b5e844a1ca3e5\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://32bde393b3f24ef4307d9626d4143f337b3c0bd34e17bb969fd5a15221d96987\",\"dweb:/ipfs/QmTkt2XZRtgsbSpmsVQUM3c4ebETQoDVYbmEV9yheBghnr\"]}},\"version\":1}"},"hashes":{}},"solidity/Inbox.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/InboxEvents.sol\n\nabstract contract InboxEvents {\n /**\n * @notice Emitted when a snapshot is accepted by the Summit contract.\n * @param domain Domain where the signed Agent is active (ZERO for Guards)\n * @param agent Agent who signed the snapshot\n * @param snapPayload Raw payload with snapshot data\n * @param snapSignature Agent signature for the snapshot\n */\n event SnapshotAccepted(uint32 indexed domain, address indexed agent, bytes snapPayload, bytes snapSignature);\n\n /**\n * @notice Emitted when a snapshot is accepted by the Summit contract.\n * @param domain Domain where the signed Notary is active\n * @param notary Notary who signed the attestation\n * @param rcptPayload Raw payload with receipt data\n * @param rcptSignature Notary signature for the receipt\n */\n event ReceiptAccepted(uint32 domain, address notary, bytes rcptPayload, bytes rcptSignature);\n\n /**\n * @notice Emitted when a proof of invalid attestation is submitted.\n * @param attPayload Raw payload with Attestation data\n * @param attSignature Notary signature for the attestation\n */\n event InvalidAttestation(bytes attPayload, bytes attSignature);\n\n /**\n * @notice Emitted when a proof of invalid attestation report is submitted.\n * @param arPayload Raw payload with report data\n * @param arSignature Guard signature for the report\n */\n event InvalidAttestationReport(bytes arPayload, bytes arSignature);\n}\n\n// contracts/events/StatementInboxEvents.sol\n\nabstract contract StatementInboxEvents {\n // ════════════════════════════════════════════ STATEMENT ACCEPTED ═════════════════════════════════════════════════\n\n /**\n * @notice Emitted when a snapshot is accepted by the Destination contract.\n * @param domain Domain where the signed Notary is active\n * @param notary Notary who signed the attestation\n * @param attPayload Raw payload with attestation data\n * @param attSignature Notary signature for the attestation\n */\n event AttestationAccepted(uint32 domain, address notary, bytes attPayload, bytes attSignature);\n\n // ═════════════════════════════════════════ INVALID STATEMENT PROVED ══════════════════════════════════════════════\n\n /**\n * @notice Emitted when a proof of invalid receipt statement is submitted.\n * @param rcptPayload Raw payload with the receipt statement\n * @param rcptSignature Notary signature for the receipt statement\n */\n event InvalidReceipt(bytes rcptPayload, bytes rcptSignature);\n\n /**\n * @notice Emitted when a proof of invalid receipt report is submitted.\n * @param rrPayload Raw payload with report data\n * @param rrSignature Guard signature for the report\n */\n event InvalidReceiptReport(bytes rrPayload, bytes rrSignature);\n\n /**\n * @notice Emitted when a proof of invalid state in the signed attestation is submitted.\n * @param stateIndex Index of invalid state in the snapshot\n * @param statePayload Raw payload with state data\n * @param attPayload Raw payload with Attestation data for snapshot\n * @param attSignature Notary signature for the attestation\n */\n event InvalidStateWithAttestation(uint8 stateIndex, bytes statePayload, bytes attPayload, bytes attSignature);\n\n /**\n * @notice Emitted when a proof of invalid state in the signed snapshot is submitted.\n * @param stateIndex Index of invalid state in the snapshot\n * @param snapPayload Raw payload with snapshot data\n * @param snapSignature Agent signature for the snapshot\n */\n event InvalidStateWithSnapshot(uint8 stateIndex, bytes snapPayload, bytes snapSignature);\n\n /**\n * @notice Emitted when a proof of invalid state report is submitted.\n * @param srPayload Raw payload with report data\n * @param srSignature Guard signature for the report\n */\n event InvalidStateReport(bytes srPayload, bytes srSignature);\n}\n\n// contracts/interfaces/ISnapshotHub.sol\n\ninterface ISnapshotHub {\n /**\n * @notice Check that a given attestation is valid: matches the historical attestation\n * derived from an accepted Notary snapshot.\n * @dev Will revert if any of these is true:\n * - Attestation payload is not properly formatted.\n * @param attPayload Raw payload with attestation data\n * @return isValid Whether the provided attestation is valid\n */\n function isValidAttestation(bytes memory attPayload) external view returns (bool isValid);\n\n /**\n * @notice Returns saved attestation with the given nonce.\n * @dev Reverts if attestation with given nonce hasn't been created yet.\n * @param attNonce Nonce for the attestation\n * @return attPayload Raw payload with formatted Attestation data\n * @return agentRoot Agent root hash used for the attestation\n * @return snapGas Snapshot gas data used for the attestation\n */\n function getAttestation(uint32 attNonce)\n external\n view\n returns (bytes memory attPayload, bytes32 agentRoot, uint256[] memory snapGas);\n\n /**\n * @notice Returns the state with the highest known nonce submitted by a given Agent.\n * @param origin Domain of origin chain\n * @param agent Agent address\n * @return statePayload Raw payload with agent's latest state for origin\n */\n function getLatestAgentState(uint32 origin, address agent) external view returns (bytes memory statePayload);\n\n /**\n * @notice Returns latest saved attestation for a Notary.\n * @param notary Notary address\n * @return attPayload Raw payload with formatted Attestation data\n * @return agentRoot Agent root hash used for the attestation\n * @return snapGas Snapshot gas data used for the attestation\n */\n function getLatestNotaryAttestation(address notary)\n external\n view\n returns (bytes memory attPayload, bytes32 agentRoot, uint256[] memory snapGas);\n\n /**\n * @notice Returns Guard snapshot from the list of all accepted Guard snapshots.\n * @dev Reverts if snapshot with given index hasn't been accepted yet.\n * @param index Snapshot index in the list of all Guard snapshots\n * @return snapPayload Raw payload with Guard snapshot\n * @return snapSignature Raw payload with Guard signature for snapshot\n */\n function getGuardSnapshot(uint256 index)\n external\n view\n returns (bytes memory snapPayload, bytes memory snapSignature);\n\n /**\n * @notice Returns Notary snapshot from the list of all accepted Guard snapshots.\n * @dev Reverts if snapshot with given index hasn't been accepted yet.\n * @param index Snapshot index in the list of all Notary snapshots\n * @return snapPayload Raw payload with Notary snapshot\n * @return snapSignature Raw payload with Notary signature for snapshot\n */\n function getNotarySnapshot(uint256 index)\n external\n view\n returns (bytes memory snapPayload, bytes memory snapSignature);\n\n /**\n * @notice Returns Notary snapshot that was used for creating a given attestation.\n * @dev Reverts if any of these is true:\n * - Attestation payload is not properly formatted.\n * - Attestation is invalid (doesn't have a matching Notary snapshot).\n * @param attPayload Raw payload with attestation data\n * @return snapPayload Raw payload with Notary snapshot\n * @return snapSignature Raw payload with Notary signature for snapshot\n */\n function getNotarySnapshot(bytes memory attPayload)\n external\n view\n returns (bytes memory snapPayload, bytes memory snapSignature);\n\n /**\n * @notice Returns proof of inclusion of (root, origin) fields of a given snapshot's state\n * into the Snapshot Merkle Tree for a given attestation.\n * @dev Reverts if any of these is true:\n * - Attestation with given nonce hasn't been created yet.\n * - State index is out of range of snapshot list.\n * @param attNonce Nonce for the attestation\n * @param stateIndex Index of state in the attestation's snapshot\n * @return snapProof The snapshot proof\n */\n function getSnapshotProof(uint32 attNonce, uint8 stateIndex) external view returns (bytes32[] memory snapProof);\n}\n\n// contracts/interfaces/IStateHub.sol\n\ninterface IStateHub {\n /**\n * @notice Check that a given state is valid: matches the historical state of Origin contract.\n * Note: any Agent including an invalid state in their snapshot will be slashed\n * upon providing the snapshot and agent signature for it to Origin contract.\n * @dev Will revert if any of these is true:\n * - State payload is not properly formatted.\n * @param statePayload Raw payload with state data\n * @return isValid Whether the provided state is valid\n */\n function isValidState(bytes memory statePayload) external view returns (bool isValid);\n\n /**\n * @notice Returns the amount of saved states so far.\n * @dev This includes the initial state of \"empty Origin Merkle Tree\".\n */\n function statesAmount() external view returns (uint256);\n\n /**\n * @notice Suggest the data (state after latest sent message) to sign for an Agent.\n * Note: signing the suggested state data will will never lead to slashing of the actor,\n * assuming they have confirmed that the block, which number is included in the data,\n * is not subject to reorganization (which is different for every observed chain).\n * @return statePayload Raw payload with the latest state data\n */\n function suggestLatestState() external view returns (bytes memory statePayload);\n\n /**\n * @notice Given the historical nonce, suggest the state data to sign for an Agent.\n * Note: signing the suggested state data will will never lead to slashing of the actor,\n * assuming they have confirmed that the block, which number is included in the data,\n * is not subject to reorganization (which is different for every observed chain).\n * @param nonce Historical nonce to form a state\n * @return statePayload Raw payload with historical state data\n */\n function suggestState(uint32 nonce) external view returns (bytes memory statePayload);\n}\n\n// contracts/interfaces/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/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// node_modules/@openzeppelin/contracts/utils/math/Math.sol\n\n// OpenZeppelin Contracts (last updated v4.9.0) (utils/math/Math.sol)\n\n/**\n * @dev Standard math utilities missing in the Solidity language.\n */\nlibrary Math {\n enum Rounding {\n Down, // Toward negative infinity\n Up, // Toward infinity\n Zero // Toward zero\n }\n\n /**\n * @dev Returns the largest of two numbers.\n */\n function max(uint256 a, uint256 b) internal pure returns (uint256) {\n return a \u003e b ? a : b;\n }\n\n /**\n * @dev Returns the smallest of two numbers.\n */\n function min(uint256 a, uint256 b) internal pure returns (uint256) {\n return a \u003c b ? a : b;\n }\n\n /**\n * @dev Returns the average of two numbers. The result is rounded towards\n * zero.\n */\n function average(uint256 a, uint256 b) internal pure returns (uint256) {\n // (a + b) / 2 can overflow.\n return (a \u0026 b) + (a ^ b) / 2;\n }\n\n /**\n * @dev Returns the ceiling of the division of two numbers.\n *\n * This differs from standard division with `/` in that it rounds up instead\n * of rounding down.\n */\n function ceilDiv(uint256 a, uint256 b) internal pure returns (uint256) {\n // (a + b - 1) / b can overflow on addition, so we distribute.\n return a == 0 ? 0 : (a - 1) / b + 1;\n }\n\n /**\n * @notice Calculates floor(x * y / denominator) with full precision. Throws if result overflows a uint256 or denominator == 0\n * @dev Original credit to Remco Bloemen under MIT license (https://xn--2-umb.com/21/muldiv)\n * with further edits by Uniswap Labs also under MIT license.\n */\n function mulDiv(uint256 x, uint256 y, uint256 denominator) internal pure returns (uint256 result) {\n unchecked {\n // 512-bit multiply [prod1 prod0] = x * y. Compute the product mod 2^256 and mod 2^256 - 1, then use\n // use the Chinese Remainder Theorem to reconstruct the 512 bit result. The result is stored in two 256\n // variables such that product = prod1 * 2^256 + prod0.\n uint256 prod0; // Least significant 256 bits of the product\n uint256 prod1; // Most significant 256 bits of the product\n assembly {\n let mm := mulmod(x, y, not(0))\n prod0 := mul(x, y)\n prod1 := sub(sub(mm, prod0), lt(mm, prod0))\n }\n\n // Handle non-overflow cases, 256 by 256 division.\n if (prod1 == 0) {\n // Solidity will revert if denominator == 0, unlike the div opcode on its own.\n // The surrounding unchecked block does not change this fact.\n // See https://docs.soliditylang.org/en/latest/control-structures.html#checked-or-unchecked-arithmetic.\n return prod0 / denominator;\n }\n\n // Make sure the result is less than 2^256. Also prevents denominator == 0.\n require(denominator \u003e prod1, \"Math: mulDiv overflow\");\n\n ///////////////////////////////////////////////\n // 512 by 256 division.\n ///////////////////////////////////////////////\n\n // Make division exact by subtracting the remainder from [prod1 prod0].\n uint256 remainder;\n assembly {\n // Compute remainder using mulmod.\n remainder := mulmod(x, y, denominator)\n\n // Subtract 256 bit number from 512 bit number.\n prod1 := sub(prod1, gt(remainder, prod0))\n prod0 := sub(prod0, remainder)\n }\n\n // Factor powers of two out of denominator and compute largest power of two divisor of denominator. Always \u003e= 1.\n // See https://cs.stackexchange.com/q/138556/92363.\n\n // Does not overflow because the denominator cannot be zero at this stage in the function.\n uint256 twos = denominator \u0026 (~denominator + 1);\n assembly {\n // Divide denominator by twos.\n denominator := div(denominator, twos)\n\n // Divide [prod1 prod0] by twos.\n prod0 := div(prod0, twos)\n\n // Flip twos such that it is 2^256 / twos. If twos is zero, then it becomes one.\n twos := add(div(sub(0, twos), twos), 1)\n }\n\n // Shift in bits from prod1 into prod0.\n prod0 |= prod1 * twos;\n\n // Invert denominator mod 2^256. Now that denominator is an odd number, it has an inverse modulo 2^256 such\n // that denominator * inv = 1 mod 2^256. Compute the inverse by starting with a seed that is correct for\n // four bits. That is, denominator * inv = 1 mod 2^4.\n uint256 inverse = (3 * denominator) ^ 2;\n\n // Use the Newton-Raphson iteration to improve the precision. Thanks to Hensel's lifting lemma, this also works\n // in modular arithmetic, doubling the correct bits in each step.\n inverse *= 2 - denominator * inverse; // inverse mod 2^8\n inverse *= 2 - denominator * inverse; // inverse mod 2^16\n inverse *= 2 - denominator * inverse; // inverse mod 2^32\n inverse *= 2 - denominator * inverse; // inverse mod 2^64\n inverse *= 2 - denominator * inverse; // inverse mod 2^128\n inverse *= 2 - denominator * inverse; // inverse mod 2^256\n\n // Because the division is now exact we can divide by multiplying with the modular inverse of denominator.\n // This will give us the correct result modulo 2^256. Since the preconditions guarantee that the outcome is\n // less than 2^256, this is the final result. We don't need to compute the high bits of the result and prod1\n // is no longer required.\n result = prod0 * inverse;\n return result;\n }\n }\n\n /**\n * @notice Calculates x * y / denominator with full precision, following the selected rounding direction.\n */\n function mulDiv(uint256 x, uint256 y, uint256 denominator, Rounding rounding) internal pure returns (uint256) {\n uint256 result = mulDiv(x, y, denominator);\n if (rounding == Rounding.Up \u0026\u0026 mulmod(x, y, denominator) \u003e 0) {\n result += 1;\n }\n return result;\n }\n\n /**\n * @dev Returns the square root of a number. If the number is not a perfect square, the value is rounded down.\n *\n * Inspired by Henry S. Warren, Jr.'s \"Hacker's Delight\" (Chapter 11).\n */\n function sqrt(uint256 a) internal pure returns (uint256) {\n if (a == 0) {\n return 0;\n }\n\n // For our first guess, we get the biggest power of 2 which is smaller than the square root of the target.\n //\n // We know that the \"msb\" (most significant bit) of our target number `a` is a power of 2 such that we have\n // `msb(a) \u003c= a \u003c 2*msb(a)`. This value can be written `msb(a)=2**k` with `k=log2(a)`.\n //\n // This can be rewritten `2**log2(a) \u003c= a \u003c 2**(log2(a) + 1)`\n // → `sqrt(2**k) \u003c= sqrt(a) \u003c sqrt(2**(k+1))`\n // → `2**(k/2) \u003c= sqrt(a) \u003c 2**((k+1)/2) \u003c= 2**(k/2 + 1)`\n //\n // Consequently, `2**(log2(a) / 2)` is a good first approximation of `sqrt(a)` with at least 1 correct bit.\n uint256 result = 1 \u003c\u003c (log2(a) \u003e\u003e 1);\n\n // At this point `result` is an estimation with one bit of precision. We know the true value is a uint128,\n // since it is the square root of a uint256. Newton's method converges quadratically (precision doubles at\n // every iteration). We thus need at most 7 iteration to turn our partial result with one bit of precision\n // into the expected uint128 result.\n unchecked {\n result = (result + a / result) \u003e\u003e 1;\n result = (result + a / result) \u003e\u003e 1;\n result = (result + a / result) \u003e\u003e 1;\n result = (result + a / result) \u003e\u003e 1;\n result = (result + a / result) \u003e\u003e 1;\n result = (result + a / result) \u003e\u003e 1;\n result = (result + a / result) \u003e\u003e 1;\n return min(result, a / result);\n }\n }\n\n /**\n * @notice Calculates sqrt(a), following the selected rounding direction.\n */\n function sqrt(uint256 a, Rounding rounding) internal pure returns (uint256) {\n unchecked {\n uint256 result = sqrt(a);\n return result + (rounding == Rounding.Up \u0026\u0026 result * result \u003c a ? 1 : 0);\n }\n }\n\n /**\n * @dev Return the log in base 2, rounded down, of a positive value.\n * Returns 0 if given 0.\n */\n function log2(uint256 value) internal pure returns (uint256) {\n uint256 result = 0;\n unchecked {\n if (value \u003e\u003e 128 \u003e 0) {\n value \u003e\u003e= 128;\n result += 128;\n }\n if (value \u003e\u003e 64 \u003e 0) {\n value \u003e\u003e= 64;\n result += 64;\n }\n if (value \u003e\u003e 32 \u003e 0) {\n value \u003e\u003e= 32;\n result += 32;\n }\n if (value \u003e\u003e 16 \u003e 0) {\n value \u003e\u003e= 16;\n result += 16;\n }\n if (value \u003e\u003e 8 \u003e 0) {\n value \u003e\u003e= 8;\n result += 8;\n }\n if (value \u003e\u003e 4 \u003e 0) {\n value \u003e\u003e= 4;\n result += 4;\n }\n if (value \u003e\u003e 2 \u003e 0) {\n value \u003e\u003e= 2;\n result += 2;\n }\n if (value \u003e\u003e 1 \u003e 0) {\n result += 1;\n }\n }\n return result;\n }\n\n /**\n * @dev Return the log in base 2, following the selected rounding direction, of a positive value.\n * Returns 0 if given 0.\n */\n function log2(uint256 value, Rounding rounding) internal pure returns (uint256) {\n unchecked {\n uint256 result = log2(value);\n return result + (rounding == Rounding.Up \u0026\u0026 1 \u003c\u003c result \u003c value ? 1 : 0);\n }\n }\n\n /**\n * @dev Return the log in base 10, rounded down, of a positive value.\n * Returns 0 if given 0.\n */\n function log10(uint256 value) internal pure returns (uint256) {\n uint256 result = 0;\n unchecked {\n if (value \u003e= 10 ** 64) {\n value /= 10 ** 64;\n result += 64;\n }\n if (value \u003e= 10 ** 32) {\n value /= 10 ** 32;\n result += 32;\n }\n if (value \u003e= 10 ** 16) {\n value /= 10 ** 16;\n result += 16;\n }\n if (value \u003e= 10 ** 8) {\n value /= 10 ** 8;\n result += 8;\n }\n if (value \u003e= 10 ** 4) {\n value /= 10 ** 4;\n result += 4;\n }\n if (value \u003e= 10 ** 2) {\n value /= 10 ** 2;\n result += 2;\n }\n if (value \u003e= 10 ** 1) {\n result += 1;\n }\n }\n return result;\n }\n\n /**\n * @dev Return the log in base 10, following the selected rounding direction, of a positive value.\n * Returns 0 if given 0.\n */\n function log10(uint256 value, Rounding rounding) internal pure returns (uint256) {\n unchecked {\n uint256 result = log10(value);\n return result + (rounding == Rounding.Up \u0026\u0026 10 ** result \u003c value ? 1 : 0);\n }\n }\n\n /**\n * @dev Return the log in base 256, rounded down, of a positive value.\n * Returns 0 if given 0.\n *\n * Adding one to the result gives the number of pairs of hex symbols needed to represent `value` as a hex string.\n */\n function log256(uint256 value) internal pure returns (uint256) {\n uint256 result = 0;\n unchecked {\n if (value \u003e\u003e 128 \u003e 0) {\n value \u003e\u003e= 128;\n result += 16;\n }\n if (value \u003e\u003e 64 \u003e 0) {\n value \u003e\u003e= 64;\n result += 8;\n }\n if (value \u003e\u003e 32 \u003e 0) {\n value \u003e\u003e= 32;\n result += 4;\n }\n if (value \u003e\u003e 16 \u003e 0) {\n value \u003e\u003e= 16;\n result += 2;\n }\n if (value \u003e\u003e 8 \u003e 0) {\n result += 1;\n }\n }\n return result;\n }\n\n /**\n * @dev Return the log in base 256, following the selected rounding direction, of a positive value.\n * Returns 0 if given 0.\n */\n function log256(uint256 value, Rounding rounding) internal pure returns (uint256) {\n unchecked {\n uint256 result = log256(value);\n return result + (rounding == Rounding.Up \u0026\u0026 1 \u003c\u003c (result \u003c\u003c 3) \u003c value ? 1 : 0);\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/utils/math/SignedMath.sol\n\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/math/SignedMath.sol)\n\n/**\n * @dev Standard signed math utilities missing in the Solidity language.\n */\nlibrary SignedMath {\n /**\n * @dev Returns the largest of two signed numbers.\n */\n function max(int256 a, int256 b) internal pure returns (int256) {\n return a \u003e b ? a : b;\n }\n\n /**\n * @dev Returns the smallest of two signed numbers.\n */\n function min(int256 a, int256 b) internal pure returns (int256) {\n return a \u003c b ? a : b;\n }\n\n /**\n * @dev Returns the average of two signed numbers without overflow.\n * The result is rounded towards zero.\n */\n function average(int256 a, int256 b) internal pure returns (int256) {\n // Formula from the book \"Hacker's Delight\"\n int256 x = (a \u0026 b) + ((a ^ b) \u003e\u003e 1);\n return x + (int256(uint256(x) \u003e\u003e 255) \u0026 (a ^ b));\n }\n\n /**\n * @dev Returns the absolute unsigned value of a signed value.\n */\n function abs(int256 n) internal pure returns (uint256) {\n unchecked {\n // must be unchecked in order to support `n = type(int256).min`\n return uint256(n \u003e= 0 ? n : -n);\n }\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// 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/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/InterfaceSummit.sol\n\ninterface InterfaceSummit {\n // ══════════════════════════════════════════ ACCEPT AGENT STATEMENTS ══════════════════════════════════════════════\n\n /**\n * @notice Accepts a receipt, which local `AgentManager` verified to have been signed by an active Notary.\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 * - Notary who signed the receipt is referenced as the \"Receipt Notary\".\n * - Notary who signed the attestation on destination chain is referenced as the \"Attestation Notary\".\n * \u003e Will revert if any of these is true:\n * \u003e - Called by anyone other than local `AgentManager`.\n * \u003e - Receipt body payload is not properly formatted.\n * \u003e - Receipt signer is in Dispute.\n * \u003e - Receipt's snapshot root is unknown.\n * @param rcptNotaryIndex Index of Receipt Notary in Agent Merkle Tree\n * @param attNotaryIndex Index of Attestation Notary in Agent Merkle Tree\n * @param sigIndex Index of stored Notary signature\n * @param attNonce Nonce of the attestation used for proving the executed message\n * @param paddedTips Padded encoded paid tips information\n * @param rcptPayload Raw payload with message execution receipt\n * @return wasAccepted Whether the receipt was accepted\n */\n function acceptReceipt(\n uint32 rcptNotaryIndex,\n uint32 attNotaryIndex,\n uint256 sigIndex,\n uint32 attNonce,\n uint256 paddedTips,\n bytes memory rcptPayload\n ) external returns (bool wasAccepted);\n\n /**\n * @notice Accepts a snapshot, which local `AgentManager` verified to have been signed by an active Guard.\n * \u003e Snapshot is a list of states for a set of Origin contracts residing on any of the chains.\n * All the states in the Guard-signed snapshot become available for Notary signing.\n * \u003e Will revert if any of these is true:\n * \u003e - Called by anyone other than local `AgentManager`.\n * \u003e - Snapshot payload is not properly formatted.\n * \u003e - Snapshot contains a state older then the Guard has previously submitted.\n * @param guardIndex Index of Guard in Agent Merkle Tree\n * @param sigIndex Index of stored Agent signature\n * @param snapPayload Raw payload with snapshot data\n */\n function acceptGuardSnapshot(uint32 guardIndex, uint256 sigIndex, bytes memory snapPayload) external;\n\n /**\n * @notice Accepts a snapshot, which local `AgentManager` verified to have been signed by an active Notary.\n * \u003e Snapshot is a list of states for a set of Origin contracts residing on any of the chains.\n * Snapshot Merkle Root is calculated and saved for valid snapshots, i.e.\n * snapshots which are only using states previously submitted by any of the Guards.\n * - Notary could use states singed by the same of different Guards 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 - Called by anyone other than local `AgentManager`.\n * \u003e - Snapshot payload is not properly formatted.\n * \u003e - Snapshot contains a state older then the Notary has previously submitted.\n * \u003e - Snapshot contains a state that no Guard has previously submitted.\n * @param notaryIndex Index of Notary in Agent Merkle Tree\n * @param sigIndex Index of stored Agent signature\n * @param agentRoot Current root of the Agent Merkle Tree\n * @param snapPayload Raw payload with snapshot data\n * @return attPayload Raw payload with data for attestation derived from Notary snapshot.\n */\n function acceptNotarySnapshot(uint32 notaryIndex, uint256 sigIndex, bytes32 agentRoot, bytes memory snapPayload)\n external\n returns (bytes memory attPayload);\n\n // ════════════════════════════════════════════════ TIPS LOGIC ═════════════════════════════════════════════════════\n\n /**\n * @notice Distributes tips using the first Receipt from the \"receipt quarantine queue\".\n * Possible scenarios:\n * - Receipt queue is empty =\u003e does nothing\n * - Receipt optimistic period is not over =\u003e does nothing\n * - Either of Notaries present in Receipt was slashed =\u003e receipt is deleted from the queue\n * - Either of Notaries present in Receipt in Dispute =\u003e receipt is moved to the end of queue\n * - None of the above =\u003e receipt tips are distributed\n * @dev Returned value makes it possible to do the following: `while (distributeTips()) {}`\n * @return queuePopped Whether the first element was popped from the queue\n */\n function distributeTips() external returns (bool queuePopped);\n\n /**\n * @notice Withdraws locked base message tips from requested domain Origin to the recipient.\n * This is done by a call to a local Origin contract, or by a manager message to the remote chain.\n * @dev This will revert, if the pending balance of origin tips (earned-claimed) is lower than requested.\n * @param origin Domain of chain to withdraw tips on\n * @param amount Amount of tips to withdraw\n */\n function withdrawTips(uint32 origin, uint256 amount) external;\n\n // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════\n\n /**\n * @notice Returns earned and claimed tips for the actor.\n * Note: Tips for address(0) belong to the Treasury.\n * @param actor Address of the actor\n * @param origin Domain where the tips were initially paid\n * @return earned Total amount of origin tips the actor has earned so far\n * @return claimed Total amount of origin tips the actor has claimed so far\n */\n function actorTips(address actor, uint32 origin) external view returns (uint128 earned, uint128 claimed);\n\n /**\n * @notice Returns the amount of receipts in the \"Receipt Quarantine Queue\".\n */\n function receiptQueueLength() external view returns (uint256);\n\n /**\n * @notice Returns the state with the highest known nonce\n * submitted by any of the currently active Guards.\n * @param origin Domain of origin chain\n * @return statePayload Raw payload with latest active Guard state for origin\n */\n function getLatestState(uint32 origin) external view returns (bytes memory statePayload);\n}\n\n// node_modules/@openzeppelin/contracts/utils/Strings.sol\n\n// OpenZeppelin Contracts (last updated v4.9.0) (utils/Strings.sol)\n\n/**\n * @dev String operations.\n */\nlibrary Strings {\n bytes16 private constant _SYMBOLS = \"0123456789abcdef\";\n uint8 private constant _ADDRESS_LENGTH = 20;\n\n /**\n * @dev Converts a `uint256` to its ASCII `string` decimal representation.\n */\n function toString(uint256 value) internal pure returns (string memory) {\n unchecked {\n uint256 length = Math.log10(value) + 1;\n string memory buffer = new string(length);\n uint256 ptr;\n /// @solidity memory-safe-assembly\n assembly {\n ptr := add(buffer, add(32, length))\n }\n while (true) {\n ptr--;\n /// @solidity memory-safe-assembly\n assembly {\n mstore8(ptr, byte(mod(value, 10), _SYMBOLS))\n }\n value /= 10;\n if (value == 0) break;\n }\n return buffer;\n }\n }\n\n /**\n * @dev Converts a `int256` to its ASCII `string` decimal representation.\n */\n function toString(int256 value) internal pure returns (string memory) {\n return string(abi.encodePacked(value \u003c 0 ? \"-\" : \"\", toString(SignedMath.abs(value))));\n }\n\n /**\n * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation.\n */\n function toHexString(uint256 value) internal pure returns (string memory) {\n unchecked {\n return toHexString(value, Math.log256(value) + 1);\n }\n }\n\n /**\n * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length.\n */\n function toHexString(uint256 value, uint256 length) internal pure returns (string memory) {\n bytes memory buffer = new bytes(2 * length + 2);\n buffer[0] = \"0\";\n buffer[1] = \"x\";\n for (uint256 i = 2 * length + 1; i \u003e 1; --i) {\n buffer[i] = _SYMBOLS[value \u0026 0xf];\n value \u003e\u003e= 4;\n }\n require(value == 0, \"Strings: hex length insufficient\");\n return string(buffer);\n }\n\n /**\n * @dev Converts an `address` with fixed length of 20 bytes to its not checksummed ASCII `string` hexadecimal representation.\n */\n function toHexString(address addr) internal pure returns (string memory) {\n return toHexString(uint256(uint160(addr)), _ADDRESS_LENGTH);\n }\n\n /**\n * @dev Returns true if the two strings are equal.\n */\n function equal(string memory a, string memory b) internal pure returns (bool) {\n return keccak256(bytes(a)) == keccak256(bytes(b));\n }\n}\n\n// node_modules/@openzeppelin/contracts-upgradeable/utils/ContextUpgradeable.sol\n\n// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)\n\n/**\n * @dev Provides information about the current execution context, including the\n * sender of the transaction and its data. While these are generally available\n * via msg.sender and msg.data, they should not be accessed in such a direct\n * manner, since when dealing with meta-transactions the account sending and\n * paying for execution may not be the actual sender (as far as an application\n * is concerned).\n *\n * This contract is only required for intermediate, library-like contracts.\n */\nabstract contract ContextUpgradeable is Initializable {\n function __Context_init() internal onlyInitializing {\n }\n\n function __Context_init_unchained() internal onlyInitializing {\n }\n function _msgSender() internal view virtual returns (address) {\n return msg.sender;\n }\n\n function _msgData() internal view virtual returns (bytes calldata) {\n return msg.data;\n }\n\n /**\n * @dev This empty reserved space is put in place to allow future versions to add new\n * variables without shifting down storage in the inheritance chain.\n * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\n */\n uint256[50] private __gap;\n}\n\n// contracts/libs/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/utils/cryptography/ECDSA.sol\n\n// OpenZeppelin Contracts (last updated v4.9.0) (utils/cryptography/ECDSA.sol)\n\n/**\n * @dev Elliptic Curve Digital Signature Algorithm (ECDSA) operations.\n *\n * These functions can be used to verify that a message was signed by the holder\n * of the private keys of a given address.\n */\nlibrary ECDSA {\n enum RecoverError {\n NoError,\n InvalidSignature,\n InvalidSignatureLength,\n InvalidSignatureS,\n InvalidSignatureV // Deprecated in v4.8\n }\n\n function _throwError(RecoverError error) private pure {\n if (error == RecoverError.NoError) {\n return; // no error: do nothing\n } else if (error == RecoverError.InvalidSignature) {\n revert(\"ECDSA: invalid signature\");\n } else if (error == RecoverError.InvalidSignatureLength) {\n revert(\"ECDSA: invalid signature length\");\n } else if (error == RecoverError.InvalidSignatureS) {\n revert(\"ECDSA: invalid signature 's' value\");\n }\n }\n\n /**\n * @dev Returns the address that signed a hashed message (`hash`) with\n * `signature` or error string. This address can then be used for verification purposes.\n *\n * The `ecrecover` EVM opcode allows for malleable (non-unique) signatures:\n * this function rejects them by requiring the `s` value to be in the lower\n * half order, and the `v` value to be either 27 or 28.\n *\n * IMPORTANT: `hash` _must_ be the result of a hash operation for the\n * verification to be secure: it is possible to craft signatures that\n * recover to arbitrary addresses for non-hashed data. A safe way to ensure\n * this is by receiving a hash of the original message (which may otherwise\n * be too long), and then calling {toEthSignedMessageHash} on it.\n *\n * Documentation for signature generation:\n * - with https://web3js.readthedocs.io/en/v1.3.4/web3-eth-accounts.html#sign[Web3.js]\n * - with https://docs.ethers.io/v5/api/signer/#Signer-signMessage[ethers]\n *\n * _Available since v4.3._\n */\n function tryRecover(bytes32 hash, bytes memory signature) internal pure returns (address, RecoverError) {\n if (signature.length == 65) {\n bytes32 r;\n bytes32 s;\n uint8 v;\n // ecrecover takes the signature parameters, and the only way to get them\n // currently is to use assembly.\n /// @solidity memory-safe-assembly\n assembly {\n r := mload(add(signature, 0x20))\n s := mload(add(signature, 0x40))\n v := byte(0, mload(add(signature, 0x60)))\n }\n return tryRecover(hash, v, r, s);\n } else {\n return (address(0), RecoverError.InvalidSignatureLength);\n }\n }\n\n /**\n * @dev Returns the address that signed a hashed message (`hash`) with\n * `signature`. This address can then be used for verification purposes.\n *\n * The `ecrecover` EVM opcode allows for malleable (non-unique) signatures:\n * this function rejects them by requiring the `s` value to be in the lower\n * half order, and the `v` value to be either 27 or 28.\n *\n * IMPORTANT: `hash` _must_ be the result of a hash operation for the\n * verification to be secure: it is possible to craft signatures that\n * recover to arbitrary addresses for non-hashed data. A safe way to ensure\n * this is by receiving a hash of the original message (which may otherwise\n * be too long), and then calling {toEthSignedMessageHash} on it.\n */\n function recover(bytes32 hash, bytes memory signature) internal pure returns (address) {\n (address recovered, RecoverError error) = tryRecover(hash, signature);\n _throwError(error);\n return recovered;\n }\n\n /**\n * @dev Overload of {ECDSA-tryRecover} that receives the `r` and `vs` short-signature fields separately.\n *\n * See https://eips.ethereum.org/EIPS/eip-2098[EIP-2098 short signatures]\n *\n * _Available since v4.3._\n */\n function tryRecover(bytes32 hash, bytes32 r, bytes32 vs) internal pure returns (address, RecoverError) {\n bytes32 s = vs \u0026 bytes32(0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff);\n uint8 v = uint8((uint256(vs) \u003e\u003e 255) + 27);\n return tryRecover(hash, v, r, s);\n }\n\n /**\n * @dev Overload of {ECDSA-recover} that receives the `r and `vs` short-signature fields separately.\n *\n * _Available since v4.2._\n */\n function recover(bytes32 hash, bytes32 r, bytes32 vs) internal pure returns (address) {\n (address recovered, RecoverError error) = tryRecover(hash, r, vs);\n _throwError(error);\n return recovered;\n }\n\n /**\n * @dev Overload of {ECDSA-tryRecover} that receives the `v`,\n * `r` and `s` signature fields separately.\n *\n * _Available since v4.3._\n */\n function tryRecover(bytes32 hash, uint8 v, bytes32 r, bytes32 s) internal pure returns (address, RecoverError) {\n // EIP-2 still allows signature malleability for ecrecover(). Remove this possibility and make the signature\n // unique. Appendix F in the Ethereum Yellow paper (https://ethereum.github.io/yellowpaper/paper.pdf), defines\n // the valid range for s in (301): 0 \u003c s \u003c secp256k1n ÷ 2 + 1, and for v in (302): v ∈ {27, 28}. Most\n // signatures from current libraries generate a unique signature with an s-value in the lower half order.\n //\n // If your library generates malleable signatures, such as s-values in the upper range, calculate a new s-value\n // with 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141 - s1 and flip v from 27 to 28 or\n // vice versa. If your library also generates signatures with 0/1 for v instead 27/28, add 27 to v to accept\n // these malleable signatures as well.\n if (uint256(s) \u003e 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0) {\n return (address(0), RecoverError.InvalidSignatureS);\n }\n\n // If the signature is valid (and not malleable), return the signer address\n address signer = ecrecover(hash, v, r, s);\n if (signer == address(0)) {\n return (address(0), RecoverError.InvalidSignature);\n }\n\n return (signer, RecoverError.NoError);\n }\n\n /**\n * @dev Overload of {ECDSA-recover} that receives the `v`,\n * `r` and `s` signature fields separately.\n */\n function recover(bytes32 hash, uint8 v, bytes32 r, bytes32 s) internal pure returns (address) {\n (address recovered, RecoverError error) = tryRecover(hash, v, r, s);\n _throwError(error);\n return recovered;\n }\n\n /**\n * @dev Returns an Ethereum Signed Message, created from a `hash`. This\n * produces hash corresponding to the one signed with the\n * https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`]\n * JSON-RPC method as part of EIP-191.\n *\n * See {recover}.\n */\n function toEthSignedMessageHash(bytes32 hash) internal pure returns (bytes32 message) {\n // 32 is the length in bytes of hash,\n // enforced by the type signature above\n /// @solidity memory-safe-assembly\n assembly {\n mstore(0x00, \"\\x19Ethereum Signed Message:\\n32\")\n mstore(0x1c, hash)\n message := keccak256(0x00, 0x3c)\n }\n }\n\n /**\n * @dev Returns an Ethereum Signed Message, created from `s`. This\n * produces hash corresponding to the one signed with the\n * https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`]\n * JSON-RPC method as part of EIP-191.\n *\n * See {recover}.\n */\n function toEthSignedMessageHash(bytes memory s) internal pure returns (bytes32) {\n return keccak256(abi.encodePacked(\"\\x19Ethereum Signed Message:\\n\", Strings.toString(s.length), s));\n }\n\n /**\n * @dev Returns an Ethereum Signed Typed Data, created from a\n * `domainSeparator` and a `structHash`. This produces hash corresponding\n * to the one signed with the\n * https://eips.ethereum.org/EIPS/eip-712[`eth_signTypedData`]\n * JSON-RPC method as part of EIP-712.\n *\n * See {recover}.\n */\n function toTypedDataHash(bytes32 domainSeparator, bytes32 structHash) internal pure returns (bytes32 data) {\n /// @solidity memory-safe-assembly\n assembly {\n let ptr := mload(0x40)\n mstore(ptr, \"\\x19\\x01\")\n mstore(add(ptr, 0x02), domainSeparator)\n mstore(add(ptr, 0x22), structHash)\n data := keccak256(ptr, 0x42)\n }\n }\n\n /**\n * @dev Returns an Ethereum Signed Data with intended validator, created from a\n * `validator` and `data` according to the version 0 of EIP-191.\n *\n * See {recover}.\n */\n function toDataWithIntendedValidatorHash(address validator, bytes memory data) internal pure returns (bytes32) {\n return keccak256(abi.encodePacked(\"\\x19\\x00\", validator, data));\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/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/inbox/StatementInbox.sol\n\n// ══════════════════════════════ LIBRARY IMPORTS ══════════════════════════════\n\n// ═════════════════════════════ INTERNAL IMPORTS ══════════════════════════════\n\n// ═════════════════════════════ EXTERNAL IMPORTS ══════════════════════════════\n\n/// @notice `StatementInbox` is the entry point for all agent-signed statements. It verifies the\n/// agent signatures, and passes the unsigned statements to the contract to consume it via `acceptX` functions. Is is\n/// also used to verify the agent-signed statements and initiate the agent slashing, should the statement be invalid.\n/// `StatementInbox` is responsible for the following:\n/// - Accepting State and Receipt Reports to initiate a dispute between Guard and Notary.\n/// - Storing all the Guard Reports with the Guard signature leading to a dispute.\n/// - Verifying State/State Reports referencing the local chain and slashing the signer if statement is invalid.\n/// - Verifying Receipt/Receipt Reports referencing the local chain and slashing the signer if statement is invalid.\nabstract contract StatementInbox is MessagingBase, StatementInboxEvents, IStatementInbox {\n using AttestationLib for bytes;\n using ReceiptLib for bytes;\n using StateLib for bytes;\n using SnapshotLib for bytes;\n\n struct StoredReport {\n uint256 sigIndex;\n bytes statementPayload;\n }\n\n // ══════════════════════════════════════════════════ STORAGE ══════════════════════════════════════════════════════\n\n address public agentManager;\n address public origin;\n address public destination;\n\n // TODO: optimize this\n bytes[] internal _storedSignatures;\n StoredReport[] internal _storedReports;\n\n /// @dev gap for upgrade safety\n uint256[45] private __GAP; // solhint-disable-line var-name-mixedcase\n\n // ════════════════════════════════════════════════ INITIALIZER ════════════════════════════════════════════════════\n\n /// @dev Initializes the contract:\n /// - Sets up `msg.sender` as the owner of the contract.\n /// - Sets up `agentManager`, `origin`, and `destination`.\n // solhint-disable-next-line func-name-mixedcase\n function __StatementInbox_init(address agentManager_, address origin_, address destination_)\n internal\n onlyInitializing\n {\n agentManager = agentManager_;\n origin = origin_;\n destination = destination_;\n __Ownable2Step_init();\n }\n\n // ══════════════════════════════════════════ SUBMIT AGENT STATEMENTS ══════════════════════════════════════════════\n\n /// @inheritdoc IStatementInbox\n // solhint-disable-next-line ordering\n function submitStateReportWithSnapshot(\n uint8 stateIndex,\n bytes memory srSignature,\n bytes memory snapPayload,\n bytes memory snapSignature\n ) external returns (bool wasAccepted) {\n // This will revert if payload is not a snapshot\n Snapshot snapshot = snapPayload.castToSnapshot();\n // This will revert if the snapshot signer is not a known Notary\n (AgentStatus memory notaryStatus,) =\n _verifySnapshot({snapshot: snapshot, snapSignature: snapSignature, verifyNotary: true});\n // Notary needs to be Active/Unstaking\n notaryStatus.verifyActiveUnstaking();\n // Check if Notary is active on this chain\n _verifyNotaryDomain(notaryStatus.domain);\n // This will revert if state index is out of range\n State state = snapshot.state(stateIndex);\n // This will revert if the report signer is not an known Guard\n (AgentStatus memory guardStatus,) = _verifyStateReport(state, srSignature);\n // Check that Guard is active\n guardStatus.verifyActive();\n _saveReport(state.unwrap().clone(), srSignature);\n // This will revert if either actor is already in dispute\n IAgentManager(agentManager).openDispute(guardStatus.index, notaryStatus.index);\n return true;\n }\n\n /// @inheritdoc IStatementInbox\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 // This will revert if payload is not a snapshot\n Snapshot snapshot = snapPayload.castToSnapshot();\n // This will revert if state index is out of range\n State state = snapshot.state(stateIndex);\n // This will revert if the report signer is not an known Guard\n (AgentStatus memory guardStatus,) = _verifyStateReport(state, srSignature);\n // Check that Guard is active\n guardStatus.verifyActive();\n // This will revert if payload is not an attestation\n Attestation att = attPayload.castToAttestation();\n // This will revert if signer is not an known Notary\n (AgentStatus memory notaryStatus,) = _verifyAttestation(att, attSignature);\n // Notary needs to be Active/Unstaking\n notaryStatus.verifyActiveUnstaking();\n // Check if Notary is active on this chain\n _verifyNotaryDomain(notaryStatus.domain);\n if (snapshot.calculateRoot() != att.snapRoot()) revert IncorrectSnapshotRoot();\n _saveReport(state.unwrap().clone(), srSignature);\n // This will revert if either actor is already in dispute\n IAgentManager(agentManager).openDispute(guardStatus.index, notaryStatus.index);\n return true;\n }\n\n /// @inheritdoc IStatementInbox\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 // This will revert if payload is not a state\n State state = statePayload.castToState();\n // This will revert if the report signer is not an known Guard\n (AgentStatus memory guardStatus,) = _verifyStateReport(state, srSignature);\n // Check that Guard is active\n guardStatus.verifyActive();\n // This will revert if payload is not an attestation\n Attestation att = attPayload.castToAttestation();\n // This will revert if signer is not a known Notary\n (AgentStatus memory notaryStatus,) = _verifyAttestation(att, attSignature);\n // Notary needs to be Active/Unstaking\n notaryStatus.verifyActiveUnstaking();\n // Check if Notary is active on this chain\n _verifyNotaryDomain(notaryStatus.domain);\n // This will revert if any of these is true:\n // - Attestation root is not equal to Merkle Root derived from State and Snapshot Proof.\n // - Snapshot Proof's first element does not match the State metadata.\n // - Snapshot Proof length exceeds Snapshot tree Height.\n // - State index is out of range.\n _verifySnapshotMerkle(att, stateIndex, state, snapProof);\n _saveReport(statePayload, srSignature);\n // This will revert if either actor is already in dispute\n IAgentManager(agentManager).openDispute(guardStatus.index, notaryStatus.index);\n return true;\n }\n\n // ══════════════════════════════════════════ VERIFY AGENT STATEMENTS ══════════════════════════════════════════════\n\n /// @inheritdoc IStatementInbox\n function verifyReceipt(bytes memory rcptPayload, bytes memory rcptSignature)\n external\n returns (bool isValidReceipt)\n {\n // This will revert if payload is not a receipt\n Receipt rcpt = rcptPayload.castToReceipt();\n // This will revert if the attestation signer is not a known Notary\n (AgentStatus memory status, address notary) = _verifyReceipt(rcpt, rcptSignature);\n // Notary needs to be Active/Unstaking\n status.verifyActiveUnstaking();\n isValidReceipt = IExecutionHub(destination).isValidReceipt(rcptPayload);\n if (!isValidReceipt) {\n emit InvalidReceipt(rcptPayload, rcptSignature);\n IAgentManager(agentManager).slashAgent(status.domain, notary, msg.sender);\n }\n }\n\n /// @inheritdoc IStatementInbox\n function verifyReceiptReport(bytes memory rcptPayload, bytes memory rrSignature)\n external\n returns (bool isValidReport)\n {\n // This will revert if payload is not a receipt\n Receipt rcpt = rcptPayload.castToReceipt();\n // This will revert if the report signer is not a known Guard\n (AgentStatus memory status, address guard) = _verifyReceiptReport(rcpt, rrSignature);\n // Guard needs to be Active/Unstaking\n status.verifyActiveUnstaking();\n // Report is valid IF AND ONLY IF the reported receipt in invalid\n isValidReport = !IExecutionHub(destination).isValidReceipt(rcptPayload);\n if (!isValidReport) {\n emit InvalidReceiptReport(rcptPayload, rrSignature);\n IAgentManager(agentManager).slashAgent(status.domain, guard, msg.sender);\n }\n }\n\n /// @inheritdoc IStatementInbox\n function verifyStateWithAttestation(\n uint8 stateIndex,\n bytes memory snapPayload,\n bytes memory attPayload,\n bytes memory attSignature\n ) external returns (bool isValidState) {\n // This will revert if payload is not an attestation\n Attestation att = attPayload.castToAttestation();\n // This will revert if the attestation signer is not a known Notary\n (AgentStatus memory status, address notary) = _verifyAttestation(att, attSignature);\n // Notary needs to be Active/Unstaking\n status.verifyActiveUnstaking();\n // This will revert if payload is not a snapshot\n Snapshot snapshot = snapPayload.castToSnapshot();\n if (snapshot.calculateRoot() != att.snapRoot()) revert IncorrectSnapshotRoot();\n // This will revert if state does not refer to this chain\n bytes memory statePayload = snapshot.state(stateIndex).unwrap().clone();\n isValidState = IStateHub(origin).isValidState(statePayload);\n if (!isValidState) {\n emit InvalidStateWithAttestation(stateIndex, statePayload, attPayload, attSignature);\n IAgentManager(agentManager).slashAgent(status.domain, notary, msg.sender);\n }\n }\n\n /// @inheritdoc IStatementInbox\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 // This will revert if payload is not an attestation\n Attestation att = attPayload.castToAttestation();\n // This will revert if the attestation signer is not a known Notary\n (AgentStatus memory status, address notary) = _verifyAttestation(att, attSignature);\n // Notary needs to be Active/Unstaking\n status.verifyActiveUnstaking();\n // This will revert if payload is not a state\n State state = statePayload.castToState();\n // This will revert if any of these is true:\n // - Attestation root is not equal to Merkle Root derived from State and Snapshot Proof.\n // - Snapshot Proof's first element does not match the State metadata.\n // - Snapshot Proof length exceeds Snapshot tree Height.\n // - State index is out of range.\n _verifySnapshotMerkle(att, stateIndex, state, snapProof);\n // This will revert if state does not refer to this chain\n isValidState = IStateHub(origin).isValidState(statePayload);\n if (!isValidState) {\n emit InvalidStateWithAttestation(stateIndex, statePayload, attPayload, attSignature);\n IAgentManager(agentManager).slashAgent(status.domain, notary, msg.sender);\n }\n }\n\n /// @inheritdoc IStatementInbox\n function verifyStateWithSnapshot(uint8 stateIndex, bytes memory snapPayload, bytes memory snapSignature)\n external\n returns (bool isValidState)\n {\n // This will revert if payload is not a snapshot\n Snapshot snapshot = snapPayload.castToSnapshot();\n // This will revert if the snapshot signer is not a known Guard/Notary\n (AgentStatus memory status, address agent) =\n _verifySnapshot({snapshot: snapshot, snapSignature: snapSignature, verifyNotary: false});\n // Agent needs to be Active/Unstaking\n status.verifyActiveUnstaking();\n // This will revert if state does not refer to this chain\n isValidState = IStateHub(origin).isValidState(snapshot.state(stateIndex).unwrap().clone());\n if (!isValidState) {\n emit InvalidStateWithSnapshot(stateIndex, snapPayload, snapSignature);\n IAgentManager(agentManager).slashAgent(status.domain, agent, msg.sender);\n }\n }\n\n /// @inheritdoc IStatementInbox\n function verifyStateReport(bytes memory statePayload, bytes memory srSignature)\n external\n returns (bool isValidReport)\n {\n // This will revert if payload is not a state\n State state = statePayload.castToState();\n // This will revert if the report signer is not a known Guard\n (AgentStatus memory status, address guard) = _verifyStateReport(state, srSignature);\n // Guard needs to be Active/Unstaking\n status.verifyActiveUnstaking();\n // Report is valid IF AND ONLY IF the reported state in invalid\n // This will revert if the reported state does not refer to this chain\n isValidReport = !IStateHub(origin).isValidState(statePayload);\n if (!isValidReport) {\n emit InvalidStateReport(statePayload, srSignature);\n IAgentManager(agentManager).slashAgent(status.domain, guard, msg.sender);\n }\n }\n\n // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════\n\n /// @inheritdoc IStatementInbox\n function getReportsAmount() external view returns (uint256) {\n return _storedReports.length;\n }\n\n /// @inheritdoc IStatementInbox\n function getGuardReport(uint256 index)\n external\n view\n returns (bytes memory statementPayload, bytes memory reportSignature)\n {\n if (index \u003e= _storedReports.length) revert IndexOutOfRange();\n StoredReport memory storedReport = _storedReports[index];\n statementPayload = storedReport.statementPayload;\n reportSignature = _storedSignatures[storedReport.sigIndex];\n }\n\n /// @inheritdoc IStatementInbox\n function getStoredSignature(uint256 index) external view returns (bytes memory) {\n return _storedSignatures[index];\n }\n\n // ══════════════════════════════════════════════ INTERNAL LOGIC ═══════════════════════════════════════════════════\n\n /// @dev Saves the statement reported by Guard as invalid and the Guard Report signature.\n function _saveReport(bytes memory statementPayload, bytes memory reportSignature) internal {\n uint256 sigIndex = _saveSignature(reportSignature);\n _storedReports.push(StoredReport(sigIndex, statementPayload));\n }\n\n /// @dev Saves the signature and returns its index.\n function _saveSignature(bytes memory signature) internal returns (uint256 sigIndex) {\n sigIndex = _storedSignatures.length;\n _storedSignatures.push(signature);\n }\n\n // ═══════════════════════════════════════════════ AGENT CHECKS ════════════════════════════════════════════════════\n\n /**\n * @dev Recovers a signer from a hashed message, and a EIP-191 signature for it.\n * Will revert, if the signer is not a known agent.\n * @dev Agent flag could be any of these: Active/Unstaking/Resting/Fraudulent/Slashed\n * Further checks need to be performed in a caller function.\n * @param hashedStatement Hash of the statement that was signed by an Agent\n * @param signature Agent signature for the hashed statement\n * @return status Struct representing agent status:\n * - flag Unknown/Active/Unstaking/Resting/Fraudulent/Slashed\n * - domain Domain where agent is/was active\n * - index Index of agent in the Agent Merkle Tree\n * @return agent Agent that signed the statement\n */\n function _recoverAgent(bytes32 hashedStatement, bytes memory signature)\n internal\n view\n returns (AgentStatus memory status, address agent)\n {\n bytes32 ethSignedMsg = ECDSA.toEthSignedMessageHash(hashedStatement);\n agent = ECDSA.recover(ethSignedMsg, signature);\n status = IAgentManager(agentManager).agentStatus(agent);\n // Discard signature of unknown agents.\n // Further flag checks are supposed to be performed in a caller function.\n status.verifyKnown();\n }\n\n /// @dev Verifies that Notary signature is active on local domain.\n function _verifyNotaryDomain(uint32 notaryDomain) internal view {\n // Notary needs to be from the local domain (if contract is not deployed on Synapse Chain).\n // Or Notary could be from any domain (if contract is deployed on Synapse Chain).\n if (notaryDomain != localDomain \u0026\u0026 localDomain != synapseDomain) revert IncorrectAgentDomain();\n }\n\n // ════════════════════════════════════════ ATTESTATION RELATED CHECKS ═════════════════════════════════════════════\n\n /**\n * @dev Internal function to verify the signed attestation payload.\n * Reverts if any of these is true:\n * - Attestation signer is not a known Notary.\n * @param att Typed memory view over attestation payload\n * @param attSignature Notary signature for the attestation\n * @return status Struct representing agent status, see {_recoverAgent}\n * @return notary Notary that signed the snapshot\n */\n function _verifyAttestation(Attestation att, bytes memory attSignature)\n internal\n view\n returns (AgentStatus memory status, address notary)\n {\n // This will revert if signer is not a known agent\n (status, notary) = _recoverAgent(att.hashValid(), attSignature);\n // Attestation signer needs to be a Notary, not a Guard\n if (status.domain == 0) revert AgentNotNotary();\n }\n\n /**\n * @dev Internal function to verify the signed attestation report payload.\n * Reverts if any of these is true:\n * - Report signer is not a known Guard.\n * @param att Typed memory view over attestation payload that Guard reports as invalid\n * @param arSignature Guard signature for the \"invalid attestation\" report\n * @return status Struct representing guard status, see {_recoverAgent}\n * @return guard Guard that signed the report\n */\n function _verifyAttestationReport(Attestation att, bytes memory arSignature)\n internal\n view\n returns (AgentStatus memory status, address guard)\n {\n // This will revert if signer is not a known agent\n (status, guard) = _recoverAgent(att.hashInvalid(), arSignature);\n // Report signer needs to be a Guard, not a Notary\n if (status.domain != 0) revert AgentNotGuard();\n }\n\n // ══════════════════════════════════════════ RECEIPT RELATED CHECKS ═══════════════════════════════════════════════\n\n /**\n * @dev Internal function to verify the signed receipt payload.\n * Reverts if any of these is true:\n * - Receipt signer is not a known Notary.\n * @param rcpt Typed memory view over receipt payload\n * @param rcptSignature Notary signature for the receipt\n * @return status Struct representing agent status, see {_recoverAgent}\n * @return notary Notary that signed the snapshot\n */\n function _verifyReceipt(Receipt rcpt, bytes memory rcptSignature)\n internal\n view\n returns (AgentStatus memory status, address notary)\n {\n // This will revert if signer is not a known agent\n (status, notary) = _recoverAgent(rcpt.hashValid(), rcptSignature);\n // Receipt signer needs to be a Notary, not a Guard\n if (status.domain == 0) revert AgentNotNotary();\n }\n\n /**\n * @dev Internal function to verify the signed receipt report payload.\n * Reverts if any of these is true:\n * - Report signer is not a known Guard.\n * @param rcpt Typed memory view over receipt payload that Guard reports as invalid\n * @param rrSignature Guard signature for the \"invalid receipt\" report\n * @return status Struct representing guard status, see {_recoverAgent}\n * @return guard Guard that signed the report\n */\n function _verifyReceiptReport(Receipt rcpt, bytes memory rrSignature)\n internal\n view\n returns (AgentStatus memory status, address guard)\n {\n // This will revert if signer is not a known agent\n (status, guard) = _recoverAgent(rcpt.hashInvalid(), rrSignature);\n // Report signer needs to be a Guard, not a Notary\n if (status.domain != 0) revert AgentNotGuard();\n }\n\n // ═══════════════════════════════════════ STATE/SNAPSHOT RELATED CHECKS ═══════════════════════════════════════════\n\n /**\n * @dev Internal function to verify the signed snapshot report payload.\n * Reverts if any of these is true:\n * - Report signer is not a known Guard.\n * @param state Typed memory view over state payload that Guard reports as invalid\n * @param srSignature Guard signature for the report\n * @return status Struct representing guard status, see {_recoverAgent}\n * @return guard Guard that signed the report\n */\n function _verifyStateReport(State state, bytes memory srSignature)\n internal\n view\n returns (AgentStatus memory status, address guard)\n {\n // This will revert if signer is not a known agent\n (status, guard) = _recoverAgent(state.hashInvalid(), srSignature);\n // Report signer needs to be a Guard, not a Notary\n if (status.domain != 0) revert AgentNotGuard();\n }\n\n /**\n * @dev Internal function to verify the signed snapshot payload.\n * Reverts if any of these is true:\n * - Snapshot signer is not a known Agent.\n * - Snapshot signer is not a Notary (if verifyNotary is true).\n * @param snapshot Typed memory view over snapshot payload\n * @param snapSignature Agent signature for the snapshot\n * @param verifyNotary If true, snapshot signer needs to be a Notary, not a Guard\n * @return status Struct representing agent status, see {_recoverAgent}\n * @return agent Agent that signed the snapshot\n */\n function _verifySnapshot(Snapshot snapshot, bytes memory snapSignature, bool verifyNotary)\n internal\n view\n returns (AgentStatus memory status, address agent)\n {\n // This will revert if signer is not a known agent\n (status, agent) = _recoverAgent(snapshot.hashValid(), snapSignature);\n // If requested, snapshot signer needs to be a Notary, not a Guard\n if (verifyNotary \u0026\u0026 status.domain == 0) revert AgentNotNotary();\n }\n\n // ═══════════════════════════════════════════ MERKLE RELATED CHECKS ═══════════════════════════════════════════════\n\n /**\n * @dev Internal function to verify that snapshot roots match.\n * Reverts if any of these is true:\n * - Attestation root is not equal to Merkle Root derived from State and Snapshot Proof.\n * - Snapshot Proof's first element does not match the State metadata.\n * - Snapshot Proof length exceeds Snapshot tree Height.\n * - State index is out of range.\n * @param att Typed memory view over Attestation\n * @param stateIndex Index of state in the snapshot\n * @param state Typed memory view over the provided state payload\n * @param snapProof Raw payload with snapshot data\n */\n function _verifySnapshotMerkle(Attestation att, uint8 stateIndex, State state, bytes32[] memory snapProof)\n internal\n pure\n {\n // Snapshot proof first element should match State metadata (aka \"right sub-leaf\")\n (, bytes32 rightSubLeaf) = state.subLeafs();\n if (snapProof[0] != rightSubLeaf) revert IncorrectSnapshotProof();\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(state.root(), state.origin(), snapProof, stateIndex);\n // Snapshot root should match the attestation root\n if (att.snapRoot() != snapshotRoot) revert IncorrectSnapshotRoot();\n }\n}\n\n// contracts/inbox/Inbox.sol\n\n// ══════════════════════════════ LIBRARY IMPORTS ══════════════════════════════\n\n// ═════════════════════════════ INTERNAL IMPORTS ══════════════════════════════\n\n/// @notice `Inbox` is the child of `StatementInbox` contract, that is used on Synapse Chain.\n/// In addition to the functionality of `StatementInbox`, it also:\n/// - Accepts Guard and Notary Snapshots and passes them to `Summit` contract.\n/// - Accepts Notary-signed Receipts and passes them to `Summit` contract.\n/// - Accepts Receipt Reports to initiate a dispute between Guard and Notary.\n/// - Verifies Attestations and Attestation Reports, and slashes the signer if they are invalid.\ncontract Inbox is StatementInbox, InboxEvents, InterfaceInbox {\n using AttestationLib for bytes;\n using ReceiptLib for bytes;\n using SnapshotLib for bytes;\n\n // Struct to get around stack too deep error. TODO: revisit this\n struct ReceiptInfo {\n AgentStatus rcptNotaryStatus;\n address notary;\n uint32 attNonce;\n AgentStatus attNotaryStatus;\n }\n\n // ══════════════════════════════════════════════════ STORAGE ══════════════════════════════════════════════════════\n\n // The address of the Summit contract.\n address public summit;\n\n // ═════════════════════════════════════════ CONSTRUCTOR \u0026 INITIALIZER ═════════════════════════════════════════════\n\n constructor(uint32 synapseDomain_) MessagingBase(\"0.0.3\", synapseDomain_) {\n if (localDomain != synapseDomain) revert MustBeSynapseDomain();\n }\n\n /// @notice Initializes `Inbox` contract:\n /// - Sets `msg.sender` as the owner of the contract\n /// - Sets `agentManager`, `origin`, `destination` and `summit` addresses\n function initialize(address agentManager_, address origin_, address destination_, address summit_)\n external\n initializer\n {\n __StatementInbox_init(agentManager_, origin_, destination_);\n summit = summit_;\n }\n\n // ══════════════════════════════════════════ SUBMIT AGENT STATEMENTS ══════════════════════════════════════════════\n\n /// @inheritdoc InterfaceInbox\n function submitSnapshot(bytes memory snapPayload, bytes memory snapSignature)\n external\n returns (bytes memory attPayload, bytes32 agentRoot_, uint256[] memory snapGas)\n {\n // This will revert if payload is not a snapshot\n Snapshot snapshot = snapPayload.castToSnapshot();\n // This will revert if the signer is not a known Guard/Notary\n (AgentStatus memory status, address agent) =\n _verifySnapshot({snapshot: snapshot, snapSignature: snapSignature, verifyNotary: false});\n // Check that Agent is active\n status.verifyActive();\n // Store Agent signature for the Snapshot\n uint256 sigIndex = _saveSignature(snapSignature);\n if (status.domain == 0) {\n // Guard that is in Dispute could still submit new snapshots, so we don't check that\n InterfaceSummit(summit).acceptGuardSnapshot({\n guardIndex: status.index,\n sigIndex: sigIndex,\n snapPayload: snapPayload\n });\n } else {\n // Get current agentRoot from AgentManager\n agentRoot_ = IAgentManager(agentManager).agentRoot();\n // This will revert if Notary is in Dispute\n attPayload = InterfaceSummit(summit).acceptNotarySnapshot({\n notaryIndex: status.index,\n sigIndex: sigIndex,\n agentRoot: agentRoot_,\n snapPayload: snapPayload\n });\n ChainGas[] memory snapGas_ = snapshot.snapGas();\n // Pass created attestation to Destination to enable executing messages coming to Synapse Chain\n InterfaceDestination(destination).acceptAttestation(\n status.index, type(uint256).max, attPayload, agentRoot_, snapGas_\n );\n // Use assembly to cast ChainGas[] to uint256[] without copying. Highest bits are left zeroed.\n // solhint-disable-next-line no-inline-assembly\n assembly {\n snapGas := snapGas_\n }\n }\n emit SnapshotAccepted(status.domain, agent, snapPayload, snapSignature);\n }\n\n /// @inheritdoc InterfaceInbox\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 // Struct to get around stack too deep error.\n ReceiptInfo memory info;\n // This will revert if payload is not a receipt\n Receipt rcpt = rcptPayload.castToReceipt();\n // This will revert if the receipt signer is not a known Notary\n (info.rcptNotaryStatus, info.notary) = _verifyReceipt(rcpt, rcptSignature);\n // Receipt Notary needs to be Active\n info.rcptNotaryStatus.verifyActive();\n info.attNonce = IExecutionHub(destination).getAttestationNonce(rcpt.snapshotRoot());\n if (info.attNonce == 0) revert IncorrectSnapshotRoot();\n // Attestation Notary domain needs to match the destination domain\n info.attNotaryStatus = IAgentManager(agentManager).agentStatus(rcpt.attNotary());\n if (info.attNotaryStatus.domain != rcpt.destination()) revert IncorrectAgentDomain();\n // Check that the correct tip values for the message were provided\n _verifyReceiptTips(rcpt.messageHash(), paddedTips, headerHash, bodyHash);\n // Store Notary signature for the Receipt\n uint256 sigIndex = _saveSignature(rcptSignature);\n // This will revert if Receipt Notary is in Dispute\n wasAccepted = InterfaceSummit(summit).acceptReceipt({\n rcptNotaryIndex: info.rcptNotaryStatus.index,\n attNotaryIndex: info.attNotaryStatus.index,\n sigIndex: sigIndex,\n attNonce: info.attNonce,\n paddedTips: paddedTips,\n rcptPayload: rcptPayload\n });\n if (wasAccepted) {\n emit ReceiptAccepted(info.rcptNotaryStatus.domain, info.notary, rcptPayload, rcptSignature);\n }\n }\n\n /// @inheritdoc InterfaceInbox\n function submitReceiptReport(bytes memory rcptPayload, bytes memory rcptSignature, bytes memory rrSignature)\n external\n returns (bool wasAccepted)\n {\n // This will revert if payload is not a receipt\n Receipt rcpt = rcptPayload.castToReceipt();\n // This will revert if the receipt signer is not a known Guard\n (AgentStatus memory guardStatus,) = _verifyReceiptReport(rcpt, rrSignature);\n // Guard needs to be Active\n guardStatus.verifyActive();\n // This will revert if report signer is not a known Notary\n (AgentStatus memory notaryStatus,) = _verifyReceipt(rcpt, rcptSignature);\n // Notary needs to be Active/Unstaking\n notaryStatus.verifyActiveUnstaking();\n _saveReport(rcptPayload, rrSignature);\n // This will revert if either actor is already in dispute\n IAgentManager(agentManager).openDispute(guardStatus.index, notaryStatus.index);\n return true;\n }\n\n /// @inheritdoc InterfaceInbox\n function passReceipt(uint32 attNotaryIndex, uint32 attNonce, uint256 paddedTips, bytes memory rcptPayload)\n external\n returns (bool wasAccepted)\n {\n // Only Destination can pass receipts\n if (msg.sender != destination) revert CallerNotDestination();\n return InterfaceSummit(summit).acceptReceipt({\n rcptNotaryIndex: attNotaryIndex,\n attNotaryIndex: attNotaryIndex,\n sigIndex: type(uint256).max,\n attNonce: attNonce,\n paddedTips: paddedTips,\n rcptPayload: rcptPayload\n });\n }\n\n // ══════════════════════════════════════════ VERIFY AGENT STATEMENTS ══════════════════════════════════════════════\n\n /// @inheritdoc InterfaceInbox\n function verifyAttestation(bytes memory attPayload, bytes memory attSignature)\n external\n returns (bool isValidAttestation)\n {\n // This will revert if payload is not an attestation\n Attestation att = attPayload.castToAttestation();\n // This will revert if the attestation signer is not a known Notary\n (AgentStatus memory status, address notary) = _verifyAttestation(att, attSignature);\n // Notary needs to be Active/Unstaking\n status.verifyActiveUnstaking();\n isValidAttestation = ISnapshotHub(summit).isValidAttestation(attPayload);\n if (!isValidAttestation) {\n emit InvalidAttestation(attPayload, attSignature);\n IAgentManager(agentManager).slashAgent(status.domain, notary, msg.sender);\n }\n }\n\n /// @inheritdoc InterfaceInbox\n function verifyAttestationReport(bytes memory attPayload, bytes memory arSignature)\n external\n returns (bool isValidReport)\n {\n // This will revert if payload is not an attestation\n Attestation att = attPayload.castToAttestation();\n // This will revert if the report signer is not a known Guard\n (AgentStatus memory status, address guard) = _verifyAttestationReport(att, arSignature);\n // Guard needs to be Active/Unstaking\n status.verifyActiveUnstaking();\n // Report is valid IF AND ONLY IF the reported attestation in invalid\n isValidReport = !ISnapshotHub(summit).isValidAttestation(attPayload);\n if (!isValidReport) {\n emit InvalidAttestationReport(attPayload, arSignature);\n IAgentManager(agentManager).slashAgent(status.domain, guard, msg.sender);\n }\n }\n\n // ══════════════════════════════════════════════ INTERNAL VIEWS ═══════════════════════════════════════════════════\n\n /// @dev Verifies that tips proof matches the message hash.\n function _verifyReceiptTips(bytes32 msgHash, uint256 paddedTips, bytes32 headerHash, bytes32 bodyHash)\n internal\n pure\n {\n Tips tips = TipsLib.wrapPadded(paddedTips);\n // full message leaf is (header, baseMessage), while base message leaf is (tips, remainingBody).\n if (MerkleMath.getParent(headerHash, MerkleMath.getParent(tips.leaf(), bodyHash)) != msgHash) {\n revert IncorrectTipsProof();\n }\n }\n}\n","language":"Solidity","languageVersion":"0.8.17","compilerVersion":"0.8.17","compilerOptions":"--combined-json bin,bin-runtime,srcmap,srcmap-runtime,abi,userdoc,devdoc,metadata,hashes --optimize --optimize-runs 10000 --allow-paths ., ./, ../","srcMap":"","srcMapRuntime":"","abiDefinition":[{"inputs":[],"name":"agentRoot","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"agent","type":"address"}],"name":"agentStatus","outputs":[{"components":[{"internalType":"enum AgentFlag","name":"flag","type":"uint8"},{"internalType":"uint32","name":"domain","type":"uint32"},{"internalType":"uint32","name":"index","type":"uint32"}],"internalType":"struct AgentStatus","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"agent","type":"address"}],"name":"disputeStatus","outputs":[{"internalType":"enum DisputeFlag","name":"flag","type":"uint8"},{"internalType":"address","name":"rival","type":"address"},{"internalType":"address","name":"fraudProver","type":"address"},{"internalType":"uint256","name":"disputePtr","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"index","type":"uint256"}],"name":"getAgent","outputs":[{"internalType":"address","name":"agent","type":"address"},{"components":[{"internalType":"enum AgentFlag","name":"flag","type":"uint8"},{"internalType":"uint32","name":"domain","type":"uint32"},{"internalType":"uint32","name":"index","type":"uint32"}],"internalType":"struct AgentStatus","name":"status","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"index","type":"uint256"}],"name":"getDispute","outputs":[{"internalType":"address","name":"guard","type":"address"},{"internalType":"address","name":"notary","type":"address"},{"internalType":"address","name":"slashedAgent","type":"address"},{"internalType":"address","name":"fraudProver","type":"address"},{"internalType":"bytes","name":"reportPayload","type":"bytes"},{"internalType":"bytes","name":"reportSignature","type":"bytes"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getDisputesAmount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint32","name":"guardIndex","type":"uint32"},{"internalType":"uint32","name":"notaryIndex","type":"uint32"}],"name":"openDispute","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint32","name":"domain","type":"uint32"},{"internalType":"address","name":"agent","type":"address"},{"internalType":"address","name":"prover","type":"address"}],"name":"slashAgent","outputs":[],"stateMutability":"nonpayable","type":"function"}],"userDoc":{"kind":"user","methods":{"agentRoot()":{"notice":"Returns the latest known root of the Agent Merkle Tree."},"agentStatus(address)":{"notice":"Returns (flag, domain, index) for a given agent. See Structures.sol for details."},"disputeStatus(address)":{"notice":"Returns the current Dispute status of a given agent. See Structures.sol for details."},"getAgent(uint256)":{"notice":"Returns agent address and their current status for a given agent index."},"getDispute(uint256)":{"notice":"Returns information about the dispute with the given index."},"getDisputesAmount()":{"notice":"Returns the number of opened Disputes."},"openDispute(uint32,uint32)":{"notice":"Allows Inbox to open a Dispute between a Guard and a Notary, if they are both not in Dispute already. \u003e Will revert if any of these is true: \u003e - Caller is not Inbox. \u003e - Guard or Notary is already in Dispute."},"slashAgent(uint32,address,address)":{"notice":"Allows Inbox to slash an agent, if their fraud was proven. \u003e Will revert if any of these is true: \u003e - Caller is not Inbox. \u003e - Domain doesn't match the saved agent domain."}},"version":1},"developerDoc":{"kind":"dev","methods":{"agentStatus(address)":{"details":"Will return AgentFlag.Fraudulent for agents that have been proven to commit fraud, but their status is not updated to Slashed yet.","params":{"agent":"Agent address"},"returns":{"_0":"Status for the given agent: (flag, domain, index)."}},"disputeStatus(address)":{"details":"Every returned value will be set to zero if agent was not slashed and is not in Dispute. `rival` and `disputePtr` will be set to zero if the agent was slashed without being in Dispute.","params":{"agent":"Agent address"},"returns":{"disputePtr":" Index of the opened Dispute PLUS ONE. Zero if agent is not in Dispute.","flag":" Flag describing the current Dispute status for the agent: None/Pending/Slashed","fraudProver":" Address who provided fraud proof to resolve the Dispute","rival":" Address of the rival agent in the Dispute"}},"getAgent(uint256)":{"details":"Will return empty values if agent with given index doesn't exist.","params":{"index":"Agent index in the Agent Merkle Tree"},"returns":{"agent":" Agent address","status":" Status for the given agent: (flag, domain, index)"}},"getDispute(uint256)":{"details":"Will revert if dispute with given index hasn't been opened yet.","params":{"index":"Dispute index"},"returns":{"fraudProver":" Address who provided fraud proof to resolve the Dispute","guard":" Address of the Guard in the Dispute","notary":" Address of the Notary in the Dispute","reportPayload":" Raw payload with report data that led to the Dispute","reportSignature":" Guard signature for the report payload","slashedAgent":" Address of the Agent who was slashed when Dispute was resolved"}},"getDisputesAmount()":{"details":"This includes the Disputes that have been resolved already."},"openDispute(uint32,uint32)":{"params":{"guardIndex":"Index of the Guard in the Agent Merkle Tree","notaryIndex":"Index of the Notary in the Agent Merkle Tree"}},"slashAgent(uint32,address,address)":{"params":{"agent":"Address of the Agent","domain":"Domain where the Agent is active","prover":"Address that initially provided fraud proof"}}},"version":1},"metadata":"{\"compiler\":{\"version\":\"0.8.17+commit.8df45f5f\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[],\"name\":\"agentRoot\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"agent\",\"type\":\"address\"}],\"name\":\"agentStatus\",\"outputs\":[{\"components\":[{\"internalType\":\"enum AgentFlag\",\"name\":\"flag\",\"type\":\"uint8\"},{\"internalType\":\"uint32\",\"name\":\"domain\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"index\",\"type\":\"uint32\"}],\"internalType\":\"struct AgentStatus\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"agent\",\"type\":\"address\"}],\"name\":\"disputeStatus\",\"outputs\":[{\"internalType\":\"enum DisputeFlag\",\"name\":\"flag\",\"type\":\"uint8\"},{\"internalType\":\"address\",\"name\":\"rival\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"fraudProver\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"disputePtr\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"index\",\"type\":\"uint256\"}],\"name\":\"getAgent\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"agent\",\"type\":\"address\"},{\"components\":[{\"internalType\":\"enum AgentFlag\",\"name\":\"flag\",\"type\":\"uint8\"},{\"internalType\":\"uint32\",\"name\":\"domain\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"index\",\"type\":\"uint32\"}],\"internalType\":\"struct AgentStatus\",\"name\":\"status\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"index\",\"type\":\"uint256\"}],\"name\":\"getDispute\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"guard\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"notary\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"slashedAgent\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"fraudProver\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"reportPayload\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"reportSignature\",\"type\":\"bytes\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getDisputesAmount\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint32\",\"name\":\"guardIndex\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"notaryIndex\",\"type\":\"uint32\"}],\"name\":\"openDispute\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint32\",\"name\":\"domain\",\"type\":\"uint32\"},{\"internalType\":\"address\",\"name\":\"agent\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"prover\",\"type\":\"address\"}],\"name\":\"slashAgent\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{\"agentStatus(address)\":{\"details\":\"Will return AgentFlag.Fraudulent for agents that have been proven to commit fraud, but their status is not updated to Slashed yet.\",\"params\":{\"agent\":\"Agent address\"},\"returns\":{\"_0\":\"Status for the given agent: (flag, domain, index).\"}},\"disputeStatus(address)\":{\"details\":\"Every returned value will be set to zero if agent was not slashed and is not in Dispute. `rival` and `disputePtr` will be set to zero if the agent was slashed without being in Dispute.\",\"params\":{\"agent\":\"Agent address\"},\"returns\":{\"disputePtr\":\" Index of the opened Dispute PLUS ONE. Zero if agent is not in Dispute.\",\"flag\":\" Flag describing the current Dispute status for the agent: None/Pending/Slashed\",\"fraudProver\":\" Address who provided fraud proof to resolve the Dispute\",\"rival\":\" Address of the rival agent in the Dispute\"}},\"getAgent(uint256)\":{\"details\":\"Will return empty values if agent with given index doesn't exist.\",\"params\":{\"index\":\"Agent index in the Agent Merkle Tree\"},\"returns\":{\"agent\":\" Agent address\",\"status\":\" Status for the given agent: (flag, domain, index)\"}},\"getDispute(uint256)\":{\"details\":\"Will revert if dispute with given index hasn't been opened yet.\",\"params\":{\"index\":\"Dispute index\"},\"returns\":{\"fraudProver\":\" Address who provided fraud proof to resolve the Dispute\",\"guard\":\" Address of the Guard in the Dispute\",\"notary\":\" Address of the Notary in the Dispute\",\"reportPayload\":\" Raw payload with report data that led to the Dispute\",\"reportSignature\":\" Guard signature for the report payload\",\"slashedAgent\":\" Address of the Agent who was slashed when Dispute was resolved\"}},\"getDisputesAmount()\":{\"details\":\"This includes the Disputes that have been resolved already.\"},\"openDispute(uint32,uint32)\":{\"params\":{\"guardIndex\":\"Index of the Guard in the Agent Merkle Tree\",\"notaryIndex\":\"Index of the Notary in the Agent Merkle Tree\"}},\"slashAgent(uint32,address,address)\":{\"params\":{\"agent\":\"Address of the Agent\",\"domain\":\"Domain where the Agent is active\",\"prover\":\"Address that initially provided fraud proof\"}}},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{\"agentRoot()\":{\"notice\":\"Returns the latest known root of the Agent Merkle Tree.\"},\"agentStatus(address)\":{\"notice\":\"Returns (flag, domain, index) for a given agent. See Structures.sol for details.\"},\"disputeStatus(address)\":{\"notice\":\"Returns the current Dispute status of a given agent. See Structures.sol for details.\"},\"getAgent(uint256)\":{\"notice\":\"Returns agent address and their current status for a given agent index.\"},\"getDispute(uint256)\":{\"notice\":\"Returns information about the dispute with the given index.\"},\"getDisputesAmount()\":{\"notice\":\"Returns the number of opened Disputes.\"},\"openDispute(uint32,uint32)\":{\"notice\":\"Allows Inbox to open a Dispute between a Guard and a Notary, if they are both not in Dispute already. \u003e Will revert if any of these is true: \u003e - Caller is not Inbox. \u003e - Guard or Notary is already in Dispute.\"},\"slashAgent(uint32,address,address)\":{\"notice\":\"Allows Inbox to slash an agent, if their fraud was proven. \u003e Will revert if any of these is true: \u003e - Caller is not Inbox. \u003e - Domain doesn't match the saved agent domain.\"}},\"version\":1}},\"settings\":{\"compilationTarget\":{\"solidity/Inbox.sol\":\"IAgentManager\"},\"evmVersion\":\"london\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\"},\"optimizer\":{\"enabled\":true,\"runs\":10000},\"remappings\":[]},\"sources\":{\"solidity/Inbox.sol\":{\"keccak256\":\"0x9b516081a036814c0169e20e484d4a5499066b7a6f48fada952b5e844a1ca3e5\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://32bde393b3f24ef4307d9626d4143f337b3c0bd34e17bb969fd5a15221d96987\",\"dweb:/ipfs/QmTkt2XZRtgsbSpmsVQUM3c4ebETQoDVYbmEV9yheBghnr\"]}},\"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/Inbox.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/InboxEvents.sol\n\nabstract contract InboxEvents {\n /**\n * @notice Emitted when a snapshot is accepted by the Summit contract.\n * @param domain Domain where the signed Agent is active (ZERO for Guards)\n * @param agent Agent who signed the snapshot\n * @param snapPayload Raw payload with snapshot data\n * @param snapSignature Agent signature for the snapshot\n */\n event SnapshotAccepted(uint32 indexed domain, address indexed agent, bytes snapPayload, bytes snapSignature);\n\n /**\n * @notice Emitted when a snapshot is accepted by the Summit contract.\n * @param domain Domain where the signed Notary is active\n * @param notary Notary who signed the attestation\n * @param rcptPayload Raw payload with receipt data\n * @param rcptSignature Notary signature for the receipt\n */\n event ReceiptAccepted(uint32 domain, address notary, bytes rcptPayload, bytes rcptSignature);\n\n /**\n * @notice Emitted when a proof of invalid attestation is submitted.\n * @param attPayload Raw payload with Attestation data\n * @param attSignature Notary signature for the attestation\n */\n event InvalidAttestation(bytes attPayload, bytes attSignature);\n\n /**\n * @notice Emitted when a proof of invalid attestation report is submitted.\n * @param arPayload Raw payload with report data\n * @param arSignature Guard signature for the report\n */\n event InvalidAttestationReport(bytes arPayload, bytes arSignature);\n}\n\n// contracts/events/StatementInboxEvents.sol\n\nabstract contract StatementInboxEvents {\n // ════════════════════════════════════════════ STATEMENT ACCEPTED ═════════════════════════════════════════════════\n\n /**\n * @notice Emitted when a snapshot is accepted by the Destination contract.\n * @param domain Domain where the signed Notary is active\n * @param notary Notary who signed the attestation\n * @param attPayload Raw payload with attestation data\n * @param attSignature Notary signature for the attestation\n */\n event AttestationAccepted(uint32 domain, address notary, bytes attPayload, bytes attSignature);\n\n // ═════════════════════════════════════════ INVALID STATEMENT PROVED ══════════════════════════════════════════════\n\n /**\n * @notice Emitted when a proof of invalid receipt statement is submitted.\n * @param rcptPayload Raw payload with the receipt statement\n * @param rcptSignature Notary signature for the receipt statement\n */\n event InvalidReceipt(bytes rcptPayload, bytes rcptSignature);\n\n /**\n * @notice Emitted when a proof of invalid receipt report is submitted.\n * @param rrPayload Raw payload with report data\n * @param rrSignature Guard signature for the report\n */\n event InvalidReceiptReport(bytes rrPayload, bytes rrSignature);\n\n /**\n * @notice Emitted when a proof of invalid state in the signed attestation is submitted.\n * @param stateIndex Index of invalid state in the snapshot\n * @param statePayload Raw payload with state data\n * @param attPayload Raw payload with Attestation data for snapshot\n * @param attSignature Notary signature for the attestation\n */\n event InvalidStateWithAttestation(uint8 stateIndex, bytes statePayload, bytes attPayload, bytes attSignature);\n\n /**\n * @notice Emitted when a proof of invalid state in the signed snapshot is submitted.\n * @param stateIndex Index of invalid state in the snapshot\n * @param snapPayload Raw payload with snapshot data\n * @param snapSignature Agent signature for the snapshot\n */\n event InvalidStateWithSnapshot(uint8 stateIndex, bytes snapPayload, bytes snapSignature);\n\n /**\n * @notice Emitted when a proof of invalid state report is submitted.\n * @param srPayload Raw payload with report data\n * @param srSignature Guard signature for the report\n */\n event InvalidStateReport(bytes srPayload, bytes srSignature);\n}\n\n// contracts/interfaces/ISnapshotHub.sol\n\ninterface ISnapshotHub {\n /**\n * @notice Check that a given attestation is valid: matches the historical attestation\n * derived from an accepted Notary snapshot.\n * @dev Will revert if any of these is true:\n * - Attestation payload is not properly formatted.\n * @param attPayload Raw payload with attestation data\n * @return isValid Whether the provided attestation is valid\n */\n function isValidAttestation(bytes memory attPayload) external view returns (bool isValid);\n\n /**\n * @notice Returns saved attestation with the given nonce.\n * @dev Reverts if attestation with given nonce hasn't been created yet.\n * @param attNonce Nonce for the attestation\n * @return attPayload Raw payload with formatted Attestation data\n * @return agentRoot Agent root hash used for the attestation\n * @return snapGas Snapshot gas data used for the attestation\n */\n function getAttestation(uint32 attNonce)\n external\n view\n returns (bytes memory attPayload, bytes32 agentRoot, uint256[] memory snapGas);\n\n /**\n * @notice Returns the state with the highest known nonce submitted by a given Agent.\n * @param origin Domain of origin chain\n * @param agent Agent address\n * @return statePayload Raw payload with agent's latest state for origin\n */\n function getLatestAgentState(uint32 origin, address agent) external view returns (bytes memory statePayload);\n\n /**\n * @notice Returns latest saved attestation for a Notary.\n * @param notary Notary address\n * @return attPayload Raw payload with formatted Attestation data\n * @return agentRoot Agent root hash used for the attestation\n * @return snapGas Snapshot gas data used for the attestation\n */\n function getLatestNotaryAttestation(address notary)\n external\n view\n returns (bytes memory attPayload, bytes32 agentRoot, uint256[] memory snapGas);\n\n /**\n * @notice Returns Guard snapshot from the list of all accepted Guard snapshots.\n * @dev Reverts if snapshot with given index hasn't been accepted yet.\n * @param index Snapshot index in the list of all Guard snapshots\n * @return snapPayload Raw payload with Guard snapshot\n * @return snapSignature Raw payload with Guard signature for snapshot\n */\n function getGuardSnapshot(uint256 index)\n external\n view\n returns (bytes memory snapPayload, bytes memory snapSignature);\n\n /**\n * @notice Returns Notary snapshot from the list of all accepted Guard snapshots.\n * @dev Reverts if snapshot with given index hasn't been accepted yet.\n * @param index Snapshot index in the list of all Notary snapshots\n * @return snapPayload Raw payload with Notary snapshot\n * @return snapSignature Raw payload with Notary signature for snapshot\n */\n function getNotarySnapshot(uint256 index)\n external\n view\n returns (bytes memory snapPayload, bytes memory snapSignature);\n\n /**\n * @notice Returns Notary snapshot that was used for creating a given attestation.\n * @dev Reverts if any of these is true:\n * - Attestation payload is not properly formatted.\n * - Attestation is invalid (doesn't have a matching Notary snapshot).\n * @param attPayload Raw payload with attestation data\n * @return snapPayload Raw payload with Notary snapshot\n * @return snapSignature Raw payload with Notary signature for snapshot\n */\n function getNotarySnapshot(bytes memory attPayload)\n external\n view\n returns (bytes memory snapPayload, bytes memory snapSignature);\n\n /**\n * @notice Returns proof of inclusion of (root, origin) fields of a given snapshot's state\n * into the Snapshot Merkle Tree for a given attestation.\n * @dev Reverts if any of these is true:\n * - Attestation with given nonce hasn't been created yet.\n * - State index is out of range of snapshot list.\n * @param attNonce Nonce for the attestation\n * @param stateIndex Index of state in the attestation's snapshot\n * @return snapProof The snapshot proof\n */\n function getSnapshotProof(uint32 attNonce, uint8 stateIndex) external view returns (bytes32[] memory snapProof);\n}\n\n// contracts/interfaces/IStateHub.sol\n\ninterface IStateHub {\n /**\n * @notice Check that a given state is valid: matches the historical state of Origin contract.\n * Note: any Agent including an invalid state in their snapshot will be slashed\n * upon providing the snapshot and agent signature for it to Origin contract.\n * @dev Will revert if any of these is true:\n * - State payload is not properly formatted.\n * @param statePayload Raw payload with state data\n * @return isValid Whether the provided state is valid\n */\n function isValidState(bytes memory statePayload) external view returns (bool isValid);\n\n /**\n * @notice Returns the amount of saved states so far.\n * @dev This includes the initial state of \"empty Origin Merkle Tree\".\n */\n function statesAmount() external view returns (uint256);\n\n /**\n * @notice Suggest the data (state after latest sent message) to sign for an Agent.\n * Note: signing the suggested state data will will never lead to slashing of the actor,\n * assuming they have confirmed that the block, which number is included in the data,\n * is not subject to reorganization (which is different for every observed chain).\n * @return statePayload Raw payload with the latest state data\n */\n function suggestLatestState() external view returns (bytes memory statePayload);\n\n /**\n * @notice Given the historical nonce, suggest the state data to sign for an Agent.\n * Note: signing the suggested state data will will never lead to slashing of the actor,\n * assuming they have confirmed that the block, which number is included in the data,\n * is not subject to reorganization (which is different for every observed chain).\n * @param nonce Historical nonce to form a state\n * @return statePayload Raw payload with historical state data\n */\n function suggestState(uint32 nonce) external view returns (bytes memory statePayload);\n}\n\n// contracts/interfaces/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/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// node_modules/@openzeppelin/contracts/utils/math/Math.sol\n\n// OpenZeppelin Contracts (last updated v4.9.0) (utils/math/Math.sol)\n\n/**\n * @dev Standard math utilities missing in the Solidity language.\n */\nlibrary Math {\n enum Rounding {\n Down, // Toward negative infinity\n Up, // Toward infinity\n Zero // Toward zero\n }\n\n /**\n * @dev Returns the largest of two numbers.\n */\n function max(uint256 a, uint256 b) internal pure returns (uint256) {\n return a \u003e b ? a : b;\n }\n\n /**\n * @dev Returns the smallest of two numbers.\n */\n function min(uint256 a, uint256 b) internal pure returns (uint256) {\n return a \u003c b ? a : b;\n }\n\n /**\n * @dev Returns the average of two numbers. The result is rounded towards\n * zero.\n */\n function average(uint256 a, uint256 b) internal pure returns (uint256) {\n // (a + b) / 2 can overflow.\n return (a \u0026 b) + (a ^ b) / 2;\n }\n\n /**\n * @dev Returns the ceiling of the division of two numbers.\n *\n * This differs from standard division with `/` in that it rounds up instead\n * of rounding down.\n */\n function ceilDiv(uint256 a, uint256 b) internal pure returns (uint256) {\n // (a + b - 1) / b can overflow on addition, so we distribute.\n return a == 0 ? 0 : (a - 1) / b + 1;\n }\n\n /**\n * @notice Calculates floor(x * y / denominator) with full precision. Throws if result overflows a uint256 or denominator == 0\n * @dev Original credit to Remco Bloemen under MIT license (https://xn--2-umb.com/21/muldiv)\n * with further edits by Uniswap Labs also under MIT license.\n */\n function mulDiv(uint256 x, uint256 y, uint256 denominator) internal pure returns (uint256 result) {\n unchecked {\n // 512-bit multiply [prod1 prod0] = x * y. Compute the product mod 2^256 and mod 2^256 - 1, then use\n // use the Chinese Remainder Theorem to reconstruct the 512 bit result. The result is stored in two 256\n // variables such that product = prod1 * 2^256 + prod0.\n uint256 prod0; // Least significant 256 bits of the product\n uint256 prod1; // Most significant 256 bits of the product\n assembly {\n let mm := mulmod(x, y, not(0))\n prod0 := mul(x, y)\n prod1 := sub(sub(mm, prod0), lt(mm, prod0))\n }\n\n // Handle non-overflow cases, 256 by 256 division.\n if (prod1 == 0) {\n // Solidity will revert if denominator == 0, unlike the div opcode on its own.\n // The surrounding unchecked block does not change this fact.\n // See https://docs.soliditylang.org/en/latest/control-structures.html#checked-or-unchecked-arithmetic.\n return prod0 / denominator;\n }\n\n // Make sure the result is less than 2^256. Also prevents denominator == 0.\n require(denominator \u003e prod1, \"Math: mulDiv overflow\");\n\n ///////////////////////////////////////////////\n // 512 by 256 division.\n ///////////////////////////////////////////////\n\n // Make division exact by subtracting the remainder from [prod1 prod0].\n uint256 remainder;\n assembly {\n // Compute remainder using mulmod.\n remainder := mulmod(x, y, denominator)\n\n // Subtract 256 bit number from 512 bit number.\n prod1 := sub(prod1, gt(remainder, prod0))\n prod0 := sub(prod0, remainder)\n }\n\n // Factor powers of two out of denominator and compute largest power of two divisor of denominator. Always \u003e= 1.\n // See https://cs.stackexchange.com/q/138556/92363.\n\n // Does not overflow because the denominator cannot be zero at this stage in the function.\n uint256 twos = denominator \u0026 (~denominator + 1);\n assembly {\n // Divide denominator by twos.\n denominator := div(denominator, twos)\n\n // Divide [prod1 prod0] by twos.\n prod0 := div(prod0, twos)\n\n // Flip twos such that it is 2^256 / twos. If twos is zero, then it becomes one.\n twos := add(div(sub(0, twos), twos), 1)\n }\n\n // Shift in bits from prod1 into prod0.\n prod0 |= prod1 * twos;\n\n // Invert denominator mod 2^256. Now that denominator is an odd number, it has an inverse modulo 2^256 such\n // that denominator * inv = 1 mod 2^256. Compute the inverse by starting with a seed that is correct for\n // four bits. That is, denominator * inv = 1 mod 2^4.\n uint256 inverse = (3 * denominator) ^ 2;\n\n // Use the Newton-Raphson iteration to improve the precision. Thanks to Hensel's lifting lemma, this also works\n // in modular arithmetic, doubling the correct bits in each step.\n inverse *= 2 - denominator * inverse; // inverse mod 2^8\n inverse *= 2 - denominator * inverse; // inverse mod 2^16\n inverse *= 2 - denominator * inverse; // inverse mod 2^32\n inverse *= 2 - denominator * inverse; // inverse mod 2^64\n inverse *= 2 - denominator * inverse; // inverse mod 2^128\n inverse *= 2 - denominator * inverse; // inverse mod 2^256\n\n // Because the division is now exact we can divide by multiplying with the modular inverse of denominator.\n // This will give us the correct result modulo 2^256. Since the preconditions guarantee that the outcome is\n // less than 2^256, this is the final result. We don't need to compute the high bits of the result and prod1\n // is no longer required.\n result = prod0 * inverse;\n return result;\n }\n }\n\n /**\n * @notice Calculates x * y / denominator with full precision, following the selected rounding direction.\n */\n function mulDiv(uint256 x, uint256 y, uint256 denominator, Rounding rounding) internal pure returns (uint256) {\n uint256 result = mulDiv(x, y, denominator);\n if (rounding == Rounding.Up \u0026\u0026 mulmod(x, y, denominator) \u003e 0) {\n result += 1;\n }\n return result;\n }\n\n /**\n * @dev Returns the square root of a number. If the number is not a perfect square, the value is rounded down.\n *\n * Inspired by Henry S. Warren, Jr.'s \"Hacker's Delight\" (Chapter 11).\n */\n function sqrt(uint256 a) internal pure returns (uint256) {\n if (a == 0) {\n return 0;\n }\n\n // For our first guess, we get the biggest power of 2 which is smaller than the square root of the target.\n //\n // We know that the \"msb\" (most significant bit) of our target number `a` is a power of 2 such that we have\n // `msb(a) \u003c= a \u003c 2*msb(a)`. This value can be written `msb(a)=2**k` with `k=log2(a)`.\n //\n // This can be rewritten `2**log2(a) \u003c= a \u003c 2**(log2(a) + 1)`\n // → `sqrt(2**k) \u003c= sqrt(a) \u003c sqrt(2**(k+1))`\n // → `2**(k/2) \u003c= sqrt(a) \u003c 2**((k+1)/2) \u003c= 2**(k/2 + 1)`\n //\n // Consequently, `2**(log2(a) / 2)` is a good first approximation of `sqrt(a)` with at least 1 correct bit.\n uint256 result = 1 \u003c\u003c (log2(a) \u003e\u003e 1);\n\n // At this point `result` is an estimation with one bit of precision. We know the true value is a uint128,\n // since it is the square root of a uint256. Newton's method converges quadratically (precision doubles at\n // every iteration). We thus need at most 7 iteration to turn our partial result with one bit of precision\n // into the expected uint128 result.\n unchecked {\n result = (result + a / result) \u003e\u003e 1;\n result = (result + a / result) \u003e\u003e 1;\n result = (result + a / result) \u003e\u003e 1;\n result = (result + a / result) \u003e\u003e 1;\n result = (result + a / result) \u003e\u003e 1;\n result = (result + a / result) \u003e\u003e 1;\n result = (result + a / result) \u003e\u003e 1;\n return min(result, a / result);\n }\n }\n\n /**\n * @notice Calculates sqrt(a), following the selected rounding direction.\n */\n function sqrt(uint256 a, Rounding rounding) internal pure returns (uint256) {\n unchecked {\n uint256 result = sqrt(a);\n return result + (rounding == Rounding.Up \u0026\u0026 result * result \u003c a ? 1 : 0);\n }\n }\n\n /**\n * @dev Return the log in base 2, rounded down, of a positive value.\n * Returns 0 if given 0.\n */\n function log2(uint256 value) internal pure returns (uint256) {\n uint256 result = 0;\n unchecked {\n if (value \u003e\u003e 128 \u003e 0) {\n value \u003e\u003e= 128;\n result += 128;\n }\n if (value \u003e\u003e 64 \u003e 0) {\n value \u003e\u003e= 64;\n result += 64;\n }\n if (value \u003e\u003e 32 \u003e 0) {\n value \u003e\u003e= 32;\n result += 32;\n }\n if (value \u003e\u003e 16 \u003e 0) {\n value \u003e\u003e= 16;\n result += 16;\n }\n if (value \u003e\u003e 8 \u003e 0) {\n value \u003e\u003e= 8;\n result += 8;\n }\n if (value \u003e\u003e 4 \u003e 0) {\n value \u003e\u003e= 4;\n result += 4;\n }\n if (value \u003e\u003e 2 \u003e 0) {\n value \u003e\u003e= 2;\n result += 2;\n }\n if (value \u003e\u003e 1 \u003e 0) {\n result += 1;\n }\n }\n return result;\n }\n\n /**\n * @dev Return the log in base 2, following the selected rounding direction, of a positive value.\n * Returns 0 if given 0.\n */\n function log2(uint256 value, Rounding rounding) internal pure returns (uint256) {\n unchecked {\n uint256 result = log2(value);\n return result + (rounding == Rounding.Up \u0026\u0026 1 \u003c\u003c result \u003c value ? 1 : 0);\n }\n }\n\n /**\n * @dev Return the log in base 10, rounded down, of a positive value.\n * Returns 0 if given 0.\n */\n function log10(uint256 value) internal pure returns (uint256) {\n uint256 result = 0;\n unchecked {\n if (value \u003e= 10 ** 64) {\n value /= 10 ** 64;\n result += 64;\n }\n if (value \u003e= 10 ** 32) {\n value /= 10 ** 32;\n result += 32;\n }\n if (value \u003e= 10 ** 16) {\n value /= 10 ** 16;\n result += 16;\n }\n if (value \u003e= 10 ** 8) {\n value /= 10 ** 8;\n result += 8;\n }\n if (value \u003e= 10 ** 4) {\n value /= 10 ** 4;\n result += 4;\n }\n if (value \u003e= 10 ** 2) {\n value /= 10 ** 2;\n result += 2;\n }\n if (value \u003e= 10 ** 1) {\n result += 1;\n }\n }\n return result;\n }\n\n /**\n * @dev Return the log in base 10, following the selected rounding direction, of a positive value.\n * Returns 0 if given 0.\n */\n function log10(uint256 value, Rounding rounding) internal pure returns (uint256) {\n unchecked {\n uint256 result = log10(value);\n return result + (rounding == Rounding.Up \u0026\u0026 10 ** result \u003c value ? 1 : 0);\n }\n }\n\n /**\n * @dev Return the log in base 256, rounded down, of a positive value.\n * Returns 0 if given 0.\n *\n * Adding one to the result gives the number of pairs of hex symbols needed to represent `value` as a hex string.\n */\n function log256(uint256 value) internal pure returns (uint256) {\n uint256 result = 0;\n unchecked {\n if (value \u003e\u003e 128 \u003e 0) {\n value \u003e\u003e= 128;\n result += 16;\n }\n if (value \u003e\u003e 64 \u003e 0) {\n value \u003e\u003e= 64;\n result += 8;\n }\n if (value \u003e\u003e 32 \u003e 0) {\n value \u003e\u003e= 32;\n result += 4;\n }\n if (value \u003e\u003e 16 \u003e 0) {\n value \u003e\u003e= 16;\n result += 2;\n }\n if (value \u003e\u003e 8 \u003e 0) {\n result += 1;\n }\n }\n return result;\n }\n\n /**\n * @dev Return the log in base 256, following the selected rounding direction, of a positive value.\n * Returns 0 if given 0.\n */\n function log256(uint256 value, Rounding rounding) internal pure returns (uint256) {\n unchecked {\n uint256 result = log256(value);\n return result + (rounding == Rounding.Up \u0026\u0026 1 \u003c\u003c (result \u003c\u003c 3) \u003c value ? 1 : 0);\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/utils/math/SignedMath.sol\n\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/math/SignedMath.sol)\n\n/**\n * @dev Standard signed math utilities missing in the Solidity language.\n */\nlibrary SignedMath {\n /**\n * @dev Returns the largest of two signed numbers.\n */\n function max(int256 a, int256 b) internal pure returns (int256) {\n return a \u003e b ? a : b;\n }\n\n /**\n * @dev Returns the smallest of two signed numbers.\n */\n function min(int256 a, int256 b) internal pure returns (int256) {\n return a \u003c b ? a : b;\n }\n\n /**\n * @dev Returns the average of two signed numbers without overflow.\n * The result is rounded towards zero.\n */\n function average(int256 a, int256 b) internal pure returns (int256) {\n // Formula from the book \"Hacker's Delight\"\n int256 x = (a \u0026 b) + ((a ^ b) \u003e\u003e 1);\n return x + (int256(uint256(x) \u003e\u003e 255) \u0026 (a ^ b));\n }\n\n /**\n * @dev Returns the absolute unsigned value of a signed value.\n */\n function abs(int256 n) internal pure returns (uint256) {\n unchecked {\n // must be unchecked in order to support `n = type(int256).min`\n return uint256(n \u003e= 0 ? n : -n);\n }\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// 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/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/InterfaceSummit.sol\n\ninterface InterfaceSummit {\n // ══════════════════════════════════════════ ACCEPT AGENT STATEMENTS ══════════════════════════════════════════════\n\n /**\n * @notice Accepts a receipt, which local `AgentManager` verified to have been signed by an active Notary.\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 * - Notary who signed the receipt is referenced as the \"Receipt Notary\".\n * - Notary who signed the attestation on destination chain is referenced as the \"Attestation Notary\".\n * \u003e Will revert if any of these is true:\n * \u003e - Called by anyone other than local `AgentManager`.\n * \u003e - Receipt body payload is not properly formatted.\n * \u003e - Receipt signer is in Dispute.\n * \u003e - Receipt's snapshot root is unknown.\n * @param rcptNotaryIndex Index of Receipt Notary in Agent Merkle Tree\n * @param attNotaryIndex Index of Attestation Notary in Agent Merkle Tree\n * @param sigIndex Index of stored Notary signature\n * @param attNonce Nonce of the attestation used for proving the executed message\n * @param paddedTips Padded encoded paid tips information\n * @param rcptPayload Raw payload with message execution receipt\n * @return wasAccepted Whether the receipt was accepted\n */\n function acceptReceipt(\n uint32 rcptNotaryIndex,\n uint32 attNotaryIndex,\n uint256 sigIndex,\n uint32 attNonce,\n uint256 paddedTips,\n bytes memory rcptPayload\n ) external returns (bool wasAccepted);\n\n /**\n * @notice Accepts a snapshot, which local `AgentManager` verified to have been signed by an active Guard.\n * \u003e Snapshot is a list of states for a set of Origin contracts residing on any of the chains.\n * All the states in the Guard-signed snapshot become available for Notary signing.\n * \u003e Will revert if any of these is true:\n * \u003e - Called by anyone other than local `AgentManager`.\n * \u003e - Snapshot payload is not properly formatted.\n * \u003e - Snapshot contains a state older then the Guard has previously submitted.\n * @param guardIndex Index of Guard in Agent Merkle Tree\n * @param sigIndex Index of stored Agent signature\n * @param snapPayload Raw payload with snapshot data\n */\n function acceptGuardSnapshot(uint32 guardIndex, uint256 sigIndex, bytes memory snapPayload) external;\n\n /**\n * @notice Accepts a snapshot, which local `AgentManager` verified to have been signed by an active Notary.\n * \u003e Snapshot is a list of states for a set of Origin contracts residing on any of the chains.\n * Snapshot Merkle Root is calculated and saved for valid snapshots, i.e.\n * snapshots which are only using states previously submitted by any of the Guards.\n * - Notary could use states singed by the same of different Guards 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 - Called by anyone other than local `AgentManager`.\n * \u003e - Snapshot payload is not properly formatted.\n * \u003e - Snapshot contains a state older then the Notary has previously submitted.\n * \u003e - Snapshot contains a state that no Guard has previously submitted.\n * @param notaryIndex Index of Notary in Agent Merkle Tree\n * @param sigIndex Index of stored Agent signature\n * @param agentRoot Current root of the Agent Merkle Tree\n * @param snapPayload Raw payload with snapshot data\n * @return attPayload Raw payload with data for attestation derived from Notary snapshot.\n */\n function acceptNotarySnapshot(uint32 notaryIndex, uint256 sigIndex, bytes32 agentRoot, bytes memory snapPayload)\n external\n returns (bytes memory attPayload);\n\n // ════════════════════════════════════════════════ TIPS LOGIC ═════════════════════════════════════════════════════\n\n /**\n * @notice Distributes tips using the first Receipt from the \"receipt quarantine queue\".\n * Possible scenarios:\n * - Receipt queue is empty =\u003e does nothing\n * - Receipt optimistic period is not over =\u003e does nothing\n * - Either of Notaries present in Receipt was slashed =\u003e receipt is deleted from the queue\n * - Either of Notaries present in Receipt in Dispute =\u003e receipt is moved to the end of queue\n * - None of the above =\u003e receipt tips are distributed\n * @dev Returned value makes it possible to do the following: `while (distributeTips()) {}`\n * @return queuePopped Whether the first element was popped from the queue\n */\n function distributeTips() external returns (bool queuePopped);\n\n /**\n * @notice Withdraws locked base message tips from requested domain Origin to the recipient.\n * This is done by a call to a local Origin contract, or by a manager message to the remote chain.\n * @dev This will revert, if the pending balance of origin tips (earned-claimed) is lower than requested.\n * @param origin Domain of chain to withdraw tips on\n * @param amount Amount of tips to withdraw\n */\n function withdrawTips(uint32 origin, uint256 amount) external;\n\n // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════\n\n /**\n * @notice Returns earned and claimed tips for the actor.\n * Note: Tips for address(0) belong to the Treasury.\n * @param actor Address of the actor\n * @param origin Domain where the tips were initially paid\n * @return earned Total amount of origin tips the actor has earned so far\n * @return claimed Total amount of origin tips the actor has claimed so far\n */\n function actorTips(address actor, uint32 origin) external view returns (uint128 earned, uint128 claimed);\n\n /**\n * @notice Returns the amount of receipts in the \"Receipt Quarantine Queue\".\n */\n function receiptQueueLength() external view returns (uint256);\n\n /**\n * @notice Returns the state with the highest known nonce\n * submitted by any of the currently active Guards.\n * @param origin Domain of origin chain\n * @return statePayload Raw payload with latest active Guard state for origin\n */\n function getLatestState(uint32 origin) external view returns (bytes memory statePayload);\n}\n\n// node_modules/@openzeppelin/contracts/utils/Strings.sol\n\n// OpenZeppelin Contracts (last updated v4.9.0) (utils/Strings.sol)\n\n/**\n * @dev String operations.\n */\nlibrary Strings {\n bytes16 private constant _SYMBOLS = \"0123456789abcdef\";\n uint8 private constant _ADDRESS_LENGTH = 20;\n\n /**\n * @dev Converts a `uint256` to its ASCII `string` decimal representation.\n */\n function toString(uint256 value) internal pure returns (string memory) {\n unchecked {\n uint256 length = Math.log10(value) + 1;\n string memory buffer = new string(length);\n uint256 ptr;\n /// @solidity memory-safe-assembly\n assembly {\n ptr := add(buffer, add(32, length))\n }\n while (true) {\n ptr--;\n /// @solidity memory-safe-assembly\n assembly {\n mstore8(ptr, byte(mod(value, 10), _SYMBOLS))\n }\n value /= 10;\n if (value == 0) break;\n }\n return buffer;\n }\n }\n\n /**\n * @dev Converts a `int256` to its ASCII `string` decimal representation.\n */\n function toString(int256 value) internal pure returns (string memory) {\n return string(abi.encodePacked(value \u003c 0 ? \"-\" : \"\", toString(SignedMath.abs(value))));\n }\n\n /**\n * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation.\n */\n function toHexString(uint256 value) internal pure returns (string memory) {\n unchecked {\n return toHexString(value, Math.log256(value) + 1);\n }\n }\n\n /**\n * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length.\n */\n function toHexString(uint256 value, uint256 length) internal pure returns (string memory) {\n bytes memory buffer = new bytes(2 * length + 2);\n buffer[0] = \"0\";\n buffer[1] = \"x\";\n for (uint256 i = 2 * length + 1; i \u003e 1; --i) {\n buffer[i] = _SYMBOLS[value \u0026 0xf];\n value \u003e\u003e= 4;\n }\n require(value == 0, \"Strings: hex length insufficient\");\n return string(buffer);\n }\n\n /**\n * @dev Converts an `address` with fixed length of 20 bytes to its not checksummed ASCII `string` hexadecimal representation.\n */\n function toHexString(address addr) internal pure returns (string memory) {\n return toHexString(uint256(uint160(addr)), _ADDRESS_LENGTH);\n }\n\n /**\n * @dev Returns true if the two strings are equal.\n */\n function equal(string memory a, string memory b) internal pure returns (bool) {\n return keccak256(bytes(a)) == keccak256(bytes(b));\n }\n}\n\n// node_modules/@openzeppelin/contracts-upgradeable/utils/ContextUpgradeable.sol\n\n// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)\n\n/**\n * @dev Provides information about the current execution context, including the\n * sender of the transaction and its data. While these are generally available\n * via msg.sender and msg.data, they should not be accessed in such a direct\n * manner, since when dealing with meta-transactions the account sending and\n * paying for execution may not be the actual sender (as far as an application\n * is concerned).\n *\n * This contract is only required for intermediate, library-like contracts.\n */\nabstract contract ContextUpgradeable is Initializable {\n function __Context_init() internal onlyInitializing {\n }\n\n function __Context_init_unchained() internal onlyInitializing {\n }\n function _msgSender() internal view virtual returns (address) {\n return msg.sender;\n }\n\n function _msgData() internal view virtual returns (bytes calldata) {\n return msg.data;\n }\n\n /**\n * @dev This empty reserved space is put in place to allow future versions to add new\n * variables without shifting down storage in the inheritance chain.\n * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\n */\n uint256[50] private __gap;\n}\n\n// contracts/libs/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/utils/cryptography/ECDSA.sol\n\n// OpenZeppelin Contracts (last updated v4.9.0) (utils/cryptography/ECDSA.sol)\n\n/**\n * @dev Elliptic Curve Digital Signature Algorithm (ECDSA) operations.\n *\n * These functions can be used to verify that a message was signed by the holder\n * of the private keys of a given address.\n */\nlibrary ECDSA {\n enum RecoverError {\n NoError,\n InvalidSignature,\n InvalidSignatureLength,\n InvalidSignatureS,\n InvalidSignatureV // Deprecated in v4.8\n }\n\n function _throwError(RecoverError error) private pure {\n if (error == RecoverError.NoError) {\n return; // no error: do nothing\n } else if (error == RecoverError.InvalidSignature) {\n revert(\"ECDSA: invalid signature\");\n } else if (error == RecoverError.InvalidSignatureLength) {\n revert(\"ECDSA: invalid signature length\");\n } else if (error == RecoverError.InvalidSignatureS) {\n revert(\"ECDSA: invalid signature 's' value\");\n }\n }\n\n /**\n * @dev Returns the address that signed a hashed message (`hash`) with\n * `signature` or error string. This address can then be used for verification purposes.\n *\n * The `ecrecover` EVM opcode allows for malleable (non-unique) signatures:\n * this function rejects them by requiring the `s` value to be in the lower\n * half order, and the `v` value to be either 27 or 28.\n *\n * IMPORTANT: `hash` _must_ be the result of a hash operation for the\n * verification to be secure: it is possible to craft signatures that\n * recover to arbitrary addresses for non-hashed data. A safe way to ensure\n * this is by receiving a hash of the original message (which may otherwise\n * be too long), and then calling {toEthSignedMessageHash} on it.\n *\n * Documentation for signature generation:\n * - with https://web3js.readthedocs.io/en/v1.3.4/web3-eth-accounts.html#sign[Web3.js]\n * - with https://docs.ethers.io/v5/api/signer/#Signer-signMessage[ethers]\n *\n * _Available since v4.3._\n */\n function tryRecover(bytes32 hash, bytes memory signature) internal pure returns (address, RecoverError) {\n if (signature.length == 65) {\n bytes32 r;\n bytes32 s;\n uint8 v;\n // ecrecover takes the signature parameters, and the only way to get them\n // currently is to use assembly.\n /// @solidity memory-safe-assembly\n assembly {\n r := mload(add(signature, 0x20))\n s := mload(add(signature, 0x40))\n v := byte(0, mload(add(signature, 0x60)))\n }\n return tryRecover(hash, v, r, s);\n } else {\n return (address(0), RecoverError.InvalidSignatureLength);\n }\n }\n\n /**\n * @dev Returns the address that signed a hashed message (`hash`) with\n * `signature`. This address can then be used for verification purposes.\n *\n * The `ecrecover` EVM opcode allows for malleable (non-unique) signatures:\n * this function rejects them by requiring the `s` value to be in the lower\n * half order, and the `v` value to be either 27 or 28.\n *\n * IMPORTANT: `hash` _must_ be the result of a hash operation for the\n * verification to be secure: it is possible to craft signatures that\n * recover to arbitrary addresses for non-hashed data. A safe way to ensure\n * this is by receiving a hash of the original message (which may otherwise\n * be too long), and then calling {toEthSignedMessageHash} on it.\n */\n function recover(bytes32 hash, bytes memory signature) internal pure returns (address) {\n (address recovered, RecoverError error) = tryRecover(hash, signature);\n _throwError(error);\n return recovered;\n }\n\n /**\n * @dev Overload of {ECDSA-tryRecover} that receives the `r` and `vs` short-signature fields separately.\n *\n * See https://eips.ethereum.org/EIPS/eip-2098[EIP-2098 short signatures]\n *\n * _Available since v4.3._\n */\n function tryRecover(bytes32 hash, bytes32 r, bytes32 vs) internal pure returns (address, RecoverError) {\n bytes32 s = vs \u0026 bytes32(0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff);\n uint8 v = uint8((uint256(vs) \u003e\u003e 255) + 27);\n return tryRecover(hash, v, r, s);\n }\n\n /**\n * @dev Overload of {ECDSA-recover} that receives the `r and `vs` short-signature fields separately.\n *\n * _Available since v4.2._\n */\n function recover(bytes32 hash, bytes32 r, bytes32 vs) internal pure returns (address) {\n (address recovered, RecoverError error) = tryRecover(hash, r, vs);\n _throwError(error);\n return recovered;\n }\n\n /**\n * @dev Overload of {ECDSA-tryRecover} that receives the `v`,\n * `r` and `s` signature fields separately.\n *\n * _Available since v4.3._\n */\n function tryRecover(bytes32 hash, uint8 v, bytes32 r, bytes32 s) internal pure returns (address, RecoverError) {\n // EIP-2 still allows signature malleability for ecrecover(). Remove this possibility and make the signature\n // unique. Appendix F in the Ethereum Yellow paper (https://ethereum.github.io/yellowpaper/paper.pdf), defines\n // the valid range for s in (301): 0 \u003c s \u003c secp256k1n ÷ 2 + 1, and for v in (302): v ∈ {27, 28}. Most\n // signatures from current libraries generate a unique signature with an s-value in the lower half order.\n //\n // If your library generates malleable signatures, such as s-values in the upper range, calculate a new s-value\n // with 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141 - s1 and flip v from 27 to 28 or\n // vice versa. If your library also generates signatures with 0/1 for v instead 27/28, add 27 to v to accept\n // these malleable signatures as well.\n if (uint256(s) \u003e 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0) {\n return (address(0), RecoverError.InvalidSignatureS);\n }\n\n // If the signature is valid (and not malleable), return the signer address\n address signer = ecrecover(hash, v, r, s);\n if (signer == address(0)) {\n return (address(0), RecoverError.InvalidSignature);\n }\n\n return (signer, RecoverError.NoError);\n }\n\n /**\n * @dev Overload of {ECDSA-recover} that receives the `v`,\n * `r` and `s` signature fields separately.\n */\n function recover(bytes32 hash, uint8 v, bytes32 r, bytes32 s) internal pure returns (address) {\n (address recovered, RecoverError error) = tryRecover(hash, v, r, s);\n _throwError(error);\n return recovered;\n }\n\n /**\n * @dev Returns an Ethereum Signed Message, created from a `hash`. This\n * produces hash corresponding to the one signed with the\n * https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`]\n * JSON-RPC method as part of EIP-191.\n *\n * See {recover}.\n */\n function toEthSignedMessageHash(bytes32 hash) internal pure returns (bytes32 message) {\n // 32 is the length in bytes of hash,\n // enforced by the type signature above\n /// @solidity memory-safe-assembly\n assembly {\n mstore(0x00, \"\\x19Ethereum Signed Message:\\n32\")\n mstore(0x1c, hash)\n message := keccak256(0x00, 0x3c)\n }\n }\n\n /**\n * @dev Returns an Ethereum Signed Message, created from `s`. This\n * produces hash corresponding to the one signed with the\n * https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`]\n * JSON-RPC method as part of EIP-191.\n *\n * See {recover}.\n */\n function toEthSignedMessageHash(bytes memory s) internal pure returns (bytes32) {\n return keccak256(abi.encodePacked(\"\\x19Ethereum Signed Message:\\n\", Strings.toString(s.length), s));\n }\n\n /**\n * @dev Returns an Ethereum Signed Typed Data, created from a\n * `domainSeparator` and a `structHash`. This produces hash corresponding\n * to the one signed with the\n * https://eips.ethereum.org/EIPS/eip-712[`eth_signTypedData`]\n * JSON-RPC method as part of EIP-712.\n *\n * See {recover}.\n */\n function toTypedDataHash(bytes32 domainSeparator, bytes32 structHash) internal pure returns (bytes32 data) {\n /// @solidity memory-safe-assembly\n assembly {\n let ptr := mload(0x40)\n mstore(ptr, \"\\x19\\x01\")\n mstore(add(ptr, 0x02), domainSeparator)\n mstore(add(ptr, 0x22), structHash)\n data := keccak256(ptr, 0x42)\n }\n }\n\n /**\n * @dev Returns an Ethereum Signed Data with intended validator, created from a\n * `validator` and `data` according to the version 0 of EIP-191.\n *\n * See {recover}.\n */\n function toDataWithIntendedValidatorHash(address validator, bytes memory data) internal pure returns (bytes32) {\n return keccak256(abi.encodePacked(\"\\x19\\x00\", validator, data));\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/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/inbox/StatementInbox.sol\n\n// ══════════════════════════════ LIBRARY IMPORTS ══════════════════════════════\n\n// ═════════════════════════════ INTERNAL IMPORTS ══════════════════════════════\n\n// ═════════════════════════════ EXTERNAL IMPORTS ══════════════════════════════\n\n/// @notice `StatementInbox` is the entry point for all agent-signed statements. It verifies the\n/// agent signatures, and passes the unsigned statements to the contract to consume it via `acceptX` functions. Is is\n/// also used to verify the agent-signed statements and initiate the agent slashing, should the statement be invalid.\n/// `StatementInbox` is responsible for the following:\n/// - Accepting State and Receipt Reports to initiate a dispute between Guard and Notary.\n/// - Storing all the Guard Reports with the Guard signature leading to a dispute.\n/// - Verifying State/State Reports referencing the local chain and slashing the signer if statement is invalid.\n/// - Verifying Receipt/Receipt Reports referencing the local chain and slashing the signer if statement is invalid.\nabstract contract StatementInbox is MessagingBase, StatementInboxEvents, IStatementInbox {\n using AttestationLib for bytes;\n using ReceiptLib for bytes;\n using StateLib for bytes;\n using SnapshotLib for bytes;\n\n struct StoredReport {\n uint256 sigIndex;\n bytes statementPayload;\n }\n\n // ══════════════════════════════════════════════════ STORAGE ══════════════════════════════════════════════════════\n\n address public agentManager;\n address public origin;\n address public destination;\n\n // TODO: optimize this\n bytes[] internal _storedSignatures;\n StoredReport[] internal _storedReports;\n\n /// @dev gap for upgrade safety\n uint256[45] private __GAP; // solhint-disable-line var-name-mixedcase\n\n // ════════════════════════════════════════════════ INITIALIZER ════════════════════════════════════════════════════\n\n /// @dev Initializes the contract:\n /// - Sets up `msg.sender` as the owner of the contract.\n /// - Sets up `agentManager`, `origin`, and `destination`.\n // solhint-disable-next-line func-name-mixedcase\n function __StatementInbox_init(address agentManager_, address origin_, address destination_)\n internal\n onlyInitializing\n {\n agentManager = agentManager_;\n origin = origin_;\n destination = destination_;\n __Ownable2Step_init();\n }\n\n // ══════════════════════════════════════════ SUBMIT AGENT STATEMENTS ══════════════════════════════════════════════\n\n /// @inheritdoc IStatementInbox\n // solhint-disable-next-line ordering\n function submitStateReportWithSnapshot(\n uint8 stateIndex,\n bytes memory srSignature,\n bytes memory snapPayload,\n bytes memory snapSignature\n ) external returns (bool wasAccepted) {\n // This will revert if payload is not a snapshot\n Snapshot snapshot = snapPayload.castToSnapshot();\n // This will revert if the snapshot signer is not a known Notary\n (AgentStatus memory notaryStatus,) =\n _verifySnapshot({snapshot: snapshot, snapSignature: snapSignature, verifyNotary: true});\n // Notary needs to be Active/Unstaking\n notaryStatus.verifyActiveUnstaking();\n // Check if Notary is active on this chain\n _verifyNotaryDomain(notaryStatus.domain);\n // This will revert if state index is out of range\n State state = snapshot.state(stateIndex);\n // This will revert if the report signer is not an known Guard\n (AgentStatus memory guardStatus,) = _verifyStateReport(state, srSignature);\n // Check that Guard is active\n guardStatus.verifyActive();\n _saveReport(state.unwrap().clone(), srSignature);\n // This will revert if either actor is already in dispute\n IAgentManager(agentManager).openDispute(guardStatus.index, notaryStatus.index);\n return true;\n }\n\n /// @inheritdoc IStatementInbox\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 // This will revert if payload is not a snapshot\n Snapshot snapshot = snapPayload.castToSnapshot();\n // This will revert if state index is out of range\n State state = snapshot.state(stateIndex);\n // This will revert if the report signer is not an known Guard\n (AgentStatus memory guardStatus,) = _verifyStateReport(state, srSignature);\n // Check that Guard is active\n guardStatus.verifyActive();\n // This will revert if payload is not an attestation\n Attestation att = attPayload.castToAttestation();\n // This will revert if signer is not an known Notary\n (AgentStatus memory notaryStatus,) = _verifyAttestation(att, attSignature);\n // Notary needs to be Active/Unstaking\n notaryStatus.verifyActiveUnstaking();\n // Check if Notary is active on this chain\n _verifyNotaryDomain(notaryStatus.domain);\n if (snapshot.calculateRoot() != att.snapRoot()) revert IncorrectSnapshotRoot();\n _saveReport(state.unwrap().clone(), srSignature);\n // This will revert if either actor is already in dispute\n IAgentManager(agentManager).openDispute(guardStatus.index, notaryStatus.index);\n return true;\n }\n\n /// @inheritdoc IStatementInbox\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 // This will revert if payload is not a state\n State state = statePayload.castToState();\n // This will revert if the report signer is not an known Guard\n (AgentStatus memory guardStatus,) = _verifyStateReport(state, srSignature);\n // Check that Guard is active\n guardStatus.verifyActive();\n // This will revert if payload is not an attestation\n Attestation att = attPayload.castToAttestation();\n // This will revert if signer is not a known Notary\n (AgentStatus memory notaryStatus,) = _verifyAttestation(att, attSignature);\n // Notary needs to be Active/Unstaking\n notaryStatus.verifyActiveUnstaking();\n // Check if Notary is active on this chain\n _verifyNotaryDomain(notaryStatus.domain);\n // This will revert if any of these is true:\n // - Attestation root is not equal to Merkle Root derived from State and Snapshot Proof.\n // - Snapshot Proof's first element does not match the State metadata.\n // - Snapshot Proof length exceeds Snapshot tree Height.\n // - State index is out of range.\n _verifySnapshotMerkle(att, stateIndex, state, snapProof);\n _saveReport(statePayload, srSignature);\n // This will revert if either actor is already in dispute\n IAgentManager(agentManager).openDispute(guardStatus.index, notaryStatus.index);\n return true;\n }\n\n // ══════════════════════════════════════════ VERIFY AGENT STATEMENTS ══════════════════════════════════════════════\n\n /// @inheritdoc IStatementInbox\n function verifyReceipt(bytes memory rcptPayload, bytes memory rcptSignature)\n external\n returns (bool isValidReceipt)\n {\n // This will revert if payload is not a receipt\n Receipt rcpt = rcptPayload.castToReceipt();\n // This will revert if the attestation signer is not a known Notary\n (AgentStatus memory status, address notary) = _verifyReceipt(rcpt, rcptSignature);\n // Notary needs to be Active/Unstaking\n status.verifyActiveUnstaking();\n isValidReceipt = IExecutionHub(destination).isValidReceipt(rcptPayload);\n if (!isValidReceipt) {\n emit InvalidReceipt(rcptPayload, rcptSignature);\n IAgentManager(agentManager).slashAgent(status.domain, notary, msg.sender);\n }\n }\n\n /// @inheritdoc IStatementInbox\n function verifyReceiptReport(bytes memory rcptPayload, bytes memory rrSignature)\n external\n returns (bool isValidReport)\n {\n // This will revert if payload is not a receipt\n Receipt rcpt = rcptPayload.castToReceipt();\n // This will revert if the report signer is not a known Guard\n (AgentStatus memory status, address guard) = _verifyReceiptReport(rcpt, rrSignature);\n // Guard needs to be Active/Unstaking\n status.verifyActiveUnstaking();\n // Report is valid IF AND ONLY IF the reported receipt in invalid\n isValidReport = !IExecutionHub(destination).isValidReceipt(rcptPayload);\n if (!isValidReport) {\n emit InvalidReceiptReport(rcptPayload, rrSignature);\n IAgentManager(agentManager).slashAgent(status.domain, guard, msg.sender);\n }\n }\n\n /// @inheritdoc IStatementInbox\n function verifyStateWithAttestation(\n uint8 stateIndex,\n bytes memory snapPayload,\n bytes memory attPayload,\n bytes memory attSignature\n ) external returns (bool isValidState) {\n // This will revert if payload is not an attestation\n Attestation att = attPayload.castToAttestation();\n // This will revert if the attestation signer is not a known Notary\n (AgentStatus memory status, address notary) = _verifyAttestation(att, attSignature);\n // Notary needs to be Active/Unstaking\n status.verifyActiveUnstaking();\n // This will revert if payload is not a snapshot\n Snapshot snapshot = snapPayload.castToSnapshot();\n if (snapshot.calculateRoot() != att.snapRoot()) revert IncorrectSnapshotRoot();\n // This will revert if state does not refer to this chain\n bytes memory statePayload = snapshot.state(stateIndex).unwrap().clone();\n isValidState = IStateHub(origin).isValidState(statePayload);\n if (!isValidState) {\n emit InvalidStateWithAttestation(stateIndex, statePayload, attPayload, attSignature);\n IAgentManager(agentManager).slashAgent(status.domain, notary, msg.sender);\n }\n }\n\n /// @inheritdoc IStatementInbox\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 // This will revert if payload is not an attestation\n Attestation att = attPayload.castToAttestation();\n // This will revert if the attestation signer is not a known Notary\n (AgentStatus memory status, address notary) = _verifyAttestation(att, attSignature);\n // Notary needs to be Active/Unstaking\n status.verifyActiveUnstaking();\n // This will revert if payload is not a state\n State state = statePayload.castToState();\n // This will revert if any of these is true:\n // - Attestation root is not equal to Merkle Root derived from State and Snapshot Proof.\n // - Snapshot Proof's first element does not match the State metadata.\n // - Snapshot Proof length exceeds Snapshot tree Height.\n // - State index is out of range.\n _verifySnapshotMerkle(att, stateIndex, state, snapProof);\n // This will revert if state does not refer to this chain\n isValidState = IStateHub(origin).isValidState(statePayload);\n if (!isValidState) {\n emit InvalidStateWithAttestation(stateIndex, statePayload, attPayload, attSignature);\n IAgentManager(agentManager).slashAgent(status.domain, notary, msg.sender);\n }\n }\n\n /// @inheritdoc IStatementInbox\n function verifyStateWithSnapshot(uint8 stateIndex, bytes memory snapPayload, bytes memory snapSignature)\n external\n returns (bool isValidState)\n {\n // This will revert if payload is not a snapshot\n Snapshot snapshot = snapPayload.castToSnapshot();\n // This will revert if the snapshot signer is not a known Guard/Notary\n (AgentStatus memory status, address agent) =\n _verifySnapshot({snapshot: snapshot, snapSignature: snapSignature, verifyNotary: false});\n // Agent needs to be Active/Unstaking\n status.verifyActiveUnstaking();\n // This will revert if state does not refer to this chain\n isValidState = IStateHub(origin).isValidState(snapshot.state(stateIndex).unwrap().clone());\n if (!isValidState) {\n emit InvalidStateWithSnapshot(stateIndex, snapPayload, snapSignature);\n IAgentManager(agentManager).slashAgent(status.domain, agent, msg.sender);\n }\n }\n\n /// @inheritdoc IStatementInbox\n function verifyStateReport(bytes memory statePayload, bytes memory srSignature)\n external\n returns (bool isValidReport)\n {\n // This will revert if payload is not a state\n State state = statePayload.castToState();\n // This will revert if the report signer is not a known Guard\n (AgentStatus memory status, address guard) = _verifyStateReport(state, srSignature);\n // Guard needs to be Active/Unstaking\n status.verifyActiveUnstaking();\n // Report is valid IF AND ONLY IF the reported state in invalid\n // This will revert if the reported state does not refer to this chain\n isValidReport = !IStateHub(origin).isValidState(statePayload);\n if (!isValidReport) {\n emit InvalidStateReport(statePayload, srSignature);\n IAgentManager(agentManager).slashAgent(status.domain, guard, msg.sender);\n }\n }\n\n // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════\n\n /// @inheritdoc IStatementInbox\n function getReportsAmount() external view returns (uint256) {\n return _storedReports.length;\n }\n\n /// @inheritdoc IStatementInbox\n function getGuardReport(uint256 index)\n external\n view\n returns (bytes memory statementPayload, bytes memory reportSignature)\n {\n if (index \u003e= _storedReports.length) revert IndexOutOfRange();\n StoredReport memory storedReport = _storedReports[index];\n statementPayload = storedReport.statementPayload;\n reportSignature = _storedSignatures[storedReport.sigIndex];\n }\n\n /// @inheritdoc IStatementInbox\n function getStoredSignature(uint256 index) external view returns (bytes memory) {\n return _storedSignatures[index];\n }\n\n // ══════════════════════════════════════════════ INTERNAL LOGIC ═══════════════════════════════════════════════════\n\n /// @dev Saves the statement reported by Guard as invalid and the Guard Report signature.\n function _saveReport(bytes memory statementPayload, bytes memory reportSignature) internal {\n uint256 sigIndex = _saveSignature(reportSignature);\n _storedReports.push(StoredReport(sigIndex, statementPayload));\n }\n\n /// @dev Saves the signature and returns its index.\n function _saveSignature(bytes memory signature) internal returns (uint256 sigIndex) {\n sigIndex = _storedSignatures.length;\n _storedSignatures.push(signature);\n }\n\n // ═══════════════════════════════════════════════ AGENT CHECKS ════════════════════════════════════════════════════\n\n /**\n * @dev Recovers a signer from a hashed message, and a EIP-191 signature for it.\n * Will revert, if the signer is not a known agent.\n * @dev Agent flag could be any of these: Active/Unstaking/Resting/Fraudulent/Slashed\n * Further checks need to be performed in a caller function.\n * @param hashedStatement Hash of the statement that was signed by an Agent\n * @param signature Agent signature for the hashed statement\n * @return status Struct representing agent status:\n * - flag Unknown/Active/Unstaking/Resting/Fraudulent/Slashed\n * - domain Domain where agent is/was active\n * - index Index of agent in the Agent Merkle Tree\n * @return agent Agent that signed the statement\n */\n function _recoverAgent(bytes32 hashedStatement, bytes memory signature)\n internal\n view\n returns (AgentStatus memory status, address agent)\n {\n bytes32 ethSignedMsg = ECDSA.toEthSignedMessageHash(hashedStatement);\n agent = ECDSA.recover(ethSignedMsg, signature);\n status = IAgentManager(agentManager).agentStatus(agent);\n // Discard signature of unknown agents.\n // Further flag checks are supposed to be performed in a caller function.\n status.verifyKnown();\n }\n\n /// @dev Verifies that Notary signature is active on local domain.\n function _verifyNotaryDomain(uint32 notaryDomain) internal view {\n // Notary needs to be from the local domain (if contract is not deployed on Synapse Chain).\n // Or Notary could be from any domain (if contract is deployed on Synapse Chain).\n if (notaryDomain != localDomain \u0026\u0026 localDomain != synapseDomain) revert IncorrectAgentDomain();\n }\n\n // ════════════════════════════════════════ ATTESTATION RELATED CHECKS ═════════════════════════════════════════════\n\n /**\n * @dev Internal function to verify the signed attestation payload.\n * Reverts if any of these is true:\n * - Attestation signer is not a known Notary.\n * @param att Typed memory view over attestation payload\n * @param attSignature Notary signature for the attestation\n * @return status Struct representing agent status, see {_recoverAgent}\n * @return notary Notary that signed the snapshot\n */\n function _verifyAttestation(Attestation att, bytes memory attSignature)\n internal\n view\n returns (AgentStatus memory status, address notary)\n {\n // This will revert if signer is not a known agent\n (status, notary) = _recoverAgent(att.hashValid(), attSignature);\n // Attestation signer needs to be a Notary, not a Guard\n if (status.domain == 0) revert AgentNotNotary();\n }\n\n /**\n * @dev Internal function to verify the signed attestation report payload.\n * Reverts if any of these is true:\n * - Report signer is not a known Guard.\n * @param att Typed memory view over attestation payload that Guard reports as invalid\n * @param arSignature Guard signature for the \"invalid attestation\" report\n * @return status Struct representing guard status, see {_recoverAgent}\n * @return guard Guard that signed the report\n */\n function _verifyAttestationReport(Attestation att, bytes memory arSignature)\n internal\n view\n returns (AgentStatus memory status, address guard)\n {\n // This will revert if signer is not a known agent\n (status, guard) = _recoverAgent(att.hashInvalid(), arSignature);\n // Report signer needs to be a Guard, not a Notary\n if (status.domain != 0) revert AgentNotGuard();\n }\n\n // ══════════════════════════════════════════ RECEIPT RELATED CHECKS ═══════════════════════════════════════════════\n\n /**\n * @dev Internal function to verify the signed receipt payload.\n * Reverts if any of these is true:\n * - Receipt signer is not a known Notary.\n * @param rcpt Typed memory view over receipt payload\n * @param rcptSignature Notary signature for the receipt\n * @return status Struct representing agent status, see {_recoverAgent}\n * @return notary Notary that signed the snapshot\n */\n function _verifyReceipt(Receipt rcpt, bytes memory rcptSignature)\n internal\n view\n returns (AgentStatus memory status, address notary)\n {\n // This will revert if signer is not a known agent\n (status, notary) = _recoverAgent(rcpt.hashValid(), rcptSignature);\n // Receipt signer needs to be a Notary, not a Guard\n if (status.domain == 0) revert AgentNotNotary();\n }\n\n /**\n * @dev Internal function to verify the signed receipt report payload.\n * Reverts if any of these is true:\n * - Report signer is not a known Guard.\n * @param rcpt Typed memory view over receipt payload that Guard reports as invalid\n * @param rrSignature Guard signature for the \"invalid receipt\" report\n * @return status Struct representing guard status, see {_recoverAgent}\n * @return guard Guard that signed the report\n */\n function _verifyReceiptReport(Receipt rcpt, bytes memory rrSignature)\n internal\n view\n returns (AgentStatus memory status, address guard)\n {\n // This will revert if signer is not a known agent\n (status, guard) = _recoverAgent(rcpt.hashInvalid(), rrSignature);\n // Report signer needs to be a Guard, not a Notary\n if (status.domain != 0) revert AgentNotGuard();\n }\n\n // ═══════════════════════════════════════ STATE/SNAPSHOT RELATED CHECKS ═══════════════════════════════════════════\n\n /**\n * @dev Internal function to verify the signed snapshot report payload.\n * Reverts if any of these is true:\n * - Report signer is not a known Guard.\n * @param state Typed memory view over state payload that Guard reports as invalid\n * @param srSignature Guard signature for the report\n * @return status Struct representing guard status, see {_recoverAgent}\n * @return guard Guard that signed the report\n */\n function _verifyStateReport(State state, bytes memory srSignature)\n internal\n view\n returns (AgentStatus memory status, address guard)\n {\n // This will revert if signer is not a known agent\n (status, guard) = _recoverAgent(state.hashInvalid(), srSignature);\n // Report signer needs to be a Guard, not a Notary\n if (status.domain != 0) revert AgentNotGuard();\n }\n\n /**\n * @dev Internal function to verify the signed snapshot payload.\n * Reverts if any of these is true:\n * - Snapshot signer is not a known Agent.\n * - Snapshot signer is not a Notary (if verifyNotary is true).\n * @param snapshot Typed memory view over snapshot payload\n * @param snapSignature Agent signature for the snapshot\n * @param verifyNotary If true, snapshot signer needs to be a Notary, not a Guard\n * @return status Struct representing agent status, see {_recoverAgent}\n * @return agent Agent that signed the snapshot\n */\n function _verifySnapshot(Snapshot snapshot, bytes memory snapSignature, bool verifyNotary)\n internal\n view\n returns (AgentStatus memory status, address agent)\n {\n // This will revert if signer is not a known agent\n (status, agent) = _recoverAgent(snapshot.hashValid(), snapSignature);\n // If requested, snapshot signer needs to be a Notary, not a Guard\n if (verifyNotary \u0026\u0026 status.domain == 0) revert AgentNotNotary();\n }\n\n // ═══════════════════════════════════════════ MERKLE RELATED CHECKS ═══════════════════════════════════════════════\n\n /**\n * @dev Internal function to verify that snapshot roots match.\n * Reverts if any of these is true:\n * - Attestation root is not equal to Merkle Root derived from State and Snapshot Proof.\n * - Snapshot Proof's first element does not match the State metadata.\n * - Snapshot Proof length exceeds Snapshot tree Height.\n * - State index is out of range.\n * @param att Typed memory view over Attestation\n * @param stateIndex Index of state in the snapshot\n * @param state Typed memory view over the provided state payload\n * @param snapProof Raw payload with snapshot data\n */\n function _verifySnapshotMerkle(Attestation att, uint8 stateIndex, State state, bytes32[] memory snapProof)\n internal\n pure\n {\n // Snapshot proof first element should match State metadata (aka \"right sub-leaf\")\n (, bytes32 rightSubLeaf) = state.subLeafs();\n if (snapProof[0] != rightSubLeaf) revert IncorrectSnapshotProof();\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(state.root(), state.origin(), snapProof, stateIndex);\n // Snapshot root should match the attestation root\n if (att.snapRoot() != snapshotRoot) revert IncorrectSnapshotRoot();\n }\n}\n\n// contracts/inbox/Inbox.sol\n\n// ══════════════════════════════ LIBRARY IMPORTS ══════════════════════════════\n\n// ═════════════════════════════ INTERNAL IMPORTS ══════════════════════════════\n\n/// @notice `Inbox` is the child of `StatementInbox` contract, that is used on Synapse Chain.\n/// In addition to the functionality of `StatementInbox`, it also:\n/// - Accepts Guard and Notary Snapshots and passes them to `Summit` contract.\n/// - Accepts Notary-signed Receipts and passes them to `Summit` contract.\n/// - Accepts Receipt Reports to initiate a dispute between Guard and Notary.\n/// - Verifies Attestations and Attestation Reports, and slashes the signer if they are invalid.\ncontract Inbox is StatementInbox, InboxEvents, InterfaceInbox {\n using AttestationLib for bytes;\n using ReceiptLib for bytes;\n using SnapshotLib for bytes;\n\n // Struct to get around stack too deep error. TODO: revisit this\n struct ReceiptInfo {\n AgentStatus rcptNotaryStatus;\n address notary;\n uint32 attNonce;\n AgentStatus attNotaryStatus;\n }\n\n // ══════════════════════════════════════════════════ STORAGE ══════════════════════════════════════════════════════\n\n // The address of the Summit contract.\n address public summit;\n\n // ═════════════════════════════════════════ CONSTRUCTOR \u0026 INITIALIZER ═════════════════════════════════════════════\n\n constructor(uint32 synapseDomain_) MessagingBase(\"0.0.3\", synapseDomain_) {\n if (localDomain != synapseDomain) revert MustBeSynapseDomain();\n }\n\n /// @notice Initializes `Inbox` contract:\n /// - Sets `msg.sender` as the owner of the contract\n /// - Sets `agentManager`, `origin`, `destination` and `summit` addresses\n function initialize(address agentManager_, address origin_, address destination_, address summit_)\n external\n initializer\n {\n __StatementInbox_init(agentManager_, origin_, destination_);\n summit = summit_;\n }\n\n // ══════════════════════════════════════════ SUBMIT AGENT STATEMENTS ══════════════════════════════════════════════\n\n /// @inheritdoc InterfaceInbox\n function submitSnapshot(bytes memory snapPayload, bytes memory snapSignature)\n external\n returns (bytes memory attPayload, bytes32 agentRoot_, uint256[] memory snapGas)\n {\n // This will revert if payload is not a snapshot\n Snapshot snapshot = snapPayload.castToSnapshot();\n // This will revert if the signer is not a known Guard/Notary\n (AgentStatus memory status, address agent) =\n _verifySnapshot({snapshot: snapshot, snapSignature: snapSignature, verifyNotary: false});\n // Check that Agent is active\n status.verifyActive();\n // Store Agent signature for the Snapshot\n uint256 sigIndex = _saveSignature(snapSignature);\n if (status.domain == 0) {\n // Guard that is in Dispute could still submit new snapshots, so we don't check that\n InterfaceSummit(summit).acceptGuardSnapshot({\n guardIndex: status.index,\n sigIndex: sigIndex,\n snapPayload: snapPayload\n });\n } else {\n // Get current agentRoot from AgentManager\n agentRoot_ = IAgentManager(agentManager).agentRoot();\n // This will revert if Notary is in Dispute\n attPayload = InterfaceSummit(summit).acceptNotarySnapshot({\n notaryIndex: status.index,\n sigIndex: sigIndex,\n agentRoot: agentRoot_,\n snapPayload: snapPayload\n });\n ChainGas[] memory snapGas_ = snapshot.snapGas();\n // Pass created attestation to Destination to enable executing messages coming to Synapse Chain\n InterfaceDestination(destination).acceptAttestation(\n status.index, type(uint256).max, attPayload, agentRoot_, snapGas_\n );\n // Use assembly to cast ChainGas[] to uint256[] without copying. Highest bits are left zeroed.\n // solhint-disable-next-line no-inline-assembly\n assembly {\n snapGas := snapGas_\n }\n }\n emit SnapshotAccepted(status.domain, agent, snapPayload, snapSignature);\n }\n\n /// @inheritdoc InterfaceInbox\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 // Struct to get around stack too deep error.\n ReceiptInfo memory info;\n // This will revert if payload is not a receipt\n Receipt rcpt = rcptPayload.castToReceipt();\n // This will revert if the receipt signer is not a known Notary\n (info.rcptNotaryStatus, info.notary) = _verifyReceipt(rcpt, rcptSignature);\n // Receipt Notary needs to be Active\n info.rcptNotaryStatus.verifyActive();\n info.attNonce = IExecutionHub(destination).getAttestationNonce(rcpt.snapshotRoot());\n if (info.attNonce == 0) revert IncorrectSnapshotRoot();\n // Attestation Notary domain needs to match the destination domain\n info.attNotaryStatus = IAgentManager(agentManager).agentStatus(rcpt.attNotary());\n if (info.attNotaryStatus.domain != rcpt.destination()) revert IncorrectAgentDomain();\n // Check that the correct tip values for the message were provided\n _verifyReceiptTips(rcpt.messageHash(), paddedTips, headerHash, bodyHash);\n // Store Notary signature for the Receipt\n uint256 sigIndex = _saveSignature(rcptSignature);\n // This will revert if Receipt Notary is in Dispute\n wasAccepted = InterfaceSummit(summit).acceptReceipt({\n rcptNotaryIndex: info.rcptNotaryStatus.index,\n attNotaryIndex: info.attNotaryStatus.index,\n sigIndex: sigIndex,\n attNonce: info.attNonce,\n paddedTips: paddedTips,\n rcptPayload: rcptPayload\n });\n if (wasAccepted) {\n emit ReceiptAccepted(info.rcptNotaryStatus.domain, info.notary, rcptPayload, rcptSignature);\n }\n }\n\n /// @inheritdoc InterfaceInbox\n function submitReceiptReport(bytes memory rcptPayload, bytes memory rcptSignature, bytes memory rrSignature)\n external\n returns (bool wasAccepted)\n {\n // This will revert if payload is not a receipt\n Receipt rcpt = rcptPayload.castToReceipt();\n // This will revert if the receipt signer is not a known Guard\n (AgentStatus memory guardStatus,) = _verifyReceiptReport(rcpt, rrSignature);\n // Guard needs to be Active\n guardStatus.verifyActive();\n // This will revert if report signer is not a known Notary\n (AgentStatus memory notaryStatus,) = _verifyReceipt(rcpt, rcptSignature);\n // Notary needs to be Active/Unstaking\n notaryStatus.verifyActiveUnstaking();\n _saveReport(rcptPayload, rrSignature);\n // This will revert if either actor is already in dispute\n IAgentManager(agentManager).openDispute(guardStatus.index, notaryStatus.index);\n return true;\n }\n\n /// @inheritdoc InterfaceInbox\n function passReceipt(uint32 attNotaryIndex, uint32 attNonce, uint256 paddedTips, bytes memory rcptPayload)\n external\n returns (bool wasAccepted)\n {\n // Only Destination can pass receipts\n if (msg.sender != destination) revert CallerNotDestination();\n return InterfaceSummit(summit).acceptReceipt({\n rcptNotaryIndex: attNotaryIndex,\n attNotaryIndex: attNotaryIndex,\n sigIndex: type(uint256).max,\n attNonce: attNonce,\n paddedTips: paddedTips,\n rcptPayload: rcptPayload\n });\n }\n\n // ══════════════════════════════════════════ VERIFY AGENT STATEMENTS ══════════════════════════════════════════════\n\n /// @inheritdoc InterfaceInbox\n function verifyAttestation(bytes memory attPayload, bytes memory attSignature)\n external\n returns (bool isValidAttestation)\n {\n // This will revert if payload is not an attestation\n Attestation att = attPayload.castToAttestation();\n // This will revert if the attestation signer is not a known Notary\n (AgentStatus memory status, address notary) = _verifyAttestation(att, attSignature);\n // Notary needs to be Active/Unstaking\n status.verifyActiveUnstaking();\n isValidAttestation = ISnapshotHub(summit).isValidAttestation(attPayload);\n if (!isValidAttestation) {\n emit InvalidAttestation(attPayload, attSignature);\n IAgentManager(agentManager).slashAgent(status.domain, notary, msg.sender);\n }\n }\n\n /// @inheritdoc InterfaceInbox\n function verifyAttestationReport(bytes memory attPayload, bytes memory arSignature)\n external\n returns (bool isValidReport)\n {\n // This will revert if payload is not an attestation\n Attestation att = attPayload.castToAttestation();\n // This will revert if the report signer is not a known Guard\n (AgentStatus memory status, address guard) = _verifyAttestationReport(att, arSignature);\n // Guard needs to be Active/Unstaking\n status.verifyActiveUnstaking();\n // Report is valid IF AND ONLY IF the reported attestation in invalid\n isValidReport = !ISnapshotHub(summit).isValidAttestation(attPayload);\n if (!isValidReport) {\n emit InvalidAttestationReport(attPayload, arSignature);\n IAgentManager(agentManager).slashAgent(status.domain, guard, msg.sender);\n }\n }\n\n // ══════════════════════════════════════════════ INTERNAL VIEWS ═══════════════════════════════════════════════════\n\n /// @dev Verifies that tips proof matches the message hash.\n function _verifyReceiptTips(bytes32 msgHash, uint256 paddedTips, bytes32 headerHash, bytes32 bodyHash)\n internal\n pure\n {\n Tips tips = TipsLib.wrapPadded(paddedTips);\n // full message leaf is (header, baseMessage), while base message leaf is (tips, remainingBody).\n if (MerkleMath.getParent(headerHash, MerkleMath.getParent(tips.leaf(), bodyHash)) != msgHash) {\n revert IncorrectTipsProof();\n }\n }\n}\n","language":"Solidity","languageVersion":"0.8.17","compilerVersion":"0.8.17","compilerOptions":"--combined-json bin,bin-runtime,srcmap,srcmap-runtime,abi,userdoc,devdoc,metadata,hashes --optimize --optimize-runs 10000 --allow-paths ., ./, ../","srcMap":"","srcMapRuntime":"","abiDefinition":[{"inputs":[{"internalType":"bytes","name":"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/Inbox.sol\":\"IExecutionHub\"},\"evmVersion\":\"london\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\"},\"optimizer\":{\"enabled\":true,\"runs\":10000},\"remappings\":[]},\"sources\":{\"solidity/Inbox.sol\":{\"keccak256\":\"0x9b516081a036814c0169e20e484d4a5499066b7a6f48fada952b5e844a1ca3e5\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://32bde393b3f24ef4307d9626d4143f337b3c0bd34e17bb969fd5a15221d96987\",\"dweb:/ipfs/QmTkt2XZRtgsbSpmsVQUM3c4ebETQoDVYbmEV9yheBghnr\"]}},\"version\":1}"},"hashes":{"execute(bytes,bytes32[],bytes32[],uint8,uint64)":"883099bc","getAttestationNonce(bytes32)":"4f127567","isValidReceipt(bytes)":"e2f006f7","messageReceipt(bytes32)":"daa74a9e","messageStatus(bytes32)":"3c6cf473"}},"solidity/Inbox.sol:ISnapshotHub":{"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/InboxEvents.sol\n\nabstract contract InboxEvents {\n /**\n * @notice Emitted when a snapshot is accepted by the Summit contract.\n * @param domain Domain where the signed Agent is active (ZERO for Guards)\n * @param agent Agent who signed the snapshot\n * @param snapPayload Raw payload with snapshot data\n * @param snapSignature Agent signature for the snapshot\n */\n event SnapshotAccepted(uint32 indexed domain, address indexed agent, bytes snapPayload, bytes snapSignature);\n\n /**\n * @notice Emitted when a snapshot is accepted by the Summit contract.\n * @param domain Domain where the signed Notary is active\n * @param notary Notary who signed the attestation\n * @param rcptPayload Raw payload with receipt data\n * @param rcptSignature Notary signature for the receipt\n */\n event ReceiptAccepted(uint32 domain, address notary, bytes rcptPayload, bytes rcptSignature);\n\n /**\n * @notice Emitted when a proof of invalid attestation is submitted.\n * @param attPayload Raw payload with Attestation data\n * @param attSignature Notary signature for the attestation\n */\n event InvalidAttestation(bytes attPayload, bytes attSignature);\n\n /**\n * @notice Emitted when a proof of invalid attestation report is submitted.\n * @param arPayload Raw payload with report data\n * @param arSignature Guard signature for the report\n */\n event InvalidAttestationReport(bytes arPayload, bytes arSignature);\n}\n\n// contracts/events/StatementInboxEvents.sol\n\nabstract contract StatementInboxEvents {\n // ════════════════════════════════════════════ STATEMENT ACCEPTED ═════════════════════════════════════════════════\n\n /**\n * @notice Emitted when a snapshot is accepted by the Destination contract.\n * @param domain Domain where the signed Notary is active\n * @param notary Notary who signed the attestation\n * @param attPayload Raw payload with attestation data\n * @param attSignature Notary signature for the attestation\n */\n event AttestationAccepted(uint32 domain, address notary, bytes attPayload, bytes attSignature);\n\n // ═════════════════════════════════════════ INVALID STATEMENT PROVED ══════════════════════════════════════════════\n\n /**\n * @notice Emitted when a proof of invalid receipt statement is submitted.\n * @param rcptPayload Raw payload with the receipt statement\n * @param rcptSignature Notary signature for the receipt statement\n */\n event InvalidReceipt(bytes rcptPayload, bytes rcptSignature);\n\n /**\n * @notice Emitted when a proof of invalid receipt report is submitted.\n * @param rrPayload Raw payload with report data\n * @param rrSignature Guard signature for the report\n */\n event InvalidReceiptReport(bytes rrPayload, bytes rrSignature);\n\n /**\n * @notice Emitted when a proof of invalid state in the signed attestation is submitted.\n * @param stateIndex Index of invalid state in the snapshot\n * @param statePayload Raw payload with state data\n * @param attPayload Raw payload with Attestation data for snapshot\n * @param attSignature Notary signature for the attestation\n */\n event InvalidStateWithAttestation(uint8 stateIndex, bytes statePayload, bytes attPayload, bytes attSignature);\n\n /**\n * @notice Emitted when a proof of invalid state in the signed snapshot is submitted.\n * @param stateIndex Index of invalid state in the snapshot\n * @param snapPayload Raw payload with snapshot data\n * @param snapSignature Agent signature for the snapshot\n */\n event InvalidStateWithSnapshot(uint8 stateIndex, bytes snapPayload, bytes snapSignature);\n\n /**\n * @notice Emitted when a proof of invalid state report is submitted.\n * @param srPayload Raw payload with report data\n * @param srSignature Guard signature for the report\n */\n event InvalidStateReport(bytes srPayload, bytes srSignature);\n}\n\n// contracts/interfaces/ISnapshotHub.sol\n\ninterface ISnapshotHub {\n /**\n * @notice Check that a given attestation is valid: matches the historical attestation\n * derived from an accepted Notary snapshot.\n * @dev Will revert if any of these is true:\n * - Attestation payload is not properly formatted.\n * @param attPayload Raw payload with attestation data\n * @return isValid Whether the provided attestation is valid\n */\n function isValidAttestation(bytes memory attPayload) external view returns (bool isValid);\n\n /**\n * @notice Returns saved attestation with the given nonce.\n * @dev Reverts if attestation with given nonce hasn't been created yet.\n * @param attNonce Nonce for the attestation\n * @return attPayload Raw payload with formatted Attestation data\n * @return agentRoot Agent root hash used for the attestation\n * @return snapGas Snapshot gas data used for the attestation\n */\n function getAttestation(uint32 attNonce)\n external\n view\n returns (bytes memory attPayload, bytes32 agentRoot, uint256[] memory snapGas);\n\n /**\n * @notice Returns the state with the highest known nonce submitted by a given Agent.\n * @param origin Domain of origin chain\n * @param agent Agent address\n * @return statePayload Raw payload with agent's latest state for origin\n */\n function getLatestAgentState(uint32 origin, address agent) external view returns (bytes memory statePayload);\n\n /**\n * @notice Returns latest saved attestation for a Notary.\n * @param notary Notary address\n * @return attPayload Raw payload with formatted Attestation data\n * @return agentRoot Agent root hash used for the attestation\n * @return snapGas Snapshot gas data used for the attestation\n */\n function getLatestNotaryAttestation(address notary)\n external\n view\n returns (bytes memory attPayload, bytes32 agentRoot, uint256[] memory snapGas);\n\n /**\n * @notice Returns Guard snapshot from the list of all accepted Guard snapshots.\n * @dev Reverts if snapshot with given index hasn't been accepted yet.\n * @param index Snapshot index in the list of all Guard snapshots\n * @return snapPayload Raw payload with Guard snapshot\n * @return snapSignature Raw payload with Guard signature for snapshot\n */\n function getGuardSnapshot(uint256 index)\n external\n view\n returns (bytes memory snapPayload, bytes memory snapSignature);\n\n /**\n * @notice Returns Notary snapshot from the list of all accepted Guard snapshots.\n * @dev Reverts if snapshot with given index hasn't been accepted yet.\n * @param index Snapshot index in the list of all Notary snapshots\n * @return snapPayload Raw payload with Notary snapshot\n * @return snapSignature Raw payload with Notary signature for snapshot\n */\n function getNotarySnapshot(uint256 index)\n external\n view\n returns (bytes memory snapPayload, bytes memory snapSignature);\n\n /**\n * @notice Returns Notary snapshot that was used for creating a given attestation.\n * @dev Reverts if any of these is true:\n * - Attestation payload is not properly formatted.\n * - Attestation is invalid (doesn't have a matching Notary snapshot).\n * @param attPayload Raw payload with attestation data\n * @return snapPayload Raw payload with Notary snapshot\n * @return snapSignature Raw payload with Notary signature for snapshot\n */\n function getNotarySnapshot(bytes memory attPayload)\n external\n view\n returns (bytes memory snapPayload, bytes memory snapSignature);\n\n /**\n * @notice Returns proof of inclusion of (root, origin) fields of a given snapshot's state\n * into the Snapshot Merkle Tree for a given attestation.\n * @dev Reverts if any of these is true:\n * - Attestation with given nonce hasn't been created yet.\n * - State index is out of range of snapshot list.\n * @param attNonce Nonce for the attestation\n * @param stateIndex Index of state in the attestation's snapshot\n * @return snapProof The snapshot proof\n */\n function getSnapshotProof(uint32 attNonce, uint8 stateIndex) external view returns (bytes32[] memory snapProof);\n}\n\n// contracts/interfaces/IStateHub.sol\n\ninterface IStateHub {\n /**\n * @notice Check that a given state is valid: matches the historical state of Origin contract.\n * Note: any Agent including an invalid state in their snapshot will be slashed\n * upon providing the snapshot and agent signature for it to Origin contract.\n * @dev Will revert if any of these is true:\n * - State payload is not properly formatted.\n * @param statePayload Raw payload with state data\n * @return isValid Whether the provided state is valid\n */\n function isValidState(bytes memory statePayload) external view returns (bool isValid);\n\n /**\n * @notice Returns the amount of saved states so far.\n * @dev This includes the initial state of \"empty Origin Merkle Tree\".\n */\n function statesAmount() external view returns (uint256);\n\n /**\n * @notice Suggest the data (state after latest sent message) to sign for an Agent.\n * Note: signing the suggested state data will will never lead to slashing of the actor,\n * assuming they have confirmed that the block, which number is included in the data,\n * is not subject to reorganization (which is different for every observed chain).\n * @return statePayload Raw payload with the latest state data\n */\n function suggestLatestState() external view returns (bytes memory statePayload);\n\n /**\n * @notice Given the historical nonce, suggest the state data to sign for an Agent.\n * Note: signing the suggested state data will will never lead to slashing of the actor,\n * assuming they have confirmed that the block, which number is included in the data,\n * is not subject to reorganization (which is different for every observed chain).\n * @param nonce Historical nonce to form a state\n * @return statePayload Raw payload with historical state data\n */\n function suggestState(uint32 nonce) external view returns (bytes memory statePayload);\n}\n\n// contracts/interfaces/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/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// node_modules/@openzeppelin/contracts/utils/math/Math.sol\n\n// OpenZeppelin Contracts (last updated v4.9.0) (utils/math/Math.sol)\n\n/**\n * @dev Standard math utilities missing in the Solidity language.\n */\nlibrary Math {\n enum Rounding {\n Down, // Toward negative infinity\n Up, // Toward infinity\n Zero // Toward zero\n }\n\n /**\n * @dev Returns the largest of two numbers.\n */\n function max(uint256 a, uint256 b) internal pure returns (uint256) {\n return a \u003e b ? a : b;\n }\n\n /**\n * @dev Returns the smallest of two numbers.\n */\n function min(uint256 a, uint256 b) internal pure returns (uint256) {\n return a \u003c b ? a : b;\n }\n\n /**\n * @dev Returns the average of two numbers. The result is rounded towards\n * zero.\n */\n function average(uint256 a, uint256 b) internal pure returns (uint256) {\n // (a + b) / 2 can overflow.\n return (a \u0026 b) + (a ^ b) / 2;\n }\n\n /**\n * @dev Returns the ceiling of the division of two numbers.\n *\n * This differs from standard division with `/` in that it rounds up instead\n * of rounding down.\n */\n function ceilDiv(uint256 a, uint256 b) internal pure returns (uint256) {\n // (a + b - 1) / b can overflow on addition, so we distribute.\n return a == 0 ? 0 : (a - 1) / b + 1;\n }\n\n /**\n * @notice Calculates floor(x * y / denominator) with full precision. Throws if result overflows a uint256 or denominator == 0\n * @dev Original credit to Remco Bloemen under MIT license (https://xn--2-umb.com/21/muldiv)\n * with further edits by Uniswap Labs also under MIT license.\n */\n function mulDiv(uint256 x, uint256 y, uint256 denominator) internal pure returns (uint256 result) {\n unchecked {\n // 512-bit multiply [prod1 prod0] = x * y. Compute the product mod 2^256 and mod 2^256 - 1, then use\n // use the Chinese Remainder Theorem to reconstruct the 512 bit result. The result is stored in two 256\n // variables such that product = prod1 * 2^256 + prod0.\n uint256 prod0; // Least significant 256 bits of the product\n uint256 prod1; // Most significant 256 bits of the product\n assembly {\n let mm := mulmod(x, y, not(0))\n prod0 := mul(x, y)\n prod1 := sub(sub(mm, prod0), lt(mm, prod0))\n }\n\n // Handle non-overflow cases, 256 by 256 division.\n if (prod1 == 0) {\n // Solidity will revert if denominator == 0, unlike the div opcode on its own.\n // The surrounding unchecked block does not change this fact.\n // See https://docs.soliditylang.org/en/latest/control-structures.html#checked-or-unchecked-arithmetic.\n return prod0 / denominator;\n }\n\n // Make sure the result is less than 2^256. Also prevents denominator == 0.\n require(denominator \u003e prod1, \"Math: mulDiv overflow\");\n\n ///////////////////////////////////////////////\n // 512 by 256 division.\n ///////////////////////////////////////////////\n\n // Make division exact by subtracting the remainder from [prod1 prod0].\n uint256 remainder;\n assembly {\n // Compute remainder using mulmod.\n remainder := mulmod(x, y, denominator)\n\n // Subtract 256 bit number from 512 bit number.\n prod1 := sub(prod1, gt(remainder, prod0))\n prod0 := sub(prod0, remainder)\n }\n\n // Factor powers of two out of denominator and compute largest power of two divisor of denominator. Always \u003e= 1.\n // See https://cs.stackexchange.com/q/138556/92363.\n\n // Does not overflow because the denominator cannot be zero at this stage in the function.\n uint256 twos = denominator \u0026 (~denominator + 1);\n assembly {\n // Divide denominator by twos.\n denominator := div(denominator, twos)\n\n // Divide [prod1 prod0] by twos.\n prod0 := div(prod0, twos)\n\n // Flip twos such that it is 2^256 / twos. If twos is zero, then it becomes one.\n twos := add(div(sub(0, twos), twos), 1)\n }\n\n // Shift in bits from prod1 into prod0.\n prod0 |= prod1 * twos;\n\n // Invert denominator mod 2^256. Now that denominator is an odd number, it has an inverse modulo 2^256 such\n // that denominator * inv = 1 mod 2^256. Compute the inverse by starting with a seed that is correct for\n // four bits. That is, denominator * inv = 1 mod 2^4.\n uint256 inverse = (3 * denominator) ^ 2;\n\n // Use the Newton-Raphson iteration to improve the precision. Thanks to Hensel's lifting lemma, this also works\n // in modular arithmetic, doubling the correct bits in each step.\n inverse *= 2 - denominator * inverse; // inverse mod 2^8\n inverse *= 2 - denominator * inverse; // inverse mod 2^16\n inverse *= 2 - denominator * inverse; // inverse mod 2^32\n inverse *= 2 - denominator * inverse; // inverse mod 2^64\n inverse *= 2 - denominator * inverse; // inverse mod 2^128\n inverse *= 2 - denominator * inverse; // inverse mod 2^256\n\n // Because the division is now exact we can divide by multiplying with the modular inverse of denominator.\n // This will give us the correct result modulo 2^256. Since the preconditions guarantee that the outcome is\n // less than 2^256, this is the final result. We don't need to compute the high bits of the result and prod1\n // is no longer required.\n result = prod0 * inverse;\n return result;\n }\n }\n\n /**\n * @notice Calculates x * y / denominator with full precision, following the selected rounding direction.\n */\n function mulDiv(uint256 x, uint256 y, uint256 denominator, Rounding rounding) internal pure returns (uint256) {\n uint256 result = mulDiv(x, y, denominator);\n if (rounding == Rounding.Up \u0026\u0026 mulmod(x, y, denominator) \u003e 0) {\n result += 1;\n }\n return result;\n }\n\n /**\n * @dev Returns the square root of a number. If the number is not a perfect square, the value is rounded down.\n *\n * Inspired by Henry S. Warren, Jr.'s \"Hacker's Delight\" (Chapter 11).\n */\n function sqrt(uint256 a) internal pure returns (uint256) {\n if (a == 0) {\n return 0;\n }\n\n // For our first guess, we get the biggest power of 2 which is smaller than the square root of the target.\n //\n // We know that the \"msb\" (most significant bit) of our target number `a` is a power of 2 such that we have\n // `msb(a) \u003c= a \u003c 2*msb(a)`. This value can be written `msb(a)=2**k` with `k=log2(a)`.\n //\n // This can be rewritten `2**log2(a) \u003c= a \u003c 2**(log2(a) + 1)`\n // → `sqrt(2**k) \u003c= sqrt(a) \u003c sqrt(2**(k+1))`\n // → `2**(k/2) \u003c= sqrt(a) \u003c 2**((k+1)/2) \u003c= 2**(k/2 + 1)`\n //\n // Consequently, `2**(log2(a) / 2)` is a good first approximation of `sqrt(a)` with at least 1 correct bit.\n uint256 result = 1 \u003c\u003c (log2(a) \u003e\u003e 1);\n\n // At this point `result` is an estimation with one bit of precision. We know the true value is a uint128,\n // since it is the square root of a uint256. Newton's method converges quadratically (precision doubles at\n // every iteration). We thus need at most 7 iteration to turn our partial result with one bit of precision\n // into the expected uint128 result.\n unchecked {\n result = (result + a / result) \u003e\u003e 1;\n result = (result + a / result) \u003e\u003e 1;\n result = (result + a / result) \u003e\u003e 1;\n result = (result + a / result) \u003e\u003e 1;\n result = (result + a / result) \u003e\u003e 1;\n result = (result + a / result) \u003e\u003e 1;\n result = (result + a / result) \u003e\u003e 1;\n return min(result, a / result);\n }\n }\n\n /**\n * @notice Calculates sqrt(a), following the selected rounding direction.\n */\n function sqrt(uint256 a, Rounding rounding) internal pure returns (uint256) {\n unchecked {\n uint256 result = sqrt(a);\n return result + (rounding == Rounding.Up \u0026\u0026 result * result \u003c a ? 1 : 0);\n }\n }\n\n /**\n * @dev Return the log in base 2, rounded down, of a positive value.\n * Returns 0 if given 0.\n */\n function log2(uint256 value) internal pure returns (uint256) {\n uint256 result = 0;\n unchecked {\n if (value \u003e\u003e 128 \u003e 0) {\n value \u003e\u003e= 128;\n result += 128;\n }\n if (value \u003e\u003e 64 \u003e 0) {\n value \u003e\u003e= 64;\n result += 64;\n }\n if (value \u003e\u003e 32 \u003e 0) {\n value \u003e\u003e= 32;\n result += 32;\n }\n if (value \u003e\u003e 16 \u003e 0) {\n value \u003e\u003e= 16;\n result += 16;\n }\n if (value \u003e\u003e 8 \u003e 0) {\n value \u003e\u003e= 8;\n result += 8;\n }\n if (value \u003e\u003e 4 \u003e 0) {\n value \u003e\u003e= 4;\n result += 4;\n }\n if (value \u003e\u003e 2 \u003e 0) {\n value \u003e\u003e= 2;\n result += 2;\n }\n if (value \u003e\u003e 1 \u003e 0) {\n result += 1;\n }\n }\n return result;\n }\n\n /**\n * @dev Return the log in base 2, following the selected rounding direction, of a positive value.\n * Returns 0 if given 0.\n */\n function log2(uint256 value, Rounding rounding) internal pure returns (uint256) {\n unchecked {\n uint256 result = log2(value);\n return result + (rounding == Rounding.Up \u0026\u0026 1 \u003c\u003c result \u003c value ? 1 : 0);\n }\n }\n\n /**\n * @dev Return the log in base 10, rounded down, of a positive value.\n * Returns 0 if given 0.\n */\n function log10(uint256 value) internal pure returns (uint256) {\n uint256 result = 0;\n unchecked {\n if (value \u003e= 10 ** 64) {\n value /= 10 ** 64;\n result += 64;\n }\n if (value \u003e= 10 ** 32) {\n value /= 10 ** 32;\n result += 32;\n }\n if (value \u003e= 10 ** 16) {\n value /= 10 ** 16;\n result += 16;\n }\n if (value \u003e= 10 ** 8) {\n value /= 10 ** 8;\n result += 8;\n }\n if (value \u003e= 10 ** 4) {\n value /= 10 ** 4;\n result += 4;\n }\n if (value \u003e= 10 ** 2) {\n value /= 10 ** 2;\n result += 2;\n }\n if (value \u003e= 10 ** 1) {\n result += 1;\n }\n }\n return result;\n }\n\n /**\n * @dev Return the log in base 10, following the selected rounding direction, of a positive value.\n * Returns 0 if given 0.\n */\n function log10(uint256 value, Rounding rounding) internal pure returns (uint256) {\n unchecked {\n uint256 result = log10(value);\n return result + (rounding == Rounding.Up \u0026\u0026 10 ** result \u003c value ? 1 : 0);\n }\n }\n\n /**\n * @dev Return the log in base 256, rounded down, of a positive value.\n * Returns 0 if given 0.\n *\n * Adding one to the result gives the number of pairs of hex symbols needed to represent `value` as a hex string.\n */\n function log256(uint256 value) internal pure returns (uint256) {\n uint256 result = 0;\n unchecked {\n if (value \u003e\u003e 128 \u003e 0) {\n value \u003e\u003e= 128;\n result += 16;\n }\n if (value \u003e\u003e 64 \u003e 0) {\n value \u003e\u003e= 64;\n result += 8;\n }\n if (value \u003e\u003e 32 \u003e 0) {\n value \u003e\u003e= 32;\n result += 4;\n }\n if (value \u003e\u003e 16 \u003e 0) {\n value \u003e\u003e= 16;\n result += 2;\n }\n if (value \u003e\u003e 8 \u003e 0) {\n result += 1;\n }\n }\n return result;\n }\n\n /**\n * @dev Return the log in base 256, following the selected rounding direction, of a positive value.\n * Returns 0 if given 0.\n */\n function log256(uint256 value, Rounding rounding) internal pure returns (uint256) {\n unchecked {\n uint256 result = log256(value);\n return result + (rounding == Rounding.Up \u0026\u0026 1 \u003c\u003c (result \u003c\u003c 3) \u003c value ? 1 : 0);\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/utils/math/SignedMath.sol\n\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/math/SignedMath.sol)\n\n/**\n * @dev Standard signed math utilities missing in the Solidity language.\n */\nlibrary SignedMath {\n /**\n * @dev Returns the largest of two signed numbers.\n */\n function max(int256 a, int256 b) internal pure returns (int256) {\n return a \u003e b ? a : b;\n }\n\n /**\n * @dev Returns the smallest of two signed numbers.\n */\n function min(int256 a, int256 b) internal pure returns (int256) {\n return a \u003c b ? a : b;\n }\n\n /**\n * @dev Returns the average of two signed numbers without overflow.\n * The result is rounded towards zero.\n */\n function average(int256 a, int256 b) internal pure returns (int256) {\n // Formula from the book \"Hacker's Delight\"\n int256 x = (a \u0026 b) + ((a ^ b) \u003e\u003e 1);\n return x + (int256(uint256(x) \u003e\u003e 255) \u0026 (a ^ b));\n }\n\n /**\n * @dev Returns the absolute unsigned value of a signed value.\n */\n function abs(int256 n) internal pure returns (uint256) {\n unchecked {\n // must be unchecked in order to support `n = type(int256).min`\n return uint256(n \u003e= 0 ? n : -n);\n }\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// 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/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/InterfaceSummit.sol\n\ninterface InterfaceSummit {\n // ══════════════════════════════════════════ ACCEPT AGENT STATEMENTS ══════════════════════════════════════════════\n\n /**\n * @notice Accepts a receipt, which local `AgentManager` verified to have been signed by an active Notary.\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 * - Notary who signed the receipt is referenced as the \"Receipt Notary\".\n * - Notary who signed the attestation on destination chain is referenced as the \"Attestation Notary\".\n * \u003e Will revert if any of these is true:\n * \u003e - Called by anyone other than local `AgentManager`.\n * \u003e - Receipt body payload is not properly formatted.\n * \u003e - Receipt signer is in Dispute.\n * \u003e - Receipt's snapshot root is unknown.\n * @param rcptNotaryIndex Index of Receipt Notary in Agent Merkle Tree\n * @param attNotaryIndex Index of Attestation Notary in Agent Merkle Tree\n * @param sigIndex Index of stored Notary signature\n * @param attNonce Nonce of the attestation used for proving the executed message\n * @param paddedTips Padded encoded paid tips information\n * @param rcptPayload Raw payload with message execution receipt\n * @return wasAccepted Whether the receipt was accepted\n */\n function acceptReceipt(\n uint32 rcptNotaryIndex,\n uint32 attNotaryIndex,\n uint256 sigIndex,\n uint32 attNonce,\n uint256 paddedTips,\n bytes memory rcptPayload\n ) external returns (bool wasAccepted);\n\n /**\n * @notice Accepts a snapshot, which local `AgentManager` verified to have been signed by an active Guard.\n * \u003e Snapshot is a list of states for a set of Origin contracts residing on any of the chains.\n * All the states in the Guard-signed snapshot become available for Notary signing.\n * \u003e Will revert if any of these is true:\n * \u003e - Called by anyone other than local `AgentManager`.\n * \u003e - Snapshot payload is not properly formatted.\n * \u003e - Snapshot contains a state older then the Guard has previously submitted.\n * @param guardIndex Index of Guard in Agent Merkle Tree\n * @param sigIndex Index of stored Agent signature\n * @param snapPayload Raw payload with snapshot data\n */\n function acceptGuardSnapshot(uint32 guardIndex, uint256 sigIndex, bytes memory snapPayload) external;\n\n /**\n * @notice Accepts a snapshot, which local `AgentManager` verified to have been signed by an active Notary.\n * \u003e Snapshot is a list of states for a set of Origin contracts residing on any of the chains.\n * Snapshot Merkle Root is calculated and saved for valid snapshots, i.e.\n * snapshots which are only using states previously submitted by any of the Guards.\n * - Notary could use states singed by the same of different Guards 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 - Called by anyone other than local `AgentManager`.\n * \u003e - Snapshot payload is not properly formatted.\n * \u003e - Snapshot contains a state older then the Notary has previously submitted.\n * \u003e - Snapshot contains a state that no Guard has previously submitted.\n * @param notaryIndex Index of Notary in Agent Merkle Tree\n * @param sigIndex Index of stored Agent signature\n * @param agentRoot Current root of the Agent Merkle Tree\n * @param snapPayload Raw payload with snapshot data\n * @return attPayload Raw payload with data for attestation derived from Notary snapshot.\n */\n function acceptNotarySnapshot(uint32 notaryIndex, uint256 sigIndex, bytes32 agentRoot, bytes memory snapPayload)\n external\n returns (bytes memory attPayload);\n\n // ════════════════════════════════════════════════ TIPS LOGIC ═════════════════════════════════════════════════════\n\n /**\n * @notice Distributes tips using the first Receipt from the \"receipt quarantine queue\".\n * Possible scenarios:\n * - Receipt queue is empty =\u003e does nothing\n * - Receipt optimistic period is not over =\u003e does nothing\n * - Either of Notaries present in Receipt was slashed =\u003e receipt is deleted from the queue\n * - Either of Notaries present in Receipt in Dispute =\u003e receipt is moved to the end of queue\n * - None of the above =\u003e receipt tips are distributed\n * @dev Returned value makes it possible to do the following: `while (distributeTips()) {}`\n * @return queuePopped Whether the first element was popped from the queue\n */\n function distributeTips() external returns (bool queuePopped);\n\n /**\n * @notice Withdraws locked base message tips from requested domain Origin to the recipient.\n * This is done by a call to a local Origin contract, or by a manager message to the remote chain.\n * @dev This will revert, if the pending balance of origin tips (earned-claimed) is lower than requested.\n * @param origin Domain of chain to withdraw tips on\n * @param amount Amount of tips to withdraw\n */\n function withdrawTips(uint32 origin, uint256 amount) external;\n\n // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════\n\n /**\n * @notice Returns earned and claimed tips for the actor.\n * Note: Tips for address(0) belong to the Treasury.\n * @param actor Address of the actor\n * @param origin Domain where the tips were initially paid\n * @return earned Total amount of origin tips the actor has earned so far\n * @return claimed Total amount of origin tips the actor has claimed so far\n */\n function actorTips(address actor, uint32 origin) external view returns (uint128 earned, uint128 claimed);\n\n /**\n * @notice Returns the amount of receipts in the \"Receipt Quarantine Queue\".\n */\n function receiptQueueLength() external view returns (uint256);\n\n /**\n * @notice Returns the state with the highest known nonce\n * submitted by any of the currently active Guards.\n * @param origin Domain of origin chain\n * @return statePayload Raw payload with latest active Guard state for origin\n */\n function getLatestState(uint32 origin) external view returns (bytes memory statePayload);\n}\n\n// node_modules/@openzeppelin/contracts/utils/Strings.sol\n\n// OpenZeppelin Contracts (last updated v4.9.0) (utils/Strings.sol)\n\n/**\n * @dev String operations.\n */\nlibrary Strings {\n bytes16 private constant _SYMBOLS = \"0123456789abcdef\";\n uint8 private constant _ADDRESS_LENGTH = 20;\n\n /**\n * @dev Converts a `uint256` to its ASCII `string` decimal representation.\n */\n function toString(uint256 value) internal pure returns (string memory) {\n unchecked {\n uint256 length = Math.log10(value) + 1;\n string memory buffer = new string(length);\n uint256 ptr;\n /// @solidity memory-safe-assembly\n assembly {\n ptr := add(buffer, add(32, length))\n }\n while (true) {\n ptr--;\n /// @solidity memory-safe-assembly\n assembly {\n mstore8(ptr, byte(mod(value, 10), _SYMBOLS))\n }\n value /= 10;\n if (value == 0) break;\n }\n return buffer;\n }\n }\n\n /**\n * @dev Converts a `int256` to its ASCII `string` decimal representation.\n */\n function toString(int256 value) internal pure returns (string memory) {\n return string(abi.encodePacked(value \u003c 0 ? \"-\" : \"\", toString(SignedMath.abs(value))));\n }\n\n /**\n * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation.\n */\n function toHexString(uint256 value) internal pure returns (string memory) {\n unchecked {\n return toHexString(value, Math.log256(value) + 1);\n }\n }\n\n /**\n * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length.\n */\n function toHexString(uint256 value, uint256 length) internal pure returns (string memory) {\n bytes memory buffer = new bytes(2 * length + 2);\n buffer[0] = \"0\";\n buffer[1] = \"x\";\n for (uint256 i = 2 * length + 1; i \u003e 1; --i) {\n buffer[i] = _SYMBOLS[value \u0026 0xf];\n value \u003e\u003e= 4;\n }\n require(value == 0, \"Strings: hex length insufficient\");\n return string(buffer);\n }\n\n /**\n * @dev Converts an `address` with fixed length of 20 bytes to its not checksummed ASCII `string` hexadecimal representation.\n */\n function toHexString(address addr) internal pure returns (string memory) {\n return toHexString(uint256(uint160(addr)), _ADDRESS_LENGTH);\n }\n\n /**\n * @dev Returns true if the two strings are equal.\n */\n function equal(string memory a, string memory b) internal pure returns (bool) {\n return keccak256(bytes(a)) == keccak256(bytes(b));\n }\n}\n\n// node_modules/@openzeppelin/contracts-upgradeable/utils/ContextUpgradeable.sol\n\n// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)\n\n/**\n * @dev Provides information about the current execution context, including the\n * sender of the transaction and its data. While these are generally available\n * via msg.sender and msg.data, they should not be accessed in such a direct\n * manner, since when dealing with meta-transactions the account sending and\n * paying for execution may not be the actual sender (as far as an application\n * is concerned).\n *\n * This contract is only required for intermediate, library-like contracts.\n */\nabstract contract ContextUpgradeable is Initializable {\n function __Context_init() internal onlyInitializing {\n }\n\n function __Context_init_unchained() internal onlyInitializing {\n }\n function _msgSender() internal view virtual returns (address) {\n return msg.sender;\n }\n\n function _msgData() internal view virtual returns (bytes calldata) {\n return msg.data;\n }\n\n /**\n * @dev This empty reserved space is put in place to allow future versions to add new\n * variables without shifting down storage in the inheritance chain.\n * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\n */\n uint256[50] private __gap;\n}\n\n// contracts/libs/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/utils/cryptography/ECDSA.sol\n\n// OpenZeppelin Contracts (last updated v4.9.0) (utils/cryptography/ECDSA.sol)\n\n/**\n * @dev Elliptic Curve Digital Signature Algorithm (ECDSA) operations.\n *\n * These functions can be used to verify that a message was signed by the holder\n * of the private keys of a given address.\n */\nlibrary ECDSA {\n enum RecoverError {\n NoError,\n InvalidSignature,\n InvalidSignatureLength,\n InvalidSignatureS,\n InvalidSignatureV // Deprecated in v4.8\n }\n\n function _throwError(RecoverError error) private pure {\n if (error == RecoverError.NoError) {\n return; // no error: do nothing\n } else if (error == RecoverError.InvalidSignature) {\n revert(\"ECDSA: invalid signature\");\n } else if (error == RecoverError.InvalidSignatureLength) {\n revert(\"ECDSA: invalid signature length\");\n } else if (error == RecoverError.InvalidSignatureS) {\n revert(\"ECDSA: invalid signature 's' value\");\n }\n }\n\n /**\n * @dev Returns the address that signed a hashed message (`hash`) with\n * `signature` or error string. This address can then be used for verification purposes.\n *\n * The `ecrecover` EVM opcode allows for malleable (non-unique) signatures:\n * this function rejects them by requiring the `s` value to be in the lower\n * half order, and the `v` value to be either 27 or 28.\n *\n * IMPORTANT: `hash` _must_ be the result of a hash operation for the\n * verification to be secure: it is possible to craft signatures that\n * recover to arbitrary addresses for non-hashed data. A safe way to ensure\n * this is by receiving a hash of the original message (which may otherwise\n * be too long), and then calling {toEthSignedMessageHash} on it.\n *\n * Documentation for signature generation:\n * - with https://web3js.readthedocs.io/en/v1.3.4/web3-eth-accounts.html#sign[Web3.js]\n * - with https://docs.ethers.io/v5/api/signer/#Signer-signMessage[ethers]\n *\n * _Available since v4.3._\n */\n function tryRecover(bytes32 hash, bytes memory signature) internal pure returns (address, RecoverError) {\n if (signature.length == 65) {\n bytes32 r;\n bytes32 s;\n uint8 v;\n // ecrecover takes the signature parameters, and the only way to get them\n // currently is to use assembly.\n /// @solidity memory-safe-assembly\n assembly {\n r := mload(add(signature, 0x20))\n s := mload(add(signature, 0x40))\n v := byte(0, mload(add(signature, 0x60)))\n }\n return tryRecover(hash, v, r, s);\n } else {\n return (address(0), RecoverError.InvalidSignatureLength);\n }\n }\n\n /**\n * @dev Returns the address that signed a hashed message (`hash`) with\n * `signature`. This address can then be used for verification purposes.\n *\n * The `ecrecover` EVM opcode allows for malleable (non-unique) signatures:\n * this function rejects them by requiring the `s` value to be in the lower\n * half order, and the `v` value to be either 27 or 28.\n *\n * IMPORTANT: `hash` _must_ be the result of a hash operation for the\n * verification to be secure: it is possible to craft signatures that\n * recover to arbitrary addresses for non-hashed data. A safe way to ensure\n * this is by receiving a hash of the original message (which may otherwise\n * be too long), and then calling {toEthSignedMessageHash} on it.\n */\n function recover(bytes32 hash, bytes memory signature) internal pure returns (address) {\n (address recovered, RecoverError error) = tryRecover(hash, signature);\n _throwError(error);\n return recovered;\n }\n\n /**\n * @dev Overload of {ECDSA-tryRecover} that receives the `r` and `vs` short-signature fields separately.\n *\n * See https://eips.ethereum.org/EIPS/eip-2098[EIP-2098 short signatures]\n *\n * _Available since v4.3._\n */\n function tryRecover(bytes32 hash, bytes32 r, bytes32 vs) internal pure returns (address, RecoverError) {\n bytes32 s = vs \u0026 bytes32(0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff);\n uint8 v = uint8((uint256(vs) \u003e\u003e 255) + 27);\n return tryRecover(hash, v, r, s);\n }\n\n /**\n * @dev Overload of {ECDSA-recover} that receives the `r and `vs` short-signature fields separately.\n *\n * _Available since v4.2._\n */\n function recover(bytes32 hash, bytes32 r, bytes32 vs) internal pure returns (address) {\n (address recovered, RecoverError error) = tryRecover(hash, r, vs);\n _throwError(error);\n return recovered;\n }\n\n /**\n * @dev Overload of {ECDSA-tryRecover} that receives the `v`,\n * `r` and `s` signature fields separately.\n *\n * _Available since v4.3._\n */\n function tryRecover(bytes32 hash, uint8 v, bytes32 r, bytes32 s) internal pure returns (address, RecoverError) {\n // EIP-2 still allows signature malleability for ecrecover(). Remove this possibility and make the signature\n // unique. Appendix F in the Ethereum Yellow paper (https://ethereum.github.io/yellowpaper/paper.pdf), defines\n // the valid range for s in (301): 0 \u003c s \u003c secp256k1n ÷ 2 + 1, and for v in (302): v ∈ {27, 28}. Most\n // signatures from current libraries generate a unique signature with an s-value in the lower half order.\n //\n // If your library generates malleable signatures, such as s-values in the upper range, calculate a new s-value\n // with 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141 - s1 and flip v from 27 to 28 or\n // vice versa. If your library also generates signatures with 0/1 for v instead 27/28, add 27 to v to accept\n // these malleable signatures as well.\n if (uint256(s) \u003e 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0) {\n return (address(0), RecoverError.InvalidSignatureS);\n }\n\n // If the signature is valid (and not malleable), return the signer address\n address signer = ecrecover(hash, v, r, s);\n if (signer == address(0)) {\n return (address(0), RecoverError.InvalidSignature);\n }\n\n return (signer, RecoverError.NoError);\n }\n\n /**\n * @dev Overload of {ECDSA-recover} that receives the `v`,\n * `r` and `s` signature fields separately.\n */\n function recover(bytes32 hash, uint8 v, bytes32 r, bytes32 s) internal pure returns (address) {\n (address recovered, RecoverError error) = tryRecover(hash, v, r, s);\n _throwError(error);\n return recovered;\n }\n\n /**\n * @dev Returns an Ethereum Signed Message, created from a `hash`. This\n * produces hash corresponding to the one signed with the\n * https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`]\n * JSON-RPC method as part of EIP-191.\n *\n * See {recover}.\n */\n function toEthSignedMessageHash(bytes32 hash) internal pure returns (bytes32 message) {\n // 32 is the length in bytes of hash,\n // enforced by the type signature above\n /// @solidity memory-safe-assembly\n assembly {\n mstore(0x00, \"\\x19Ethereum Signed Message:\\n32\")\n mstore(0x1c, hash)\n message := keccak256(0x00, 0x3c)\n }\n }\n\n /**\n * @dev Returns an Ethereum Signed Message, created from `s`. This\n * produces hash corresponding to the one signed with the\n * https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`]\n * JSON-RPC method as part of EIP-191.\n *\n * See {recover}.\n */\n function toEthSignedMessageHash(bytes memory s) internal pure returns (bytes32) {\n return keccak256(abi.encodePacked(\"\\x19Ethereum Signed Message:\\n\", Strings.toString(s.length), s));\n }\n\n /**\n * @dev Returns an Ethereum Signed Typed Data, created from a\n * `domainSeparator` and a `structHash`. This produces hash corresponding\n * to the one signed with the\n * https://eips.ethereum.org/EIPS/eip-712[`eth_signTypedData`]\n * JSON-RPC method as part of EIP-712.\n *\n * See {recover}.\n */\n function toTypedDataHash(bytes32 domainSeparator, bytes32 structHash) internal pure returns (bytes32 data) {\n /// @solidity memory-safe-assembly\n assembly {\n let ptr := mload(0x40)\n mstore(ptr, \"\\x19\\x01\")\n mstore(add(ptr, 0x02), domainSeparator)\n mstore(add(ptr, 0x22), structHash)\n data := keccak256(ptr, 0x42)\n }\n }\n\n /**\n * @dev Returns an Ethereum Signed Data with intended validator, created from a\n * `validator` and `data` according to the version 0 of EIP-191.\n *\n * See {recover}.\n */\n function toDataWithIntendedValidatorHash(address validator, bytes memory data) internal pure returns (bytes32) {\n return keccak256(abi.encodePacked(\"\\x19\\x00\", validator, data));\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/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/inbox/StatementInbox.sol\n\n// ══════════════════════════════ LIBRARY IMPORTS ══════════════════════════════\n\n// ═════════════════════════════ INTERNAL IMPORTS ══════════════════════════════\n\n// ═════════════════════════════ EXTERNAL IMPORTS ══════════════════════════════\n\n/// @notice `StatementInbox` is the entry point for all agent-signed statements. It verifies the\n/// agent signatures, and passes the unsigned statements to the contract to consume it via `acceptX` functions. Is is\n/// also used to verify the agent-signed statements and initiate the agent slashing, should the statement be invalid.\n/// `StatementInbox` is responsible for the following:\n/// - Accepting State and Receipt Reports to initiate a dispute between Guard and Notary.\n/// - Storing all the Guard Reports with the Guard signature leading to a dispute.\n/// - Verifying State/State Reports referencing the local chain and slashing the signer if statement is invalid.\n/// - Verifying Receipt/Receipt Reports referencing the local chain and slashing the signer if statement is invalid.\nabstract contract StatementInbox is MessagingBase, StatementInboxEvents, IStatementInbox {\n using AttestationLib for bytes;\n using ReceiptLib for bytes;\n using StateLib for bytes;\n using SnapshotLib for bytes;\n\n struct StoredReport {\n uint256 sigIndex;\n bytes statementPayload;\n }\n\n // ══════════════════════════════════════════════════ STORAGE ══════════════════════════════════════════════════════\n\n address public agentManager;\n address public origin;\n address public destination;\n\n // TODO: optimize this\n bytes[] internal _storedSignatures;\n StoredReport[] internal _storedReports;\n\n /// @dev gap for upgrade safety\n uint256[45] private __GAP; // solhint-disable-line var-name-mixedcase\n\n // ════════════════════════════════════════════════ INITIALIZER ════════════════════════════════════════════════════\n\n /// @dev Initializes the contract:\n /// - Sets up `msg.sender` as the owner of the contract.\n /// - Sets up `agentManager`, `origin`, and `destination`.\n // solhint-disable-next-line func-name-mixedcase\n function __StatementInbox_init(address agentManager_, address origin_, address destination_)\n internal\n onlyInitializing\n {\n agentManager = agentManager_;\n origin = origin_;\n destination = destination_;\n __Ownable2Step_init();\n }\n\n // ══════════════════════════════════════════ SUBMIT AGENT STATEMENTS ══════════════════════════════════════════════\n\n /// @inheritdoc IStatementInbox\n // solhint-disable-next-line ordering\n function submitStateReportWithSnapshot(\n uint8 stateIndex,\n bytes memory srSignature,\n bytes memory snapPayload,\n bytes memory snapSignature\n ) external returns (bool wasAccepted) {\n // This will revert if payload is not a snapshot\n Snapshot snapshot = snapPayload.castToSnapshot();\n // This will revert if the snapshot signer is not a known Notary\n (AgentStatus memory notaryStatus,) =\n _verifySnapshot({snapshot: snapshot, snapSignature: snapSignature, verifyNotary: true});\n // Notary needs to be Active/Unstaking\n notaryStatus.verifyActiveUnstaking();\n // Check if Notary is active on this chain\n _verifyNotaryDomain(notaryStatus.domain);\n // This will revert if state index is out of range\n State state = snapshot.state(stateIndex);\n // This will revert if the report signer is not an known Guard\n (AgentStatus memory guardStatus,) = _verifyStateReport(state, srSignature);\n // Check that Guard is active\n guardStatus.verifyActive();\n _saveReport(state.unwrap().clone(), srSignature);\n // This will revert if either actor is already in dispute\n IAgentManager(agentManager).openDispute(guardStatus.index, notaryStatus.index);\n return true;\n }\n\n /// @inheritdoc IStatementInbox\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 // This will revert if payload is not a snapshot\n Snapshot snapshot = snapPayload.castToSnapshot();\n // This will revert if state index is out of range\n State state = snapshot.state(stateIndex);\n // This will revert if the report signer is not an known Guard\n (AgentStatus memory guardStatus,) = _verifyStateReport(state, srSignature);\n // Check that Guard is active\n guardStatus.verifyActive();\n // This will revert if payload is not an attestation\n Attestation att = attPayload.castToAttestation();\n // This will revert if signer is not an known Notary\n (AgentStatus memory notaryStatus,) = _verifyAttestation(att, attSignature);\n // Notary needs to be Active/Unstaking\n notaryStatus.verifyActiveUnstaking();\n // Check if Notary is active on this chain\n _verifyNotaryDomain(notaryStatus.domain);\n if (snapshot.calculateRoot() != att.snapRoot()) revert IncorrectSnapshotRoot();\n _saveReport(state.unwrap().clone(), srSignature);\n // This will revert if either actor is already in dispute\n IAgentManager(agentManager).openDispute(guardStatus.index, notaryStatus.index);\n return true;\n }\n\n /// @inheritdoc IStatementInbox\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 // This will revert if payload is not a state\n State state = statePayload.castToState();\n // This will revert if the report signer is not an known Guard\n (AgentStatus memory guardStatus,) = _verifyStateReport(state, srSignature);\n // Check that Guard is active\n guardStatus.verifyActive();\n // This will revert if payload is not an attestation\n Attestation att = attPayload.castToAttestation();\n // This will revert if signer is not a known Notary\n (AgentStatus memory notaryStatus,) = _verifyAttestation(att, attSignature);\n // Notary needs to be Active/Unstaking\n notaryStatus.verifyActiveUnstaking();\n // Check if Notary is active on this chain\n _verifyNotaryDomain(notaryStatus.domain);\n // This will revert if any of these is true:\n // - Attestation root is not equal to Merkle Root derived from State and Snapshot Proof.\n // - Snapshot Proof's first element does not match the State metadata.\n // - Snapshot Proof length exceeds Snapshot tree Height.\n // - State index is out of range.\n _verifySnapshotMerkle(att, stateIndex, state, snapProof);\n _saveReport(statePayload, srSignature);\n // This will revert if either actor is already in dispute\n IAgentManager(agentManager).openDispute(guardStatus.index, notaryStatus.index);\n return true;\n }\n\n // ══════════════════════════════════════════ VERIFY AGENT STATEMENTS ══════════════════════════════════════════════\n\n /// @inheritdoc IStatementInbox\n function verifyReceipt(bytes memory rcptPayload, bytes memory rcptSignature)\n external\n returns (bool isValidReceipt)\n {\n // This will revert if payload is not a receipt\n Receipt rcpt = rcptPayload.castToReceipt();\n // This will revert if the attestation signer is not a known Notary\n (AgentStatus memory status, address notary) = _verifyReceipt(rcpt, rcptSignature);\n // Notary needs to be Active/Unstaking\n status.verifyActiveUnstaking();\n isValidReceipt = IExecutionHub(destination).isValidReceipt(rcptPayload);\n if (!isValidReceipt) {\n emit InvalidReceipt(rcptPayload, rcptSignature);\n IAgentManager(agentManager).slashAgent(status.domain, notary, msg.sender);\n }\n }\n\n /// @inheritdoc IStatementInbox\n function verifyReceiptReport(bytes memory rcptPayload, bytes memory rrSignature)\n external\n returns (bool isValidReport)\n {\n // This will revert if payload is not a receipt\n Receipt rcpt = rcptPayload.castToReceipt();\n // This will revert if the report signer is not a known Guard\n (AgentStatus memory status, address guard) = _verifyReceiptReport(rcpt, rrSignature);\n // Guard needs to be Active/Unstaking\n status.verifyActiveUnstaking();\n // Report is valid IF AND ONLY IF the reported receipt in invalid\n isValidReport = !IExecutionHub(destination).isValidReceipt(rcptPayload);\n if (!isValidReport) {\n emit InvalidReceiptReport(rcptPayload, rrSignature);\n IAgentManager(agentManager).slashAgent(status.domain, guard, msg.sender);\n }\n }\n\n /// @inheritdoc IStatementInbox\n function verifyStateWithAttestation(\n uint8 stateIndex,\n bytes memory snapPayload,\n bytes memory attPayload,\n bytes memory attSignature\n ) external returns (bool isValidState) {\n // This will revert if payload is not an attestation\n Attestation att = attPayload.castToAttestation();\n // This will revert if the attestation signer is not a known Notary\n (AgentStatus memory status, address notary) = _verifyAttestation(att, attSignature);\n // Notary needs to be Active/Unstaking\n status.verifyActiveUnstaking();\n // This will revert if payload is not a snapshot\n Snapshot snapshot = snapPayload.castToSnapshot();\n if (snapshot.calculateRoot() != att.snapRoot()) revert IncorrectSnapshotRoot();\n // This will revert if state does not refer to this chain\n bytes memory statePayload = snapshot.state(stateIndex).unwrap().clone();\n isValidState = IStateHub(origin).isValidState(statePayload);\n if (!isValidState) {\n emit InvalidStateWithAttestation(stateIndex, statePayload, attPayload, attSignature);\n IAgentManager(agentManager).slashAgent(status.domain, notary, msg.sender);\n }\n }\n\n /// @inheritdoc IStatementInbox\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 // This will revert if payload is not an attestation\n Attestation att = attPayload.castToAttestation();\n // This will revert if the attestation signer is not a known Notary\n (AgentStatus memory status, address notary) = _verifyAttestation(att, attSignature);\n // Notary needs to be Active/Unstaking\n status.verifyActiveUnstaking();\n // This will revert if payload is not a state\n State state = statePayload.castToState();\n // This will revert if any of these is true:\n // - Attestation root is not equal to Merkle Root derived from State and Snapshot Proof.\n // - Snapshot Proof's first element does not match the State metadata.\n // - Snapshot Proof length exceeds Snapshot tree Height.\n // - State index is out of range.\n _verifySnapshotMerkle(att, stateIndex, state, snapProof);\n // This will revert if state does not refer to this chain\n isValidState = IStateHub(origin).isValidState(statePayload);\n if (!isValidState) {\n emit InvalidStateWithAttestation(stateIndex, statePayload, attPayload, attSignature);\n IAgentManager(agentManager).slashAgent(status.domain, notary, msg.sender);\n }\n }\n\n /// @inheritdoc IStatementInbox\n function verifyStateWithSnapshot(uint8 stateIndex, bytes memory snapPayload, bytes memory snapSignature)\n external\n returns (bool isValidState)\n {\n // This will revert if payload is not a snapshot\n Snapshot snapshot = snapPayload.castToSnapshot();\n // This will revert if the snapshot signer is not a known Guard/Notary\n (AgentStatus memory status, address agent) =\n _verifySnapshot({snapshot: snapshot, snapSignature: snapSignature, verifyNotary: false});\n // Agent needs to be Active/Unstaking\n status.verifyActiveUnstaking();\n // This will revert if state does not refer to this chain\n isValidState = IStateHub(origin).isValidState(snapshot.state(stateIndex).unwrap().clone());\n if (!isValidState) {\n emit InvalidStateWithSnapshot(stateIndex, snapPayload, snapSignature);\n IAgentManager(agentManager).slashAgent(status.domain, agent, msg.sender);\n }\n }\n\n /// @inheritdoc IStatementInbox\n function verifyStateReport(bytes memory statePayload, bytes memory srSignature)\n external\n returns (bool isValidReport)\n {\n // This will revert if payload is not a state\n State state = statePayload.castToState();\n // This will revert if the report signer is not a known Guard\n (AgentStatus memory status, address guard) = _verifyStateReport(state, srSignature);\n // Guard needs to be Active/Unstaking\n status.verifyActiveUnstaking();\n // Report is valid IF AND ONLY IF the reported state in invalid\n // This will revert if the reported state does not refer to this chain\n isValidReport = !IStateHub(origin).isValidState(statePayload);\n if (!isValidReport) {\n emit InvalidStateReport(statePayload, srSignature);\n IAgentManager(agentManager).slashAgent(status.domain, guard, msg.sender);\n }\n }\n\n // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════\n\n /// @inheritdoc IStatementInbox\n function getReportsAmount() external view returns (uint256) {\n return _storedReports.length;\n }\n\n /// @inheritdoc IStatementInbox\n function getGuardReport(uint256 index)\n external\n view\n returns (bytes memory statementPayload, bytes memory reportSignature)\n {\n if (index \u003e= _storedReports.length) revert IndexOutOfRange();\n StoredReport memory storedReport = _storedReports[index];\n statementPayload = storedReport.statementPayload;\n reportSignature = _storedSignatures[storedReport.sigIndex];\n }\n\n /// @inheritdoc IStatementInbox\n function getStoredSignature(uint256 index) external view returns (bytes memory) {\n return _storedSignatures[index];\n }\n\n // ══════════════════════════════════════════════ INTERNAL LOGIC ═══════════════════════════════════════════════════\n\n /// @dev Saves the statement reported by Guard as invalid and the Guard Report signature.\n function _saveReport(bytes memory statementPayload, bytes memory reportSignature) internal {\n uint256 sigIndex = _saveSignature(reportSignature);\n _storedReports.push(StoredReport(sigIndex, statementPayload));\n }\n\n /// @dev Saves the signature and returns its index.\n function _saveSignature(bytes memory signature) internal returns (uint256 sigIndex) {\n sigIndex = _storedSignatures.length;\n _storedSignatures.push(signature);\n }\n\n // ═══════════════════════════════════════════════ AGENT CHECKS ════════════════════════════════════════════════════\n\n /**\n * @dev Recovers a signer from a hashed message, and a EIP-191 signature for it.\n * Will revert, if the signer is not a known agent.\n * @dev Agent flag could be any of these: Active/Unstaking/Resting/Fraudulent/Slashed\n * Further checks need to be performed in a caller function.\n * @param hashedStatement Hash of the statement that was signed by an Agent\n * @param signature Agent signature for the hashed statement\n * @return status Struct representing agent status:\n * - flag Unknown/Active/Unstaking/Resting/Fraudulent/Slashed\n * - domain Domain where agent is/was active\n * - index Index of agent in the Agent Merkle Tree\n * @return agent Agent that signed the statement\n */\n function _recoverAgent(bytes32 hashedStatement, bytes memory signature)\n internal\n view\n returns (AgentStatus memory status, address agent)\n {\n bytes32 ethSignedMsg = ECDSA.toEthSignedMessageHash(hashedStatement);\n agent = ECDSA.recover(ethSignedMsg, signature);\n status = IAgentManager(agentManager).agentStatus(agent);\n // Discard signature of unknown agents.\n // Further flag checks are supposed to be performed in a caller function.\n status.verifyKnown();\n }\n\n /// @dev Verifies that Notary signature is active on local domain.\n function _verifyNotaryDomain(uint32 notaryDomain) internal view {\n // Notary needs to be from the local domain (if contract is not deployed on Synapse Chain).\n // Or Notary could be from any domain (if contract is deployed on Synapse Chain).\n if (notaryDomain != localDomain \u0026\u0026 localDomain != synapseDomain) revert IncorrectAgentDomain();\n }\n\n // ════════════════════════════════════════ ATTESTATION RELATED CHECKS ═════════════════════════════════════════════\n\n /**\n * @dev Internal function to verify the signed attestation payload.\n * Reverts if any of these is true:\n * - Attestation signer is not a known Notary.\n * @param att Typed memory view over attestation payload\n * @param attSignature Notary signature for the attestation\n * @return status Struct representing agent status, see {_recoverAgent}\n * @return notary Notary that signed the snapshot\n */\n function _verifyAttestation(Attestation att, bytes memory attSignature)\n internal\n view\n returns (AgentStatus memory status, address notary)\n {\n // This will revert if signer is not a known agent\n (status, notary) = _recoverAgent(att.hashValid(), attSignature);\n // Attestation signer needs to be a Notary, not a Guard\n if (status.domain == 0) revert AgentNotNotary();\n }\n\n /**\n * @dev Internal function to verify the signed attestation report payload.\n * Reverts if any of these is true:\n * - Report signer is not a known Guard.\n * @param att Typed memory view over attestation payload that Guard reports as invalid\n * @param arSignature Guard signature for the \"invalid attestation\" report\n * @return status Struct representing guard status, see {_recoverAgent}\n * @return guard Guard that signed the report\n */\n function _verifyAttestationReport(Attestation att, bytes memory arSignature)\n internal\n view\n returns (AgentStatus memory status, address guard)\n {\n // This will revert if signer is not a known agent\n (status, guard) = _recoverAgent(att.hashInvalid(), arSignature);\n // Report signer needs to be a Guard, not a Notary\n if (status.domain != 0) revert AgentNotGuard();\n }\n\n // ══════════════════════════════════════════ RECEIPT RELATED CHECKS ═══════════════════════════════════════════════\n\n /**\n * @dev Internal function to verify the signed receipt payload.\n * Reverts if any of these is true:\n * - Receipt signer is not a known Notary.\n * @param rcpt Typed memory view over receipt payload\n * @param rcptSignature Notary signature for the receipt\n * @return status Struct representing agent status, see {_recoverAgent}\n * @return notary Notary that signed the snapshot\n */\n function _verifyReceipt(Receipt rcpt, bytes memory rcptSignature)\n internal\n view\n returns (AgentStatus memory status, address notary)\n {\n // This will revert if signer is not a known agent\n (status, notary) = _recoverAgent(rcpt.hashValid(), rcptSignature);\n // Receipt signer needs to be a Notary, not a Guard\n if (status.domain == 0) revert AgentNotNotary();\n }\n\n /**\n * @dev Internal function to verify the signed receipt report payload.\n * Reverts if any of these is true:\n * - Report signer is not a known Guard.\n * @param rcpt Typed memory view over receipt payload that Guard reports as invalid\n * @param rrSignature Guard signature for the \"invalid receipt\" report\n * @return status Struct representing guard status, see {_recoverAgent}\n * @return guard Guard that signed the report\n */\n function _verifyReceiptReport(Receipt rcpt, bytes memory rrSignature)\n internal\n view\n returns (AgentStatus memory status, address guard)\n {\n // This will revert if signer is not a known agent\n (status, guard) = _recoverAgent(rcpt.hashInvalid(), rrSignature);\n // Report signer needs to be a Guard, not a Notary\n if (status.domain != 0) revert AgentNotGuard();\n }\n\n // ═══════════════════════════════════════ STATE/SNAPSHOT RELATED CHECKS ═══════════════════════════════════════════\n\n /**\n * @dev Internal function to verify the signed snapshot report payload.\n * Reverts if any of these is true:\n * - Report signer is not a known Guard.\n * @param state Typed memory view over state payload that Guard reports as invalid\n * @param srSignature Guard signature for the report\n * @return status Struct representing guard status, see {_recoverAgent}\n * @return guard Guard that signed the report\n */\n function _verifyStateReport(State state, bytes memory srSignature)\n internal\n view\n returns (AgentStatus memory status, address guard)\n {\n // This will revert if signer is not a known agent\n (status, guard) = _recoverAgent(state.hashInvalid(), srSignature);\n // Report signer needs to be a Guard, not a Notary\n if (status.domain != 0) revert AgentNotGuard();\n }\n\n /**\n * @dev Internal function to verify the signed snapshot payload.\n * Reverts if any of these is true:\n * - Snapshot signer is not a known Agent.\n * - Snapshot signer is not a Notary (if verifyNotary is true).\n * @param snapshot Typed memory view over snapshot payload\n * @param snapSignature Agent signature for the snapshot\n * @param verifyNotary If true, snapshot signer needs to be a Notary, not a Guard\n * @return status Struct representing agent status, see {_recoverAgent}\n * @return agent Agent that signed the snapshot\n */\n function _verifySnapshot(Snapshot snapshot, bytes memory snapSignature, bool verifyNotary)\n internal\n view\n returns (AgentStatus memory status, address agent)\n {\n // This will revert if signer is not a known agent\n (status, agent) = _recoverAgent(snapshot.hashValid(), snapSignature);\n // If requested, snapshot signer needs to be a Notary, not a Guard\n if (verifyNotary \u0026\u0026 status.domain == 0) revert AgentNotNotary();\n }\n\n // ═══════════════════════════════════════════ MERKLE RELATED CHECKS ═══════════════════════════════════════════════\n\n /**\n * @dev Internal function to verify that snapshot roots match.\n * Reverts if any of these is true:\n * - Attestation root is not equal to Merkle Root derived from State and Snapshot Proof.\n * - Snapshot Proof's first element does not match the State metadata.\n * - Snapshot Proof length exceeds Snapshot tree Height.\n * - State index is out of range.\n * @param att Typed memory view over Attestation\n * @param stateIndex Index of state in the snapshot\n * @param state Typed memory view over the provided state payload\n * @param snapProof Raw payload with snapshot data\n */\n function _verifySnapshotMerkle(Attestation att, uint8 stateIndex, State state, bytes32[] memory snapProof)\n internal\n pure\n {\n // Snapshot proof first element should match State metadata (aka \"right sub-leaf\")\n (, bytes32 rightSubLeaf) = state.subLeafs();\n if (snapProof[0] != rightSubLeaf) revert IncorrectSnapshotProof();\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(state.root(), state.origin(), snapProof, stateIndex);\n // Snapshot root should match the attestation root\n if (att.snapRoot() != snapshotRoot) revert IncorrectSnapshotRoot();\n }\n}\n\n// contracts/inbox/Inbox.sol\n\n// ══════════════════════════════ LIBRARY IMPORTS ══════════════════════════════\n\n// ═════════════════════════════ INTERNAL IMPORTS ══════════════════════════════\n\n/// @notice `Inbox` is the child of `StatementInbox` contract, that is used on Synapse Chain.\n/// In addition to the functionality of `StatementInbox`, it also:\n/// - Accepts Guard and Notary Snapshots and passes them to `Summit` contract.\n/// - Accepts Notary-signed Receipts and passes them to `Summit` contract.\n/// - Accepts Receipt Reports to initiate a dispute between Guard and Notary.\n/// - Verifies Attestations and Attestation Reports, and slashes the signer if they are invalid.\ncontract Inbox is StatementInbox, InboxEvents, InterfaceInbox {\n using AttestationLib for bytes;\n using ReceiptLib for bytes;\n using SnapshotLib for bytes;\n\n // Struct to get around stack too deep error. TODO: revisit this\n struct ReceiptInfo {\n AgentStatus rcptNotaryStatus;\n address notary;\n uint32 attNonce;\n AgentStatus attNotaryStatus;\n }\n\n // ══════════════════════════════════════════════════ STORAGE ══════════════════════════════════════════════════════\n\n // The address of the Summit contract.\n address public summit;\n\n // ═════════════════════════════════════════ CONSTRUCTOR \u0026 INITIALIZER ═════════════════════════════════════════════\n\n constructor(uint32 synapseDomain_) MessagingBase(\"0.0.3\", synapseDomain_) {\n if (localDomain != synapseDomain) revert MustBeSynapseDomain();\n }\n\n /// @notice Initializes `Inbox` contract:\n /// - Sets `msg.sender` as the owner of the contract\n /// - Sets `agentManager`, `origin`, `destination` and `summit` addresses\n function initialize(address agentManager_, address origin_, address destination_, address summit_)\n external\n initializer\n {\n __StatementInbox_init(agentManager_, origin_, destination_);\n summit = summit_;\n }\n\n // ══════════════════════════════════════════ SUBMIT AGENT STATEMENTS ══════════════════════════════════════════════\n\n /// @inheritdoc InterfaceInbox\n function submitSnapshot(bytes memory snapPayload, bytes memory snapSignature)\n external\n returns (bytes memory attPayload, bytes32 agentRoot_, uint256[] memory snapGas)\n {\n // This will revert if payload is not a snapshot\n Snapshot snapshot = snapPayload.castToSnapshot();\n // This will revert if the signer is not a known Guard/Notary\n (AgentStatus memory status, address agent) =\n _verifySnapshot({snapshot: snapshot, snapSignature: snapSignature, verifyNotary: false});\n // Check that Agent is active\n status.verifyActive();\n // Store Agent signature for the Snapshot\n uint256 sigIndex = _saveSignature(snapSignature);\n if (status.domain == 0) {\n // Guard that is in Dispute could still submit new snapshots, so we don't check that\n InterfaceSummit(summit).acceptGuardSnapshot({\n guardIndex: status.index,\n sigIndex: sigIndex,\n snapPayload: snapPayload\n });\n } else {\n // Get current agentRoot from AgentManager\n agentRoot_ = IAgentManager(agentManager).agentRoot();\n // This will revert if Notary is in Dispute\n attPayload = InterfaceSummit(summit).acceptNotarySnapshot({\n notaryIndex: status.index,\n sigIndex: sigIndex,\n agentRoot: agentRoot_,\n snapPayload: snapPayload\n });\n ChainGas[] memory snapGas_ = snapshot.snapGas();\n // Pass created attestation to Destination to enable executing messages coming to Synapse Chain\n InterfaceDestination(destination).acceptAttestation(\n status.index, type(uint256).max, attPayload, agentRoot_, snapGas_\n );\n // Use assembly to cast ChainGas[] to uint256[] without copying. Highest bits are left zeroed.\n // solhint-disable-next-line no-inline-assembly\n assembly {\n snapGas := snapGas_\n }\n }\n emit SnapshotAccepted(status.domain, agent, snapPayload, snapSignature);\n }\n\n /// @inheritdoc InterfaceInbox\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 // Struct to get around stack too deep error.\n ReceiptInfo memory info;\n // This will revert if payload is not a receipt\n Receipt rcpt = rcptPayload.castToReceipt();\n // This will revert if the receipt signer is not a known Notary\n (info.rcptNotaryStatus, info.notary) = _verifyReceipt(rcpt, rcptSignature);\n // Receipt Notary needs to be Active\n info.rcptNotaryStatus.verifyActive();\n info.attNonce = IExecutionHub(destination).getAttestationNonce(rcpt.snapshotRoot());\n if (info.attNonce == 0) revert IncorrectSnapshotRoot();\n // Attestation Notary domain needs to match the destination domain\n info.attNotaryStatus = IAgentManager(agentManager).agentStatus(rcpt.attNotary());\n if (info.attNotaryStatus.domain != rcpt.destination()) revert IncorrectAgentDomain();\n // Check that the correct tip values for the message were provided\n _verifyReceiptTips(rcpt.messageHash(), paddedTips, headerHash, bodyHash);\n // Store Notary signature for the Receipt\n uint256 sigIndex = _saveSignature(rcptSignature);\n // This will revert if Receipt Notary is in Dispute\n wasAccepted = InterfaceSummit(summit).acceptReceipt({\n rcptNotaryIndex: info.rcptNotaryStatus.index,\n attNotaryIndex: info.attNotaryStatus.index,\n sigIndex: sigIndex,\n attNonce: info.attNonce,\n paddedTips: paddedTips,\n rcptPayload: rcptPayload\n });\n if (wasAccepted) {\n emit ReceiptAccepted(info.rcptNotaryStatus.domain, info.notary, rcptPayload, rcptSignature);\n }\n }\n\n /// @inheritdoc InterfaceInbox\n function submitReceiptReport(bytes memory rcptPayload, bytes memory rcptSignature, bytes memory rrSignature)\n external\n returns (bool wasAccepted)\n {\n // This will revert if payload is not a receipt\n Receipt rcpt = rcptPayload.castToReceipt();\n // This will revert if the receipt signer is not a known Guard\n (AgentStatus memory guardStatus,) = _verifyReceiptReport(rcpt, rrSignature);\n // Guard needs to be Active\n guardStatus.verifyActive();\n // This will revert if report signer is not a known Notary\n (AgentStatus memory notaryStatus,) = _verifyReceipt(rcpt, rcptSignature);\n // Notary needs to be Active/Unstaking\n notaryStatus.verifyActiveUnstaking();\n _saveReport(rcptPayload, rrSignature);\n // This will revert if either actor is already in dispute\n IAgentManager(agentManager).openDispute(guardStatus.index, notaryStatus.index);\n return true;\n }\n\n /// @inheritdoc InterfaceInbox\n function passReceipt(uint32 attNotaryIndex, uint32 attNonce, uint256 paddedTips, bytes memory rcptPayload)\n external\n returns (bool wasAccepted)\n {\n // Only Destination can pass receipts\n if (msg.sender != destination) revert CallerNotDestination();\n return InterfaceSummit(summit).acceptReceipt({\n rcptNotaryIndex: attNotaryIndex,\n attNotaryIndex: attNotaryIndex,\n sigIndex: type(uint256).max,\n attNonce: attNonce,\n paddedTips: paddedTips,\n rcptPayload: rcptPayload\n });\n }\n\n // ══════════════════════════════════════════ VERIFY AGENT STATEMENTS ══════════════════════════════════════════════\n\n /// @inheritdoc InterfaceInbox\n function verifyAttestation(bytes memory attPayload, bytes memory attSignature)\n external\n returns (bool isValidAttestation)\n {\n // This will revert if payload is not an attestation\n Attestation att = attPayload.castToAttestation();\n // This will revert if the attestation signer is not a known Notary\n (AgentStatus memory status, address notary) = _verifyAttestation(att, attSignature);\n // Notary needs to be Active/Unstaking\n status.verifyActiveUnstaking();\n isValidAttestation = ISnapshotHub(summit).isValidAttestation(attPayload);\n if (!isValidAttestation) {\n emit InvalidAttestation(attPayload, attSignature);\n IAgentManager(agentManager).slashAgent(status.domain, notary, msg.sender);\n }\n }\n\n /// @inheritdoc InterfaceInbox\n function verifyAttestationReport(bytes memory attPayload, bytes memory arSignature)\n external\n returns (bool isValidReport)\n {\n // This will revert if payload is not an attestation\n Attestation att = attPayload.castToAttestation();\n // This will revert if the report signer is not a known Guard\n (AgentStatus memory status, address guard) = _verifyAttestationReport(att, arSignature);\n // Guard needs to be Active/Unstaking\n status.verifyActiveUnstaking();\n // Report is valid IF AND ONLY IF the reported attestation in invalid\n isValidReport = !ISnapshotHub(summit).isValidAttestation(attPayload);\n if (!isValidReport) {\n emit InvalidAttestationReport(attPayload, arSignature);\n IAgentManager(agentManager).slashAgent(status.domain, guard, msg.sender);\n }\n }\n\n // ══════════════════════════════════════════════ INTERNAL VIEWS ═══════════════════════════════════════════════════\n\n /// @dev Verifies that tips proof matches the message hash.\n function _verifyReceiptTips(bytes32 msgHash, uint256 paddedTips, bytes32 headerHash, bytes32 bodyHash)\n internal\n pure\n {\n Tips tips = TipsLib.wrapPadded(paddedTips);\n // full message leaf is (header, baseMessage), while base message leaf is (tips, remainingBody).\n if (MerkleMath.getParent(headerHash, MerkleMath.getParent(tips.leaf(), bodyHash)) != msgHash) {\n revert IncorrectTipsProof();\n }\n }\n}\n","language":"Solidity","languageVersion":"0.8.17","compilerVersion":"0.8.17","compilerOptions":"--combined-json bin,bin-runtime,srcmap,srcmap-runtime,abi,userdoc,devdoc,metadata,hashes --optimize --optimize-runs 10000 --allow-paths ., ./, ../","srcMap":"","srcMapRuntime":"","abiDefinition":[{"inputs":[{"internalType":"uint32","name":"attNonce","type":"uint32"}],"name":"getAttestation","outputs":[{"internalType":"bytes","name":"attPayload","type":"bytes"},{"internalType":"bytes32","name":"agentRoot","type":"bytes32"},{"internalType":"uint256[]","name":"snapGas","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"index","type":"uint256"}],"name":"getGuardSnapshot","outputs":[{"internalType":"bytes","name":"snapPayload","type":"bytes"},{"internalType":"bytes","name":"snapSignature","type":"bytes"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint32","name":"origin","type":"uint32"},{"internalType":"address","name":"agent","type":"address"}],"name":"getLatestAgentState","outputs":[{"internalType":"bytes","name":"statePayload","type":"bytes"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"notary","type":"address"}],"name":"getLatestNotaryAttestation","outputs":[{"internalType":"bytes","name":"attPayload","type":"bytes"},{"internalType":"bytes32","name":"agentRoot","type":"bytes32"},{"internalType":"uint256[]","name":"snapGas","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes","name":"attPayload","type":"bytes"}],"name":"getNotarySnapshot","outputs":[{"internalType":"bytes","name":"snapPayload","type":"bytes"},{"internalType":"bytes","name":"snapSignature","type":"bytes"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"index","type":"uint256"}],"name":"getNotarySnapshot","outputs":[{"internalType":"bytes","name":"snapPayload","type":"bytes"},{"internalType":"bytes","name":"snapSignature","type":"bytes"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint32","name":"attNonce","type":"uint32"},{"internalType":"uint8","name":"stateIndex","type":"uint8"}],"name":"getSnapshotProof","outputs":[{"internalType":"bytes32[]","name":"snapProof","type":"bytes32[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes","name":"attPayload","type":"bytes"}],"name":"isValidAttestation","outputs":[{"internalType":"bool","name":"isValid","type":"bool"}],"stateMutability":"view","type":"function"}],"userDoc":{"kind":"user","methods":{"getAttestation(uint32)":{"notice":"Returns saved attestation with the given nonce."},"getGuardSnapshot(uint256)":{"notice":"Returns Guard snapshot from the list of all accepted Guard snapshots."},"getLatestAgentState(uint32,address)":{"notice":"Returns the state with the highest known nonce submitted by a given Agent."},"getLatestNotaryAttestation(address)":{"notice":"Returns latest saved attestation for a Notary."},"getNotarySnapshot(bytes)":{"notice":"Returns Notary snapshot that was used for creating a given attestation."},"getNotarySnapshot(uint256)":{"notice":"Returns Notary snapshot from the list of all accepted Guard snapshots."},"getSnapshotProof(uint32,uint8)":{"notice":"Returns proof of inclusion of (root, origin) fields of a given snapshot's state into the Snapshot Merkle Tree for a given attestation."},"isValidAttestation(bytes)":{"notice":"Check that a given attestation is valid: matches the historical attestation derived from an accepted Notary snapshot."}},"version":1},"developerDoc":{"kind":"dev","methods":{"getAttestation(uint32)":{"details":"Reverts if attestation with given nonce hasn't been created yet.","params":{"attNonce":"Nonce for the attestation"},"returns":{"agentRoot":" Agent root hash used for the attestation","attPayload":" Raw payload with formatted Attestation data","snapGas":" Snapshot gas data used for the attestation"}},"getGuardSnapshot(uint256)":{"details":"Reverts if snapshot with given index hasn't been accepted yet.","params":{"index":"Snapshot index in the list of all Guard snapshots"},"returns":{"snapPayload":" Raw payload with Guard snapshot","snapSignature":" Raw payload with Guard signature for snapshot"}},"getLatestAgentState(uint32,address)":{"params":{"agent":"Agent address","origin":"Domain of origin chain"},"returns":{"statePayload":"Raw payload with agent's latest state for origin"}},"getLatestNotaryAttestation(address)":{"params":{"notary":"Notary address"},"returns":{"agentRoot":" Agent root hash used for the attestation","attPayload":" Raw payload with formatted Attestation data","snapGas":" Snapshot gas data used for the attestation"}},"getNotarySnapshot(bytes)":{"details":"Reverts if any of these is true: - Attestation payload is not properly formatted. - Attestation is invalid (doesn't have a matching Notary snapshot).","params":{"attPayload":"Raw payload with attestation data"},"returns":{"snapPayload":" Raw payload with Notary snapshot","snapSignature":" Raw payload with Notary signature for snapshot"}},"getNotarySnapshot(uint256)":{"details":"Reverts if snapshot with given index hasn't been accepted yet.","params":{"index":"Snapshot index in the list of all Notary snapshots"},"returns":{"snapPayload":" Raw payload with Notary snapshot","snapSignature":" Raw payload with Notary signature for snapshot"}},"getSnapshotProof(uint32,uint8)":{"details":"Reverts if any of these is true: - Attestation with given nonce hasn't been created yet. - State index is out of range of snapshot list.","params":{"attNonce":"Nonce for the attestation","stateIndex":"Index of state in the attestation's snapshot"},"returns":{"snapProof":" The snapshot proof"}},"isValidAttestation(bytes)":{"details":"Will revert if any of these is true: - Attestation payload is not properly formatted.","params":{"attPayload":"Raw payload with attestation data"},"returns":{"isValid":" Whether the provided attestation is valid"}}},"version":1},"metadata":"{\"compiler\":{\"version\":\"0.8.17+commit.8df45f5f\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"uint32\",\"name\":\"attNonce\",\"type\":\"uint32\"}],\"name\":\"getAttestation\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"attPayload\",\"type\":\"bytes\"},{\"internalType\":\"bytes32\",\"name\":\"agentRoot\",\"type\":\"bytes32\"},{\"internalType\":\"uint256[]\",\"name\":\"snapGas\",\"type\":\"uint256[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"index\",\"type\":\"uint256\"}],\"name\":\"getGuardSnapshot\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"snapPayload\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"snapSignature\",\"type\":\"bytes\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint32\",\"name\":\"origin\",\"type\":\"uint32\"},{\"internalType\":\"address\",\"name\":\"agent\",\"type\":\"address\"}],\"name\":\"getLatestAgentState\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"statePayload\",\"type\":\"bytes\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"notary\",\"type\":\"address\"}],\"name\":\"getLatestNotaryAttestation\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"attPayload\",\"type\":\"bytes\"},{\"internalType\":\"bytes32\",\"name\":\"agentRoot\",\"type\":\"bytes32\"},{\"internalType\":\"uint256[]\",\"name\":\"snapGas\",\"type\":\"uint256[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"attPayload\",\"type\":\"bytes\"}],\"name\":\"getNotarySnapshot\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"snapPayload\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"snapSignature\",\"type\":\"bytes\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"index\",\"type\":\"uint256\"}],\"name\":\"getNotarySnapshot\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"snapPayload\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"snapSignature\",\"type\":\"bytes\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint32\",\"name\":\"attNonce\",\"type\":\"uint32\"},{\"internalType\":\"uint8\",\"name\":\"stateIndex\",\"type\":\"uint8\"}],\"name\":\"getSnapshotProof\",\"outputs\":[{\"internalType\":\"bytes32[]\",\"name\":\"snapProof\",\"type\":\"bytes32[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"attPayload\",\"type\":\"bytes\"}],\"name\":\"isValidAttestation\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"isValid\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{\"getAttestation(uint32)\":{\"details\":\"Reverts if attestation with given nonce hasn't been created yet.\",\"params\":{\"attNonce\":\"Nonce for the attestation\"},\"returns\":{\"agentRoot\":\" Agent root hash used for the attestation\",\"attPayload\":\" Raw payload with formatted Attestation data\",\"snapGas\":\" Snapshot gas data used for the attestation\"}},\"getGuardSnapshot(uint256)\":{\"details\":\"Reverts if snapshot with given index hasn't been accepted yet.\",\"params\":{\"index\":\"Snapshot index in the list of all Guard snapshots\"},\"returns\":{\"snapPayload\":\" Raw payload with Guard snapshot\",\"snapSignature\":\" Raw payload with Guard signature for snapshot\"}},\"getLatestAgentState(uint32,address)\":{\"params\":{\"agent\":\"Agent address\",\"origin\":\"Domain of origin chain\"},\"returns\":{\"statePayload\":\"Raw payload with agent's latest state for origin\"}},\"getLatestNotaryAttestation(address)\":{\"params\":{\"notary\":\"Notary address\"},\"returns\":{\"agentRoot\":\" Agent root hash used for the attestation\",\"attPayload\":\" Raw payload with formatted Attestation data\",\"snapGas\":\" Snapshot gas data used for the attestation\"}},\"getNotarySnapshot(bytes)\":{\"details\":\"Reverts if any of these is true: - Attestation payload is not properly formatted. - Attestation is invalid (doesn't have a matching Notary snapshot).\",\"params\":{\"attPayload\":\"Raw payload with attestation data\"},\"returns\":{\"snapPayload\":\" Raw payload with Notary snapshot\",\"snapSignature\":\" Raw payload with Notary signature for snapshot\"}},\"getNotarySnapshot(uint256)\":{\"details\":\"Reverts if snapshot with given index hasn't been accepted yet.\",\"params\":{\"index\":\"Snapshot index in the list of all Notary snapshots\"},\"returns\":{\"snapPayload\":\" Raw payload with Notary snapshot\",\"snapSignature\":\" Raw payload with Notary signature for snapshot\"}},\"getSnapshotProof(uint32,uint8)\":{\"details\":\"Reverts if any of these is true: - Attestation with given nonce hasn't been created yet. - State index is out of range of snapshot list.\",\"params\":{\"attNonce\":\"Nonce for the attestation\",\"stateIndex\":\"Index of state in the attestation's snapshot\"},\"returns\":{\"snapProof\":\" The snapshot proof\"}},\"isValidAttestation(bytes)\":{\"details\":\"Will revert if any of these is true: - Attestation payload is not properly formatted.\",\"params\":{\"attPayload\":\"Raw payload with attestation data\"},\"returns\":{\"isValid\":\" Whether the provided attestation is valid\"}}},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{\"getAttestation(uint32)\":{\"notice\":\"Returns saved attestation with the given nonce.\"},\"getGuardSnapshot(uint256)\":{\"notice\":\"Returns Guard snapshot from the list of all accepted Guard snapshots.\"},\"getLatestAgentState(uint32,address)\":{\"notice\":\"Returns the state with the highest known nonce submitted by a given Agent.\"},\"getLatestNotaryAttestation(address)\":{\"notice\":\"Returns latest saved attestation for a Notary.\"},\"getNotarySnapshot(bytes)\":{\"notice\":\"Returns Notary snapshot that was used for creating a given attestation.\"},\"getNotarySnapshot(uint256)\":{\"notice\":\"Returns Notary snapshot from the list of all accepted Guard snapshots.\"},\"getSnapshotProof(uint32,uint8)\":{\"notice\":\"Returns proof of inclusion of (root, origin) fields of a given snapshot's state into the Snapshot Merkle Tree for a given attestation.\"},\"isValidAttestation(bytes)\":{\"notice\":\"Check that a given attestation is valid: matches the historical attestation derived from an accepted Notary snapshot.\"}},\"version\":1}},\"settings\":{\"compilationTarget\":{\"solidity/Inbox.sol\":\"ISnapshotHub\"},\"evmVersion\":\"london\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\"},\"optimizer\":{\"enabled\":true,\"runs\":10000},\"remappings\":[]},\"sources\":{\"solidity/Inbox.sol\":{\"keccak256\":\"0x9b516081a036814c0169e20e484d4a5499066b7a6f48fada952b5e844a1ca3e5\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://32bde393b3f24ef4307d9626d4143f337b3c0bd34e17bb969fd5a15221d96987\",\"dweb:/ipfs/QmTkt2XZRtgsbSpmsVQUM3c4ebETQoDVYbmEV9yheBghnr\"]}},\"version\":1}"},"hashes":{"getAttestation(uint32)":"a23d9bae","getGuardSnapshot(uint256)":"caecc6db","getLatestAgentState(uint32,address)":"e8c12f80","getLatestNotaryAttestation(address)":"bf1aae26","getNotarySnapshot(bytes)":"02eef8dc","getNotarySnapshot(uint256)":"f5230719","getSnapshotProof(uint32,uint8)":"81241b89","isValidAttestation(bytes)":"4362fd11"}},"solidity/Inbox.sol:IStateHub":{"code":"0x","runtime-code":"0x","info":{"source":"// SPDX-License-Identifier: MIT\npragma solidity =0.8.17 ^0.8.0 ^0.8.1 ^0.8.2;\n\n// contracts/events/InboxEvents.sol\n\nabstract contract InboxEvents {\n /**\n * @notice Emitted when a snapshot is accepted by the Summit contract.\n * @param domain Domain where the signed Agent is active (ZERO for Guards)\n * @param agent Agent who signed the snapshot\n * @param snapPayload Raw payload with snapshot data\n * @param snapSignature Agent signature for the snapshot\n */\n event SnapshotAccepted(uint32 indexed domain, address indexed agent, bytes snapPayload, bytes snapSignature);\n\n /**\n * @notice Emitted when a snapshot is accepted by the Summit contract.\n * @param domain Domain where the signed Notary is active\n * @param notary Notary who signed the attestation\n * @param rcptPayload Raw payload with receipt data\n * @param rcptSignature Notary signature for the receipt\n */\n event ReceiptAccepted(uint32 domain, address notary, bytes rcptPayload, bytes rcptSignature);\n\n /**\n * @notice Emitted when a proof of invalid attestation is submitted.\n * @param attPayload Raw payload with Attestation data\n * @param attSignature Notary signature for the attestation\n */\n event InvalidAttestation(bytes attPayload, bytes attSignature);\n\n /**\n * @notice Emitted when a proof of invalid attestation report is submitted.\n * @param arPayload Raw payload with report data\n * @param arSignature Guard signature for the report\n */\n event InvalidAttestationReport(bytes arPayload, bytes arSignature);\n}\n\n// contracts/events/StatementInboxEvents.sol\n\nabstract contract StatementInboxEvents {\n // ════════════════════════════════════════════ STATEMENT ACCEPTED ═════════════════════════════════════════════════\n\n /**\n * @notice Emitted when a snapshot is accepted by the Destination contract.\n * @param domain Domain where the signed Notary is active\n * @param notary Notary who signed the attestation\n * @param attPayload Raw payload with attestation data\n * @param attSignature Notary signature for the attestation\n */\n event AttestationAccepted(uint32 domain, address notary, bytes attPayload, bytes attSignature);\n\n // ═════════════════════════════════════════ INVALID STATEMENT PROVED ══════════════════════════════════════════════\n\n /**\n * @notice Emitted when a proof of invalid receipt statement is submitted.\n * @param rcptPayload Raw payload with the receipt statement\n * @param rcptSignature Notary signature for the receipt statement\n */\n event InvalidReceipt(bytes rcptPayload, bytes rcptSignature);\n\n /**\n * @notice Emitted when a proof of invalid receipt report is submitted.\n * @param rrPayload Raw payload with report data\n * @param rrSignature Guard signature for the report\n */\n event InvalidReceiptReport(bytes rrPayload, bytes rrSignature);\n\n /**\n * @notice Emitted when a proof of invalid state in the signed attestation is submitted.\n * @param stateIndex Index of invalid state in the snapshot\n * @param statePayload Raw payload with state data\n * @param attPayload Raw payload with Attestation data for snapshot\n * @param attSignature Notary signature for the attestation\n */\n event InvalidStateWithAttestation(uint8 stateIndex, bytes statePayload, bytes attPayload, bytes attSignature);\n\n /**\n * @notice Emitted when a proof of invalid state in the signed snapshot is submitted.\n * @param stateIndex Index of invalid state in the snapshot\n * @param snapPayload Raw payload with snapshot data\n * @param snapSignature Agent signature for the snapshot\n */\n event InvalidStateWithSnapshot(uint8 stateIndex, bytes snapPayload, bytes snapSignature);\n\n /**\n * @notice Emitted when a proof of invalid state report is submitted.\n * @param srPayload Raw payload with report data\n * @param srSignature Guard signature for the report\n */\n event InvalidStateReport(bytes srPayload, bytes srSignature);\n}\n\n// contracts/interfaces/ISnapshotHub.sol\n\ninterface ISnapshotHub {\n /**\n * @notice Check that a given attestation is valid: matches the historical attestation\n * derived from an accepted Notary snapshot.\n * @dev Will revert if any of these is true:\n * - Attestation payload is not properly formatted.\n * @param attPayload Raw payload with attestation data\n * @return isValid Whether the provided attestation is valid\n */\n function isValidAttestation(bytes memory attPayload) external view returns (bool isValid);\n\n /**\n * @notice Returns saved attestation with the given nonce.\n * @dev Reverts if attestation with given nonce hasn't been created yet.\n * @param attNonce Nonce for the attestation\n * @return attPayload Raw payload with formatted Attestation data\n * @return agentRoot Agent root hash used for the attestation\n * @return snapGas Snapshot gas data used for the attestation\n */\n function getAttestation(uint32 attNonce)\n external\n view\n returns (bytes memory attPayload, bytes32 agentRoot, uint256[] memory snapGas);\n\n /**\n * @notice Returns the state with the highest known nonce submitted by a given Agent.\n * @param origin Domain of origin chain\n * @param agent Agent address\n * @return statePayload Raw payload with agent's latest state for origin\n */\n function getLatestAgentState(uint32 origin, address agent) external view returns (bytes memory statePayload);\n\n /**\n * @notice Returns latest saved attestation for a Notary.\n * @param notary Notary address\n * @return attPayload Raw payload with formatted Attestation data\n * @return agentRoot Agent root hash used for the attestation\n * @return snapGas Snapshot gas data used for the attestation\n */\n function getLatestNotaryAttestation(address notary)\n external\n view\n returns (bytes memory attPayload, bytes32 agentRoot, uint256[] memory snapGas);\n\n /**\n * @notice Returns Guard snapshot from the list of all accepted Guard snapshots.\n * @dev Reverts if snapshot with given index hasn't been accepted yet.\n * @param index Snapshot index in the list of all Guard snapshots\n * @return snapPayload Raw payload with Guard snapshot\n * @return snapSignature Raw payload with Guard signature for snapshot\n */\n function getGuardSnapshot(uint256 index)\n external\n view\n returns (bytes memory snapPayload, bytes memory snapSignature);\n\n /**\n * @notice Returns Notary snapshot from the list of all accepted Guard snapshots.\n * @dev Reverts if snapshot with given index hasn't been accepted yet.\n * @param index Snapshot index in the list of all Notary snapshots\n * @return snapPayload Raw payload with Notary snapshot\n * @return snapSignature Raw payload with Notary signature for snapshot\n */\n function getNotarySnapshot(uint256 index)\n external\n view\n returns (bytes memory snapPayload, bytes memory snapSignature);\n\n /**\n * @notice Returns Notary snapshot that was used for creating a given attestation.\n * @dev Reverts if any of these is true:\n * - Attestation payload is not properly formatted.\n * - Attestation is invalid (doesn't have a matching Notary snapshot).\n * @param attPayload Raw payload with attestation data\n * @return snapPayload Raw payload with Notary snapshot\n * @return snapSignature Raw payload with Notary signature for snapshot\n */\n function getNotarySnapshot(bytes memory attPayload)\n external\n view\n returns (bytes memory snapPayload, bytes memory snapSignature);\n\n /**\n * @notice Returns proof of inclusion of (root, origin) fields of a given snapshot's state\n * into the Snapshot Merkle Tree for a given attestation.\n * @dev Reverts if any of these is true:\n * - Attestation with given nonce hasn't been created yet.\n * - State index is out of range of snapshot list.\n * @param attNonce Nonce for the attestation\n * @param stateIndex Index of state in the attestation's snapshot\n * @return snapProof The snapshot proof\n */\n function getSnapshotProof(uint32 attNonce, uint8 stateIndex) external view returns (bytes32[] memory snapProof);\n}\n\n// contracts/interfaces/IStateHub.sol\n\ninterface IStateHub {\n /**\n * @notice Check that a given state is valid: matches the historical state of Origin contract.\n * Note: any Agent including an invalid state in their snapshot will be slashed\n * upon providing the snapshot and agent signature for it to Origin contract.\n * @dev Will revert if any of these is true:\n * - State payload is not properly formatted.\n * @param statePayload Raw payload with state data\n * @return isValid Whether the provided state is valid\n */\n function isValidState(bytes memory statePayload) external view returns (bool isValid);\n\n /**\n * @notice Returns the amount of saved states so far.\n * @dev This includes the initial state of \"empty Origin Merkle Tree\".\n */\n function statesAmount() external view returns (uint256);\n\n /**\n * @notice Suggest the data (state after latest sent message) to sign for an Agent.\n * Note: signing the suggested state data will will never lead to slashing of the actor,\n * assuming they have confirmed that the block, which number is included in the data,\n * is not subject to reorganization (which is different for every observed chain).\n * @return statePayload Raw payload with the latest state data\n */\n function suggestLatestState() external view returns (bytes memory statePayload);\n\n /**\n * @notice Given the historical nonce, suggest the state data to sign for an Agent.\n * Note: signing the suggested state data will will never lead to slashing of the actor,\n * assuming they have confirmed that the block, which number is included in the data,\n * is not subject to reorganization (which is different for every observed chain).\n * @param nonce Historical nonce to form a state\n * @return statePayload Raw payload with historical state data\n */\n function suggestState(uint32 nonce) external view returns (bytes memory statePayload);\n}\n\n// contracts/interfaces/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/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// node_modules/@openzeppelin/contracts/utils/math/Math.sol\n\n// OpenZeppelin Contracts (last updated v4.9.0) (utils/math/Math.sol)\n\n/**\n * @dev Standard math utilities missing in the Solidity language.\n */\nlibrary Math {\n enum Rounding {\n Down, // Toward negative infinity\n Up, // Toward infinity\n Zero // Toward zero\n }\n\n /**\n * @dev Returns the largest of two numbers.\n */\n function max(uint256 a, uint256 b) internal pure returns (uint256) {\n return a \u003e b ? a : b;\n }\n\n /**\n * @dev Returns the smallest of two numbers.\n */\n function min(uint256 a, uint256 b) internal pure returns (uint256) {\n return a \u003c b ? a : b;\n }\n\n /**\n * @dev Returns the average of two numbers. The result is rounded towards\n * zero.\n */\n function average(uint256 a, uint256 b) internal pure returns (uint256) {\n // (a + b) / 2 can overflow.\n return (a \u0026 b) + (a ^ b) / 2;\n }\n\n /**\n * @dev Returns the ceiling of the division of two numbers.\n *\n * This differs from standard division with `/` in that it rounds up instead\n * of rounding down.\n */\n function ceilDiv(uint256 a, uint256 b) internal pure returns (uint256) {\n // (a + b - 1) / b can overflow on addition, so we distribute.\n return a == 0 ? 0 : (a - 1) / b + 1;\n }\n\n /**\n * @notice Calculates floor(x * y / denominator) with full precision. Throws if result overflows a uint256 or denominator == 0\n * @dev Original credit to Remco Bloemen under MIT license (https://xn--2-umb.com/21/muldiv)\n * with further edits by Uniswap Labs also under MIT license.\n */\n function mulDiv(uint256 x, uint256 y, uint256 denominator) internal pure returns (uint256 result) {\n unchecked {\n // 512-bit multiply [prod1 prod0] = x * y. Compute the product mod 2^256 and mod 2^256 - 1, then use\n // use the Chinese Remainder Theorem to reconstruct the 512 bit result. The result is stored in two 256\n // variables such that product = prod1 * 2^256 + prod0.\n uint256 prod0; // Least significant 256 bits of the product\n uint256 prod1; // Most significant 256 bits of the product\n assembly {\n let mm := mulmod(x, y, not(0))\n prod0 := mul(x, y)\n prod1 := sub(sub(mm, prod0), lt(mm, prod0))\n }\n\n // Handle non-overflow cases, 256 by 256 division.\n if (prod1 == 0) {\n // Solidity will revert if denominator == 0, unlike the div opcode on its own.\n // The surrounding unchecked block does not change this fact.\n // See https://docs.soliditylang.org/en/latest/control-structures.html#checked-or-unchecked-arithmetic.\n return prod0 / denominator;\n }\n\n // Make sure the result is less than 2^256. Also prevents denominator == 0.\n require(denominator \u003e prod1, \"Math: mulDiv overflow\");\n\n ///////////////////////////////////////////////\n // 512 by 256 division.\n ///////////////////////////////////////////////\n\n // Make division exact by subtracting the remainder from [prod1 prod0].\n uint256 remainder;\n assembly {\n // Compute remainder using mulmod.\n remainder := mulmod(x, y, denominator)\n\n // Subtract 256 bit number from 512 bit number.\n prod1 := sub(prod1, gt(remainder, prod0))\n prod0 := sub(prod0, remainder)\n }\n\n // Factor powers of two out of denominator and compute largest power of two divisor of denominator. Always \u003e= 1.\n // See https://cs.stackexchange.com/q/138556/92363.\n\n // Does not overflow because the denominator cannot be zero at this stage in the function.\n uint256 twos = denominator \u0026 (~denominator + 1);\n assembly {\n // Divide denominator by twos.\n denominator := div(denominator, twos)\n\n // Divide [prod1 prod0] by twos.\n prod0 := div(prod0, twos)\n\n // Flip twos such that it is 2^256 / twos. If twos is zero, then it becomes one.\n twos := add(div(sub(0, twos), twos), 1)\n }\n\n // Shift in bits from prod1 into prod0.\n prod0 |= prod1 * twos;\n\n // Invert denominator mod 2^256. Now that denominator is an odd number, it has an inverse modulo 2^256 such\n // that denominator * inv = 1 mod 2^256. Compute the inverse by starting with a seed that is correct for\n // four bits. That is, denominator * inv = 1 mod 2^4.\n uint256 inverse = (3 * denominator) ^ 2;\n\n // Use the Newton-Raphson iteration to improve the precision. Thanks to Hensel's lifting lemma, this also works\n // in modular arithmetic, doubling the correct bits in each step.\n inverse *= 2 - denominator * inverse; // inverse mod 2^8\n inverse *= 2 - denominator * inverse; // inverse mod 2^16\n inverse *= 2 - denominator * inverse; // inverse mod 2^32\n inverse *= 2 - denominator * inverse; // inverse mod 2^64\n inverse *= 2 - denominator * inverse; // inverse mod 2^128\n inverse *= 2 - denominator * inverse; // inverse mod 2^256\n\n // Because the division is now exact we can divide by multiplying with the modular inverse of denominator.\n // This will give us the correct result modulo 2^256. Since the preconditions guarantee that the outcome is\n // less than 2^256, this is the final result. We don't need to compute the high bits of the result and prod1\n // is no longer required.\n result = prod0 * inverse;\n return result;\n }\n }\n\n /**\n * @notice Calculates x * y / denominator with full precision, following the selected rounding direction.\n */\n function mulDiv(uint256 x, uint256 y, uint256 denominator, Rounding rounding) internal pure returns (uint256) {\n uint256 result = mulDiv(x, y, denominator);\n if (rounding == Rounding.Up \u0026\u0026 mulmod(x, y, denominator) \u003e 0) {\n result += 1;\n }\n return result;\n }\n\n /**\n * @dev Returns the square root of a number. If the number is not a perfect square, the value is rounded down.\n *\n * Inspired by Henry S. Warren, Jr.'s \"Hacker's Delight\" (Chapter 11).\n */\n function sqrt(uint256 a) internal pure returns (uint256) {\n if (a == 0) {\n return 0;\n }\n\n // For our first guess, we get the biggest power of 2 which is smaller than the square root of the target.\n //\n // We know that the \"msb\" (most significant bit) of our target number `a` is a power of 2 such that we have\n // `msb(a) \u003c= a \u003c 2*msb(a)`. This value can be written `msb(a)=2**k` with `k=log2(a)`.\n //\n // This can be rewritten `2**log2(a) \u003c= a \u003c 2**(log2(a) + 1)`\n // → `sqrt(2**k) \u003c= sqrt(a) \u003c sqrt(2**(k+1))`\n // → `2**(k/2) \u003c= sqrt(a) \u003c 2**((k+1)/2) \u003c= 2**(k/2 + 1)`\n //\n // Consequently, `2**(log2(a) / 2)` is a good first approximation of `sqrt(a)` with at least 1 correct bit.\n uint256 result = 1 \u003c\u003c (log2(a) \u003e\u003e 1);\n\n // At this point `result` is an estimation with one bit of precision. We know the true value is a uint128,\n // since it is the square root of a uint256. Newton's method converges quadratically (precision doubles at\n // every iteration). We thus need at most 7 iteration to turn our partial result with one bit of precision\n // into the expected uint128 result.\n unchecked {\n result = (result + a / result) \u003e\u003e 1;\n result = (result + a / result) \u003e\u003e 1;\n result = (result + a / result) \u003e\u003e 1;\n result = (result + a / result) \u003e\u003e 1;\n result = (result + a / result) \u003e\u003e 1;\n result = (result + a / result) \u003e\u003e 1;\n result = (result + a / result) \u003e\u003e 1;\n return min(result, a / result);\n }\n }\n\n /**\n * @notice Calculates sqrt(a), following the selected rounding direction.\n */\n function sqrt(uint256 a, Rounding rounding) internal pure returns (uint256) {\n unchecked {\n uint256 result = sqrt(a);\n return result + (rounding == Rounding.Up \u0026\u0026 result * result \u003c a ? 1 : 0);\n }\n }\n\n /**\n * @dev Return the log in base 2, rounded down, of a positive value.\n * Returns 0 if given 0.\n */\n function log2(uint256 value) internal pure returns (uint256) {\n uint256 result = 0;\n unchecked {\n if (value \u003e\u003e 128 \u003e 0) {\n value \u003e\u003e= 128;\n result += 128;\n }\n if (value \u003e\u003e 64 \u003e 0) {\n value \u003e\u003e= 64;\n result += 64;\n }\n if (value \u003e\u003e 32 \u003e 0) {\n value \u003e\u003e= 32;\n result += 32;\n }\n if (value \u003e\u003e 16 \u003e 0) {\n value \u003e\u003e= 16;\n result += 16;\n }\n if (value \u003e\u003e 8 \u003e 0) {\n value \u003e\u003e= 8;\n result += 8;\n }\n if (value \u003e\u003e 4 \u003e 0) {\n value \u003e\u003e= 4;\n result += 4;\n }\n if (value \u003e\u003e 2 \u003e 0) {\n value \u003e\u003e= 2;\n result += 2;\n }\n if (value \u003e\u003e 1 \u003e 0) {\n result += 1;\n }\n }\n return result;\n }\n\n /**\n * @dev Return the log in base 2, following the selected rounding direction, of a positive value.\n * Returns 0 if given 0.\n */\n function log2(uint256 value, Rounding rounding) internal pure returns (uint256) {\n unchecked {\n uint256 result = log2(value);\n return result + (rounding == Rounding.Up \u0026\u0026 1 \u003c\u003c result \u003c value ? 1 : 0);\n }\n }\n\n /**\n * @dev Return the log in base 10, rounded down, of a positive value.\n * Returns 0 if given 0.\n */\n function log10(uint256 value) internal pure returns (uint256) {\n uint256 result = 0;\n unchecked {\n if (value \u003e= 10 ** 64) {\n value /= 10 ** 64;\n result += 64;\n }\n if (value \u003e= 10 ** 32) {\n value /= 10 ** 32;\n result += 32;\n }\n if (value \u003e= 10 ** 16) {\n value /= 10 ** 16;\n result += 16;\n }\n if (value \u003e= 10 ** 8) {\n value /= 10 ** 8;\n result += 8;\n }\n if (value \u003e= 10 ** 4) {\n value /= 10 ** 4;\n result += 4;\n }\n if (value \u003e= 10 ** 2) {\n value /= 10 ** 2;\n result += 2;\n }\n if (value \u003e= 10 ** 1) {\n result += 1;\n }\n }\n return result;\n }\n\n /**\n * @dev Return the log in base 10, following the selected rounding direction, of a positive value.\n * Returns 0 if given 0.\n */\n function log10(uint256 value, Rounding rounding) internal pure returns (uint256) {\n unchecked {\n uint256 result = log10(value);\n return result + (rounding == Rounding.Up \u0026\u0026 10 ** result \u003c value ? 1 : 0);\n }\n }\n\n /**\n * @dev Return the log in base 256, rounded down, of a positive value.\n * Returns 0 if given 0.\n *\n * Adding one to the result gives the number of pairs of hex symbols needed to represent `value` as a hex string.\n */\n function log256(uint256 value) internal pure returns (uint256) {\n uint256 result = 0;\n unchecked {\n if (value \u003e\u003e 128 \u003e 0) {\n value \u003e\u003e= 128;\n result += 16;\n }\n if (value \u003e\u003e 64 \u003e 0) {\n value \u003e\u003e= 64;\n result += 8;\n }\n if (value \u003e\u003e 32 \u003e 0) {\n value \u003e\u003e= 32;\n result += 4;\n }\n if (value \u003e\u003e 16 \u003e 0) {\n value \u003e\u003e= 16;\n result += 2;\n }\n if (value \u003e\u003e 8 \u003e 0) {\n result += 1;\n }\n }\n return result;\n }\n\n /**\n * @dev Return the log in base 256, following the selected rounding direction, of a positive value.\n * Returns 0 if given 0.\n */\n function log256(uint256 value, Rounding rounding) internal pure returns (uint256) {\n unchecked {\n uint256 result = log256(value);\n return result + (rounding == Rounding.Up \u0026\u0026 1 \u003c\u003c (result \u003c\u003c 3) \u003c value ? 1 : 0);\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/utils/math/SignedMath.sol\n\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/math/SignedMath.sol)\n\n/**\n * @dev Standard signed math utilities missing in the Solidity language.\n */\nlibrary SignedMath {\n /**\n * @dev Returns the largest of two signed numbers.\n */\n function max(int256 a, int256 b) internal pure returns (int256) {\n return a \u003e b ? a : b;\n }\n\n /**\n * @dev Returns the smallest of two signed numbers.\n */\n function min(int256 a, int256 b) internal pure returns (int256) {\n return a \u003c b ? a : b;\n }\n\n /**\n * @dev Returns the average of two signed numbers without overflow.\n * The result is rounded towards zero.\n */\n function average(int256 a, int256 b) internal pure returns (int256) {\n // Formula from the book \"Hacker's Delight\"\n int256 x = (a \u0026 b) + ((a ^ b) \u003e\u003e 1);\n return x + (int256(uint256(x) \u003e\u003e 255) \u0026 (a ^ b));\n }\n\n /**\n * @dev Returns the absolute unsigned value of a signed value.\n */\n function abs(int256 n) internal pure returns (uint256) {\n unchecked {\n // must be unchecked in order to support `n = type(int256).min`\n return uint256(n \u003e= 0 ? n : -n);\n }\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// 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/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/InterfaceSummit.sol\n\ninterface InterfaceSummit {\n // ══════════════════════════════════════════ ACCEPT AGENT STATEMENTS ══════════════════════════════════════════════\n\n /**\n * @notice Accepts a receipt, which local `AgentManager` verified to have been signed by an active Notary.\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 * - Notary who signed the receipt is referenced as the \"Receipt Notary\".\n * - Notary who signed the attestation on destination chain is referenced as the \"Attestation Notary\".\n * \u003e Will revert if any of these is true:\n * \u003e - Called by anyone other than local `AgentManager`.\n * \u003e - Receipt body payload is not properly formatted.\n * \u003e - Receipt signer is in Dispute.\n * \u003e - Receipt's snapshot root is unknown.\n * @param rcptNotaryIndex Index of Receipt Notary in Agent Merkle Tree\n * @param attNotaryIndex Index of Attestation Notary in Agent Merkle Tree\n * @param sigIndex Index of stored Notary signature\n * @param attNonce Nonce of the attestation used for proving the executed message\n * @param paddedTips Padded encoded paid tips information\n * @param rcptPayload Raw payload with message execution receipt\n * @return wasAccepted Whether the receipt was accepted\n */\n function acceptReceipt(\n uint32 rcptNotaryIndex,\n uint32 attNotaryIndex,\n uint256 sigIndex,\n uint32 attNonce,\n uint256 paddedTips,\n bytes memory rcptPayload\n ) external returns (bool wasAccepted);\n\n /**\n * @notice Accepts a snapshot, which local `AgentManager` verified to have been signed by an active Guard.\n * \u003e Snapshot is a list of states for a set of Origin contracts residing on any of the chains.\n * All the states in the Guard-signed snapshot become available for Notary signing.\n * \u003e Will revert if any of these is true:\n * \u003e - Called by anyone other than local `AgentManager`.\n * \u003e - Snapshot payload is not properly formatted.\n * \u003e - Snapshot contains a state older then the Guard has previously submitted.\n * @param guardIndex Index of Guard in Agent Merkle Tree\n * @param sigIndex Index of stored Agent signature\n * @param snapPayload Raw payload with snapshot data\n */\n function acceptGuardSnapshot(uint32 guardIndex, uint256 sigIndex, bytes memory snapPayload) external;\n\n /**\n * @notice Accepts a snapshot, which local `AgentManager` verified to have been signed by an active Notary.\n * \u003e Snapshot is a list of states for a set of Origin contracts residing on any of the chains.\n * Snapshot Merkle Root is calculated and saved for valid snapshots, i.e.\n * snapshots which are only using states previously submitted by any of the Guards.\n * - Notary could use states singed by the same of different Guards 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 - Called by anyone other than local `AgentManager`.\n * \u003e - Snapshot payload is not properly formatted.\n * \u003e - Snapshot contains a state older then the Notary has previously submitted.\n * \u003e - Snapshot contains a state that no Guard has previously submitted.\n * @param notaryIndex Index of Notary in Agent Merkle Tree\n * @param sigIndex Index of stored Agent signature\n * @param agentRoot Current root of the Agent Merkle Tree\n * @param snapPayload Raw payload with snapshot data\n * @return attPayload Raw payload with data for attestation derived from Notary snapshot.\n */\n function acceptNotarySnapshot(uint32 notaryIndex, uint256 sigIndex, bytes32 agentRoot, bytes memory snapPayload)\n external\n returns (bytes memory attPayload);\n\n // ════════════════════════════════════════════════ TIPS LOGIC ═════════════════════════════════════════════════════\n\n /**\n * @notice Distributes tips using the first Receipt from the \"receipt quarantine queue\".\n * Possible scenarios:\n * - Receipt queue is empty =\u003e does nothing\n * - Receipt optimistic period is not over =\u003e does nothing\n * - Either of Notaries present in Receipt was slashed =\u003e receipt is deleted from the queue\n * - Either of Notaries present in Receipt in Dispute =\u003e receipt is moved to the end of queue\n * - None of the above =\u003e receipt tips are distributed\n * @dev Returned value makes it possible to do the following: `while (distributeTips()) {}`\n * @return queuePopped Whether the first element was popped from the queue\n */\n function distributeTips() external returns (bool queuePopped);\n\n /**\n * @notice Withdraws locked base message tips from requested domain Origin to the recipient.\n * This is done by a call to a local Origin contract, or by a manager message to the remote chain.\n * @dev This will revert, if the pending balance of origin tips (earned-claimed) is lower than requested.\n * @param origin Domain of chain to withdraw tips on\n * @param amount Amount of tips to withdraw\n */\n function withdrawTips(uint32 origin, uint256 amount) external;\n\n // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════\n\n /**\n * @notice Returns earned and claimed tips for the actor.\n * Note: Tips for address(0) belong to the Treasury.\n * @param actor Address of the actor\n * @param origin Domain where the tips were initially paid\n * @return earned Total amount of origin tips the actor has earned so far\n * @return claimed Total amount of origin tips the actor has claimed so far\n */\n function actorTips(address actor, uint32 origin) external view returns (uint128 earned, uint128 claimed);\n\n /**\n * @notice Returns the amount of receipts in the \"Receipt Quarantine Queue\".\n */\n function receiptQueueLength() external view returns (uint256);\n\n /**\n * @notice Returns the state with the highest known nonce\n * submitted by any of the currently active Guards.\n * @param origin Domain of origin chain\n * @return statePayload Raw payload with latest active Guard state for origin\n */\n function getLatestState(uint32 origin) external view returns (bytes memory statePayload);\n}\n\n// node_modules/@openzeppelin/contracts/utils/Strings.sol\n\n// OpenZeppelin Contracts (last updated v4.9.0) (utils/Strings.sol)\n\n/**\n * @dev String operations.\n */\nlibrary Strings {\n bytes16 private constant _SYMBOLS = \"0123456789abcdef\";\n uint8 private constant _ADDRESS_LENGTH = 20;\n\n /**\n * @dev Converts a `uint256` to its ASCII `string` decimal representation.\n */\n function toString(uint256 value) internal pure returns (string memory) {\n unchecked {\n uint256 length = Math.log10(value) + 1;\n string memory buffer = new string(length);\n uint256 ptr;\n /// @solidity memory-safe-assembly\n assembly {\n ptr := add(buffer, add(32, length))\n }\n while (true) {\n ptr--;\n /// @solidity memory-safe-assembly\n assembly {\n mstore8(ptr, byte(mod(value, 10), _SYMBOLS))\n }\n value /= 10;\n if (value == 0) break;\n }\n return buffer;\n }\n }\n\n /**\n * @dev Converts a `int256` to its ASCII `string` decimal representation.\n */\n function toString(int256 value) internal pure returns (string memory) {\n return string(abi.encodePacked(value \u003c 0 ? \"-\" : \"\", toString(SignedMath.abs(value))));\n }\n\n /**\n * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation.\n */\n function toHexString(uint256 value) internal pure returns (string memory) {\n unchecked {\n return toHexString(value, Math.log256(value) + 1);\n }\n }\n\n /**\n * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length.\n */\n function toHexString(uint256 value, uint256 length) internal pure returns (string memory) {\n bytes memory buffer = new bytes(2 * length + 2);\n buffer[0] = \"0\";\n buffer[1] = \"x\";\n for (uint256 i = 2 * length + 1; i \u003e 1; --i) {\n buffer[i] = _SYMBOLS[value \u0026 0xf];\n value \u003e\u003e= 4;\n }\n require(value == 0, \"Strings: hex length insufficient\");\n return string(buffer);\n }\n\n /**\n * @dev Converts an `address` with fixed length of 20 bytes to its not checksummed ASCII `string` hexadecimal representation.\n */\n function toHexString(address addr) internal pure returns (string memory) {\n return toHexString(uint256(uint160(addr)), _ADDRESS_LENGTH);\n }\n\n /**\n * @dev Returns true if the two strings are equal.\n */\n function equal(string memory a, string memory b) internal pure returns (bool) {\n return keccak256(bytes(a)) == keccak256(bytes(b));\n }\n}\n\n// node_modules/@openzeppelin/contracts-upgradeable/utils/ContextUpgradeable.sol\n\n// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)\n\n/**\n * @dev Provides information about the current execution context, including the\n * sender of the transaction and its data. While these are generally available\n * via msg.sender and msg.data, they should not be accessed in such a direct\n * manner, since when dealing with meta-transactions the account sending and\n * paying for execution may not be the actual sender (as far as an application\n * is concerned).\n *\n * This contract is only required for intermediate, library-like contracts.\n */\nabstract contract ContextUpgradeable is Initializable {\n function __Context_init() internal onlyInitializing {\n }\n\n function __Context_init_unchained() internal onlyInitializing {\n }\n function _msgSender() internal view virtual returns (address) {\n return msg.sender;\n }\n\n function _msgData() internal view virtual returns (bytes calldata) {\n return msg.data;\n }\n\n /**\n * @dev This empty reserved space is put in place to allow future versions to add new\n * variables without shifting down storage in the inheritance chain.\n * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\n */\n uint256[50] private __gap;\n}\n\n// contracts/libs/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/utils/cryptography/ECDSA.sol\n\n// OpenZeppelin Contracts (last updated v4.9.0) (utils/cryptography/ECDSA.sol)\n\n/**\n * @dev Elliptic Curve Digital Signature Algorithm (ECDSA) operations.\n *\n * These functions can be used to verify that a message was signed by the holder\n * of the private keys of a given address.\n */\nlibrary ECDSA {\n enum RecoverError {\n NoError,\n InvalidSignature,\n InvalidSignatureLength,\n InvalidSignatureS,\n InvalidSignatureV // Deprecated in v4.8\n }\n\n function _throwError(RecoverError error) private pure {\n if (error == RecoverError.NoError) {\n return; // no error: do nothing\n } else if (error == RecoverError.InvalidSignature) {\n revert(\"ECDSA: invalid signature\");\n } else if (error == RecoverError.InvalidSignatureLength) {\n revert(\"ECDSA: invalid signature length\");\n } else if (error == RecoverError.InvalidSignatureS) {\n revert(\"ECDSA: invalid signature 's' value\");\n }\n }\n\n /**\n * @dev Returns the address that signed a hashed message (`hash`) with\n * `signature` or error string. This address can then be used for verification purposes.\n *\n * The `ecrecover` EVM opcode allows for malleable (non-unique) signatures:\n * this function rejects them by requiring the `s` value to be in the lower\n * half order, and the `v` value to be either 27 or 28.\n *\n * IMPORTANT: `hash` _must_ be the result of a hash operation for the\n * verification to be secure: it is possible to craft signatures that\n * recover to arbitrary addresses for non-hashed data. A safe way to ensure\n * this is by receiving a hash of the original message (which may otherwise\n * be too long), and then calling {toEthSignedMessageHash} on it.\n *\n * Documentation for signature generation:\n * - with https://web3js.readthedocs.io/en/v1.3.4/web3-eth-accounts.html#sign[Web3.js]\n * - with https://docs.ethers.io/v5/api/signer/#Signer-signMessage[ethers]\n *\n * _Available since v4.3._\n */\n function tryRecover(bytes32 hash, bytes memory signature) internal pure returns (address, RecoverError) {\n if (signature.length == 65) {\n bytes32 r;\n bytes32 s;\n uint8 v;\n // ecrecover takes the signature parameters, and the only way to get them\n // currently is to use assembly.\n /// @solidity memory-safe-assembly\n assembly {\n r := mload(add(signature, 0x20))\n s := mload(add(signature, 0x40))\n v := byte(0, mload(add(signature, 0x60)))\n }\n return tryRecover(hash, v, r, s);\n } else {\n return (address(0), RecoverError.InvalidSignatureLength);\n }\n }\n\n /**\n * @dev Returns the address that signed a hashed message (`hash`) with\n * `signature`. This address can then be used for verification purposes.\n *\n * The `ecrecover` EVM opcode allows for malleable (non-unique) signatures:\n * this function rejects them by requiring the `s` value to be in the lower\n * half order, and the `v` value to be either 27 or 28.\n *\n * IMPORTANT: `hash` _must_ be the result of a hash operation for the\n * verification to be secure: it is possible to craft signatures that\n * recover to arbitrary addresses for non-hashed data. A safe way to ensure\n * this is by receiving a hash of the original message (which may otherwise\n * be too long), and then calling {toEthSignedMessageHash} on it.\n */\n function recover(bytes32 hash, bytes memory signature) internal pure returns (address) {\n (address recovered, RecoverError error) = tryRecover(hash, signature);\n _throwError(error);\n return recovered;\n }\n\n /**\n * @dev Overload of {ECDSA-tryRecover} that receives the `r` and `vs` short-signature fields separately.\n *\n * See https://eips.ethereum.org/EIPS/eip-2098[EIP-2098 short signatures]\n *\n * _Available since v4.3._\n */\n function tryRecover(bytes32 hash, bytes32 r, bytes32 vs) internal pure returns (address, RecoverError) {\n bytes32 s = vs \u0026 bytes32(0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff);\n uint8 v = uint8((uint256(vs) \u003e\u003e 255) + 27);\n return tryRecover(hash, v, r, s);\n }\n\n /**\n * @dev Overload of {ECDSA-recover} that receives the `r and `vs` short-signature fields separately.\n *\n * _Available since v4.2._\n */\n function recover(bytes32 hash, bytes32 r, bytes32 vs) internal pure returns (address) {\n (address recovered, RecoverError error) = tryRecover(hash, r, vs);\n _throwError(error);\n return recovered;\n }\n\n /**\n * @dev Overload of {ECDSA-tryRecover} that receives the `v`,\n * `r` and `s` signature fields separately.\n *\n * _Available since v4.3._\n */\n function tryRecover(bytes32 hash, uint8 v, bytes32 r, bytes32 s) internal pure returns (address, RecoverError) {\n // EIP-2 still allows signature malleability for ecrecover(). Remove this possibility and make the signature\n // unique. Appendix F in the Ethereum Yellow paper (https://ethereum.github.io/yellowpaper/paper.pdf), defines\n // the valid range for s in (301): 0 \u003c s \u003c secp256k1n ÷ 2 + 1, and for v in (302): v ∈ {27, 28}. Most\n // signatures from current libraries generate a unique signature with an s-value in the lower half order.\n //\n // If your library generates malleable signatures, such as s-values in the upper range, calculate a new s-value\n // with 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141 - s1 and flip v from 27 to 28 or\n // vice versa. If your library also generates signatures with 0/1 for v instead 27/28, add 27 to v to accept\n // these malleable signatures as well.\n if (uint256(s) \u003e 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0) {\n return (address(0), RecoverError.InvalidSignatureS);\n }\n\n // If the signature is valid (and not malleable), return the signer address\n address signer = ecrecover(hash, v, r, s);\n if (signer == address(0)) {\n return (address(0), RecoverError.InvalidSignature);\n }\n\n return (signer, RecoverError.NoError);\n }\n\n /**\n * @dev Overload of {ECDSA-recover} that receives the `v`,\n * `r` and `s` signature fields separately.\n */\n function recover(bytes32 hash, uint8 v, bytes32 r, bytes32 s) internal pure returns (address) {\n (address recovered, RecoverError error) = tryRecover(hash, v, r, s);\n _throwError(error);\n return recovered;\n }\n\n /**\n * @dev Returns an Ethereum Signed Message, created from a `hash`. This\n * produces hash corresponding to the one signed with the\n * https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`]\n * JSON-RPC method as part of EIP-191.\n *\n * See {recover}.\n */\n function toEthSignedMessageHash(bytes32 hash) internal pure returns (bytes32 message) {\n // 32 is the length in bytes of hash,\n // enforced by the type signature above\n /// @solidity memory-safe-assembly\n assembly {\n mstore(0x00, \"\\x19Ethereum Signed Message:\\n32\")\n mstore(0x1c, hash)\n message := keccak256(0x00, 0x3c)\n }\n }\n\n /**\n * @dev Returns an Ethereum Signed Message, created from `s`. This\n * produces hash corresponding to the one signed with the\n * https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`]\n * JSON-RPC method as part of EIP-191.\n *\n * See {recover}.\n */\n function toEthSignedMessageHash(bytes memory s) internal pure returns (bytes32) {\n return keccak256(abi.encodePacked(\"\\x19Ethereum Signed Message:\\n\", Strings.toString(s.length), s));\n }\n\n /**\n * @dev Returns an Ethereum Signed Typed Data, created from a\n * `domainSeparator` and a `structHash`. This produces hash corresponding\n * to the one signed with the\n * https://eips.ethereum.org/EIPS/eip-712[`eth_signTypedData`]\n * JSON-RPC method as part of EIP-712.\n *\n * See {recover}.\n */\n function toTypedDataHash(bytes32 domainSeparator, bytes32 structHash) internal pure returns (bytes32 data) {\n /// @solidity memory-safe-assembly\n assembly {\n let ptr := mload(0x40)\n mstore(ptr, \"\\x19\\x01\")\n mstore(add(ptr, 0x02), domainSeparator)\n mstore(add(ptr, 0x22), structHash)\n data := keccak256(ptr, 0x42)\n }\n }\n\n /**\n * @dev Returns an Ethereum Signed Data with intended validator, created from a\n * `validator` and `data` according to the version 0 of EIP-191.\n *\n * See {recover}.\n */\n function toDataWithIntendedValidatorHash(address validator, bytes memory data) internal pure returns (bytes32) {\n return keccak256(abi.encodePacked(\"\\x19\\x00\", validator, data));\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/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/inbox/StatementInbox.sol\n\n// ══════════════════════════════ LIBRARY IMPORTS ══════════════════════════════\n\n// ═════════════════════════════ INTERNAL IMPORTS ══════════════════════════════\n\n// ═════════════════════════════ EXTERNAL IMPORTS ══════════════════════════════\n\n/// @notice `StatementInbox` is the entry point for all agent-signed statements. It verifies the\n/// agent signatures, and passes the unsigned statements to the contract to consume it via `acceptX` functions. Is is\n/// also used to verify the agent-signed statements and initiate the agent slashing, should the statement be invalid.\n/// `StatementInbox` is responsible for the following:\n/// - Accepting State and Receipt Reports to initiate a dispute between Guard and Notary.\n/// - Storing all the Guard Reports with the Guard signature leading to a dispute.\n/// - Verifying State/State Reports referencing the local chain and slashing the signer if statement is invalid.\n/// - Verifying Receipt/Receipt Reports referencing the local chain and slashing the signer if statement is invalid.\nabstract contract StatementInbox is MessagingBase, StatementInboxEvents, IStatementInbox {\n using AttestationLib for bytes;\n using ReceiptLib for bytes;\n using StateLib for bytes;\n using SnapshotLib for bytes;\n\n struct StoredReport {\n uint256 sigIndex;\n bytes statementPayload;\n }\n\n // ══════════════════════════════════════════════════ STORAGE ══════════════════════════════════════════════════════\n\n address public agentManager;\n address public origin;\n address public destination;\n\n // TODO: optimize this\n bytes[] internal _storedSignatures;\n StoredReport[] internal _storedReports;\n\n /// @dev gap for upgrade safety\n uint256[45] private __GAP; // solhint-disable-line var-name-mixedcase\n\n // ════════════════════════════════════════════════ INITIALIZER ════════════════════════════════════════════════════\n\n /// @dev Initializes the contract:\n /// - Sets up `msg.sender` as the owner of the contract.\n /// - Sets up `agentManager`, `origin`, and `destination`.\n // solhint-disable-next-line func-name-mixedcase\n function __StatementInbox_init(address agentManager_, address origin_, address destination_)\n internal\n onlyInitializing\n {\n agentManager = agentManager_;\n origin = origin_;\n destination = destination_;\n __Ownable2Step_init();\n }\n\n // ══════════════════════════════════════════ SUBMIT AGENT STATEMENTS ══════════════════════════════════════════════\n\n /// @inheritdoc IStatementInbox\n // solhint-disable-next-line ordering\n function submitStateReportWithSnapshot(\n uint8 stateIndex,\n bytes memory srSignature,\n bytes memory snapPayload,\n bytes memory snapSignature\n ) external returns (bool wasAccepted) {\n // This will revert if payload is not a snapshot\n Snapshot snapshot = snapPayload.castToSnapshot();\n // This will revert if the snapshot signer is not a known Notary\n (AgentStatus memory notaryStatus,) =\n _verifySnapshot({snapshot: snapshot, snapSignature: snapSignature, verifyNotary: true});\n // Notary needs to be Active/Unstaking\n notaryStatus.verifyActiveUnstaking();\n // Check if Notary is active on this chain\n _verifyNotaryDomain(notaryStatus.domain);\n // This will revert if state index is out of range\n State state = snapshot.state(stateIndex);\n // This will revert if the report signer is not an known Guard\n (AgentStatus memory guardStatus,) = _verifyStateReport(state, srSignature);\n // Check that Guard is active\n guardStatus.verifyActive();\n _saveReport(state.unwrap().clone(), srSignature);\n // This will revert if either actor is already in dispute\n IAgentManager(agentManager).openDispute(guardStatus.index, notaryStatus.index);\n return true;\n }\n\n /// @inheritdoc IStatementInbox\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 // This will revert if payload is not a snapshot\n Snapshot snapshot = snapPayload.castToSnapshot();\n // This will revert if state index is out of range\n State state = snapshot.state(stateIndex);\n // This will revert if the report signer is not an known Guard\n (AgentStatus memory guardStatus,) = _verifyStateReport(state, srSignature);\n // Check that Guard is active\n guardStatus.verifyActive();\n // This will revert if payload is not an attestation\n Attestation att = attPayload.castToAttestation();\n // This will revert if signer is not an known Notary\n (AgentStatus memory notaryStatus,) = _verifyAttestation(att, attSignature);\n // Notary needs to be Active/Unstaking\n notaryStatus.verifyActiveUnstaking();\n // Check if Notary is active on this chain\n _verifyNotaryDomain(notaryStatus.domain);\n if (snapshot.calculateRoot() != att.snapRoot()) revert IncorrectSnapshotRoot();\n _saveReport(state.unwrap().clone(), srSignature);\n // This will revert if either actor is already in dispute\n IAgentManager(agentManager).openDispute(guardStatus.index, notaryStatus.index);\n return true;\n }\n\n /// @inheritdoc IStatementInbox\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 // This will revert if payload is not a state\n State state = statePayload.castToState();\n // This will revert if the report signer is not an known Guard\n (AgentStatus memory guardStatus,) = _verifyStateReport(state, srSignature);\n // Check that Guard is active\n guardStatus.verifyActive();\n // This will revert if payload is not an attestation\n Attestation att = attPayload.castToAttestation();\n // This will revert if signer is not a known Notary\n (AgentStatus memory notaryStatus,) = _verifyAttestation(att, attSignature);\n // Notary needs to be Active/Unstaking\n notaryStatus.verifyActiveUnstaking();\n // Check if Notary is active on this chain\n _verifyNotaryDomain(notaryStatus.domain);\n // This will revert if any of these is true:\n // - Attestation root is not equal to Merkle Root derived from State and Snapshot Proof.\n // - Snapshot Proof's first element does not match the State metadata.\n // - Snapshot Proof length exceeds Snapshot tree Height.\n // - State index is out of range.\n _verifySnapshotMerkle(att, stateIndex, state, snapProof);\n _saveReport(statePayload, srSignature);\n // This will revert if either actor is already in dispute\n IAgentManager(agentManager).openDispute(guardStatus.index, notaryStatus.index);\n return true;\n }\n\n // ══════════════════════════════════════════ VERIFY AGENT STATEMENTS ══════════════════════════════════════════════\n\n /// @inheritdoc IStatementInbox\n function verifyReceipt(bytes memory rcptPayload, bytes memory rcptSignature)\n external\n returns (bool isValidReceipt)\n {\n // This will revert if payload is not a receipt\n Receipt rcpt = rcptPayload.castToReceipt();\n // This will revert if the attestation signer is not a known Notary\n (AgentStatus memory status, address notary) = _verifyReceipt(rcpt, rcptSignature);\n // Notary needs to be Active/Unstaking\n status.verifyActiveUnstaking();\n isValidReceipt = IExecutionHub(destination).isValidReceipt(rcptPayload);\n if (!isValidReceipt) {\n emit InvalidReceipt(rcptPayload, rcptSignature);\n IAgentManager(agentManager).slashAgent(status.domain, notary, msg.sender);\n }\n }\n\n /// @inheritdoc IStatementInbox\n function verifyReceiptReport(bytes memory rcptPayload, bytes memory rrSignature)\n external\n returns (bool isValidReport)\n {\n // This will revert if payload is not a receipt\n Receipt rcpt = rcptPayload.castToReceipt();\n // This will revert if the report signer is not a known Guard\n (AgentStatus memory status, address guard) = _verifyReceiptReport(rcpt, rrSignature);\n // Guard needs to be Active/Unstaking\n status.verifyActiveUnstaking();\n // Report is valid IF AND ONLY IF the reported receipt in invalid\n isValidReport = !IExecutionHub(destination).isValidReceipt(rcptPayload);\n if (!isValidReport) {\n emit InvalidReceiptReport(rcptPayload, rrSignature);\n IAgentManager(agentManager).slashAgent(status.domain, guard, msg.sender);\n }\n }\n\n /// @inheritdoc IStatementInbox\n function verifyStateWithAttestation(\n uint8 stateIndex,\n bytes memory snapPayload,\n bytes memory attPayload,\n bytes memory attSignature\n ) external returns (bool isValidState) {\n // This will revert if payload is not an attestation\n Attestation att = attPayload.castToAttestation();\n // This will revert if the attestation signer is not a known Notary\n (AgentStatus memory status, address notary) = _verifyAttestation(att, attSignature);\n // Notary needs to be Active/Unstaking\n status.verifyActiveUnstaking();\n // This will revert if payload is not a snapshot\n Snapshot snapshot = snapPayload.castToSnapshot();\n if (snapshot.calculateRoot() != att.snapRoot()) revert IncorrectSnapshotRoot();\n // This will revert if state does not refer to this chain\n bytes memory statePayload = snapshot.state(stateIndex).unwrap().clone();\n isValidState = IStateHub(origin).isValidState(statePayload);\n if (!isValidState) {\n emit InvalidStateWithAttestation(stateIndex, statePayload, attPayload, attSignature);\n IAgentManager(agentManager).slashAgent(status.domain, notary, msg.sender);\n }\n }\n\n /// @inheritdoc IStatementInbox\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 // This will revert if payload is not an attestation\n Attestation att = attPayload.castToAttestation();\n // This will revert if the attestation signer is not a known Notary\n (AgentStatus memory status, address notary) = _verifyAttestation(att, attSignature);\n // Notary needs to be Active/Unstaking\n status.verifyActiveUnstaking();\n // This will revert if payload is not a state\n State state = statePayload.castToState();\n // This will revert if any of these is true:\n // - Attestation root is not equal to Merkle Root derived from State and Snapshot Proof.\n // - Snapshot Proof's first element does not match the State metadata.\n // - Snapshot Proof length exceeds Snapshot tree Height.\n // - State index is out of range.\n _verifySnapshotMerkle(att, stateIndex, state, snapProof);\n // This will revert if state does not refer to this chain\n isValidState = IStateHub(origin).isValidState(statePayload);\n if (!isValidState) {\n emit InvalidStateWithAttestation(stateIndex, statePayload, attPayload, attSignature);\n IAgentManager(agentManager).slashAgent(status.domain, notary, msg.sender);\n }\n }\n\n /// @inheritdoc IStatementInbox\n function verifyStateWithSnapshot(uint8 stateIndex, bytes memory snapPayload, bytes memory snapSignature)\n external\n returns (bool isValidState)\n {\n // This will revert if payload is not a snapshot\n Snapshot snapshot = snapPayload.castToSnapshot();\n // This will revert if the snapshot signer is not a known Guard/Notary\n (AgentStatus memory status, address agent) =\n _verifySnapshot({snapshot: snapshot, snapSignature: snapSignature, verifyNotary: false});\n // Agent needs to be Active/Unstaking\n status.verifyActiveUnstaking();\n // This will revert if state does not refer to this chain\n isValidState = IStateHub(origin).isValidState(snapshot.state(stateIndex).unwrap().clone());\n if (!isValidState) {\n emit InvalidStateWithSnapshot(stateIndex, snapPayload, snapSignature);\n IAgentManager(agentManager).slashAgent(status.domain, agent, msg.sender);\n }\n }\n\n /// @inheritdoc IStatementInbox\n function verifyStateReport(bytes memory statePayload, bytes memory srSignature)\n external\n returns (bool isValidReport)\n {\n // This will revert if payload is not a state\n State state = statePayload.castToState();\n // This will revert if the report signer is not a known Guard\n (AgentStatus memory status, address guard) = _verifyStateReport(state, srSignature);\n // Guard needs to be Active/Unstaking\n status.verifyActiveUnstaking();\n // Report is valid IF AND ONLY IF the reported state in invalid\n // This will revert if the reported state does not refer to this chain\n isValidReport = !IStateHub(origin).isValidState(statePayload);\n if (!isValidReport) {\n emit InvalidStateReport(statePayload, srSignature);\n IAgentManager(agentManager).slashAgent(status.domain, guard, msg.sender);\n }\n }\n\n // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════\n\n /// @inheritdoc IStatementInbox\n function getReportsAmount() external view returns (uint256) {\n return _storedReports.length;\n }\n\n /// @inheritdoc IStatementInbox\n function getGuardReport(uint256 index)\n external\n view\n returns (bytes memory statementPayload, bytes memory reportSignature)\n {\n if (index \u003e= _storedReports.length) revert IndexOutOfRange();\n StoredReport memory storedReport = _storedReports[index];\n statementPayload = storedReport.statementPayload;\n reportSignature = _storedSignatures[storedReport.sigIndex];\n }\n\n /// @inheritdoc IStatementInbox\n function getStoredSignature(uint256 index) external view returns (bytes memory) {\n return _storedSignatures[index];\n }\n\n // ══════════════════════════════════════════════ INTERNAL LOGIC ═══════════════════════════════════════════════════\n\n /// @dev Saves the statement reported by Guard as invalid and the Guard Report signature.\n function _saveReport(bytes memory statementPayload, bytes memory reportSignature) internal {\n uint256 sigIndex = _saveSignature(reportSignature);\n _storedReports.push(StoredReport(sigIndex, statementPayload));\n }\n\n /// @dev Saves the signature and returns its index.\n function _saveSignature(bytes memory signature) internal returns (uint256 sigIndex) {\n sigIndex = _storedSignatures.length;\n _storedSignatures.push(signature);\n }\n\n // ═══════════════════════════════════════════════ AGENT CHECKS ════════════════════════════════════════════════════\n\n /**\n * @dev Recovers a signer from a hashed message, and a EIP-191 signature for it.\n * Will revert, if the signer is not a known agent.\n * @dev Agent flag could be any of these: Active/Unstaking/Resting/Fraudulent/Slashed\n * Further checks need to be performed in a caller function.\n * @param hashedStatement Hash of the statement that was signed by an Agent\n * @param signature Agent signature for the hashed statement\n * @return status Struct representing agent status:\n * - flag Unknown/Active/Unstaking/Resting/Fraudulent/Slashed\n * - domain Domain where agent is/was active\n * - index Index of agent in the Agent Merkle Tree\n * @return agent Agent that signed the statement\n */\n function _recoverAgent(bytes32 hashedStatement, bytes memory signature)\n internal\n view\n returns (AgentStatus memory status, address agent)\n {\n bytes32 ethSignedMsg = ECDSA.toEthSignedMessageHash(hashedStatement);\n agent = ECDSA.recover(ethSignedMsg, signature);\n status = IAgentManager(agentManager).agentStatus(agent);\n // Discard signature of unknown agents.\n // Further flag checks are supposed to be performed in a caller function.\n status.verifyKnown();\n }\n\n /// @dev Verifies that Notary signature is active on local domain.\n function _verifyNotaryDomain(uint32 notaryDomain) internal view {\n // Notary needs to be from the local domain (if contract is not deployed on Synapse Chain).\n // Or Notary could be from any domain (if contract is deployed on Synapse Chain).\n if (notaryDomain != localDomain \u0026\u0026 localDomain != synapseDomain) revert IncorrectAgentDomain();\n }\n\n // ════════════════════════════════════════ ATTESTATION RELATED CHECKS ═════════════════════════════════════════════\n\n /**\n * @dev Internal function to verify the signed attestation payload.\n * Reverts if any of these is true:\n * - Attestation signer is not a known Notary.\n * @param att Typed memory view over attestation payload\n * @param attSignature Notary signature for the attestation\n * @return status Struct representing agent status, see {_recoverAgent}\n * @return notary Notary that signed the snapshot\n */\n function _verifyAttestation(Attestation att, bytes memory attSignature)\n internal\n view\n returns (AgentStatus memory status, address notary)\n {\n // This will revert if signer is not a known agent\n (status, notary) = _recoverAgent(att.hashValid(), attSignature);\n // Attestation signer needs to be a Notary, not a Guard\n if (status.domain == 0) revert AgentNotNotary();\n }\n\n /**\n * @dev Internal function to verify the signed attestation report payload.\n * Reverts if any of these is true:\n * - Report signer is not a known Guard.\n * @param att Typed memory view over attestation payload that Guard reports as invalid\n * @param arSignature Guard signature for the \"invalid attestation\" report\n * @return status Struct representing guard status, see {_recoverAgent}\n * @return guard Guard that signed the report\n */\n function _verifyAttestationReport(Attestation att, bytes memory arSignature)\n internal\n view\n returns (AgentStatus memory status, address guard)\n {\n // This will revert if signer is not a known agent\n (status, guard) = _recoverAgent(att.hashInvalid(), arSignature);\n // Report signer needs to be a Guard, not a Notary\n if (status.domain != 0) revert AgentNotGuard();\n }\n\n // ══════════════════════════════════════════ RECEIPT RELATED CHECKS ═══════════════════════════════════════════════\n\n /**\n * @dev Internal function to verify the signed receipt payload.\n * Reverts if any of these is true:\n * - Receipt signer is not a known Notary.\n * @param rcpt Typed memory view over receipt payload\n * @param rcptSignature Notary signature for the receipt\n * @return status Struct representing agent status, see {_recoverAgent}\n * @return notary Notary that signed the snapshot\n */\n function _verifyReceipt(Receipt rcpt, bytes memory rcptSignature)\n internal\n view\n returns (AgentStatus memory status, address notary)\n {\n // This will revert if signer is not a known agent\n (status, notary) = _recoverAgent(rcpt.hashValid(), rcptSignature);\n // Receipt signer needs to be a Notary, not a Guard\n if (status.domain == 0) revert AgentNotNotary();\n }\n\n /**\n * @dev Internal function to verify the signed receipt report payload.\n * Reverts if any of these is true:\n * - Report signer is not a known Guard.\n * @param rcpt Typed memory view over receipt payload that Guard reports as invalid\n * @param rrSignature Guard signature for the \"invalid receipt\" report\n * @return status Struct representing guard status, see {_recoverAgent}\n * @return guard Guard that signed the report\n */\n function _verifyReceiptReport(Receipt rcpt, bytes memory rrSignature)\n internal\n view\n returns (AgentStatus memory status, address guard)\n {\n // This will revert if signer is not a known agent\n (status, guard) = _recoverAgent(rcpt.hashInvalid(), rrSignature);\n // Report signer needs to be a Guard, not a Notary\n if (status.domain != 0) revert AgentNotGuard();\n }\n\n // ═══════════════════════════════════════ STATE/SNAPSHOT RELATED CHECKS ═══════════════════════════════════════════\n\n /**\n * @dev Internal function to verify the signed snapshot report payload.\n * Reverts if any of these is true:\n * - Report signer is not a known Guard.\n * @param state Typed memory view over state payload that Guard reports as invalid\n * @param srSignature Guard signature for the report\n * @return status Struct representing guard status, see {_recoverAgent}\n * @return guard Guard that signed the report\n */\n function _verifyStateReport(State state, bytes memory srSignature)\n internal\n view\n returns (AgentStatus memory status, address guard)\n {\n // This will revert if signer is not a known agent\n (status, guard) = _recoverAgent(state.hashInvalid(), srSignature);\n // Report signer needs to be a Guard, not a Notary\n if (status.domain != 0) revert AgentNotGuard();\n }\n\n /**\n * @dev Internal function to verify the signed snapshot payload.\n * Reverts if any of these is true:\n * - Snapshot signer is not a known Agent.\n * - Snapshot signer is not a Notary (if verifyNotary is true).\n * @param snapshot Typed memory view over snapshot payload\n * @param snapSignature Agent signature for the snapshot\n * @param verifyNotary If true, snapshot signer needs to be a Notary, not a Guard\n * @return status Struct representing agent status, see {_recoverAgent}\n * @return agent Agent that signed the snapshot\n */\n function _verifySnapshot(Snapshot snapshot, bytes memory snapSignature, bool verifyNotary)\n internal\n view\n returns (AgentStatus memory status, address agent)\n {\n // This will revert if signer is not a known agent\n (status, agent) = _recoverAgent(snapshot.hashValid(), snapSignature);\n // If requested, snapshot signer needs to be a Notary, not a Guard\n if (verifyNotary \u0026\u0026 status.domain == 0) revert AgentNotNotary();\n }\n\n // ═══════════════════════════════════════════ MERKLE RELATED CHECKS ═══════════════════════════════════════════════\n\n /**\n * @dev Internal function to verify that snapshot roots match.\n * Reverts if any of these is true:\n * - Attestation root is not equal to Merkle Root derived from State and Snapshot Proof.\n * - Snapshot Proof's first element does not match the State metadata.\n * - Snapshot Proof length exceeds Snapshot tree Height.\n * - State index is out of range.\n * @param att Typed memory view over Attestation\n * @param stateIndex Index of state in the snapshot\n * @param state Typed memory view over the provided state payload\n * @param snapProof Raw payload with snapshot data\n */\n function _verifySnapshotMerkle(Attestation att, uint8 stateIndex, State state, bytes32[] memory snapProof)\n internal\n pure\n {\n // Snapshot proof first element should match State metadata (aka \"right sub-leaf\")\n (, bytes32 rightSubLeaf) = state.subLeafs();\n if (snapProof[0] != rightSubLeaf) revert IncorrectSnapshotProof();\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(state.root(), state.origin(), snapProof, stateIndex);\n // Snapshot root should match the attestation root\n if (att.snapRoot() != snapshotRoot) revert IncorrectSnapshotRoot();\n }\n}\n\n// contracts/inbox/Inbox.sol\n\n// ══════════════════════════════ LIBRARY IMPORTS ══════════════════════════════\n\n// ═════════════════════════════ INTERNAL IMPORTS ══════════════════════════════\n\n/// @notice `Inbox` is the child of `StatementInbox` contract, that is used on Synapse Chain.\n/// In addition to the functionality of `StatementInbox`, it also:\n/// - Accepts Guard and Notary Snapshots and passes them to `Summit` contract.\n/// - Accepts Notary-signed Receipts and passes them to `Summit` contract.\n/// - Accepts Receipt Reports to initiate a dispute between Guard and Notary.\n/// - Verifies Attestations and Attestation Reports, and slashes the signer if they are invalid.\ncontract Inbox is StatementInbox, InboxEvents, InterfaceInbox {\n using AttestationLib for bytes;\n using ReceiptLib for bytes;\n using SnapshotLib for bytes;\n\n // Struct to get around stack too deep error. TODO: revisit this\n struct ReceiptInfo {\n AgentStatus rcptNotaryStatus;\n address notary;\n uint32 attNonce;\n AgentStatus attNotaryStatus;\n }\n\n // ══════════════════════════════════════════════════ STORAGE ══════════════════════════════════════════════════════\n\n // The address of the Summit contract.\n address public summit;\n\n // ═════════════════════════════════════════ CONSTRUCTOR \u0026 INITIALIZER ═════════════════════════════════════════════\n\n constructor(uint32 synapseDomain_) MessagingBase(\"0.0.3\", synapseDomain_) {\n if (localDomain != synapseDomain) revert MustBeSynapseDomain();\n }\n\n /// @notice Initializes `Inbox` contract:\n /// - Sets `msg.sender` as the owner of the contract\n /// - Sets `agentManager`, `origin`, `destination` and `summit` addresses\n function initialize(address agentManager_, address origin_, address destination_, address summit_)\n external\n initializer\n {\n __StatementInbox_init(agentManager_, origin_, destination_);\n summit = summit_;\n }\n\n // ══════════════════════════════════════════ SUBMIT AGENT STATEMENTS ══════════════════════════════════════════════\n\n /// @inheritdoc InterfaceInbox\n function submitSnapshot(bytes memory snapPayload, bytes memory snapSignature)\n external\n returns (bytes memory attPayload, bytes32 agentRoot_, uint256[] memory snapGas)\n {\n // This will revert if payload is not a snapshot\n Snapshot snapshot = snapPayload.castToSnapshot();\n // This will revert if the signer is not a known Guard/Notary\n (AgentStatus memory status, address agent) =\n _verifySnapshot({snapshot: snapshot, snapSignature: snapSignature, verifyNotary: false});\n // Check that Agent is active\n status.verifyActive();\n // Store Agent signature for the Snapshot\n uint256 sigIndex = _saveSignature(snapSignature);\n if (status.domain == 0) {\n // Guard that is in Dispute could still submit new snapshots, so we don't check that\n InterfaceSummit(summit).acceptGuardSnapshot({\n guardIndex: status.index,\n sigIndex: sigIndex,\n snapPayload: snapPayload\n });\n } else {\n // Get current agentRoot from AgentManager\n agentRoot_ = IAgentManager(agentManager).agentRoot();\n // This will revert if Notary is in Dispute\n attPayload = InterfaceSummit(summit).acceptNotarySnapshot({\n notaryIndex: status.index,\n sigIndex: sigIndex,\n agentRoot: agentRoot_,\n snapPayload: snapPayload\n });\n ChainGas[] memory snapGas_ = snapshot.snapGas();\n // Pass created attestation to Destination to enable executing messages coming to Synapse Chain\n InterfaceDestination(destination).acceptAttestation(\n status.index, type(uint256).max, attPayload, agentRoot_, snapGas_\n );\n // Use assembly to cast ChainGas[] to uint256[] without copying. Highest bits are left zeroed.\n // solhint-disable-next-line no-inline-assembly\n assembly {\n snapGas := snapGas_\n }\n }\n emit SnapshotAccepted(status.domain, agent, snapPayload, snapSignature);\n }\n\n /// @inheritdoc InterfaceInbox\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 // Struct to get around stack too deep error.\n ReceiptInfo memory info;\n // This will revert if payload is not a receipt\n Receipt rcpt = rcptPayload.castToReceipt();\n // This will revert if the receipt signer is not a known Notary\n (info.rcptNotaryStatus, info.notary) = _verifyReceipt(rcpt, rcptSignature);\n // Receipt Notary needs to be Active\n info.rcptNotaryStatus.verifyActive();\n info.attNonce = IExecutionHub(destination).getAttestationNonce(rcpt.snapshotRoot());\n if (info.attNonce == 0) revert IncorrectSnapshotRoot();\n // Attestation Notary domain needs to match the destination domain\n info.attNotaryStatus = IAgentManager(agentManager).agentStatus(rcpt.attNotary());\n if (info.attNotaryStatus.domain != rcpt.destination()) revert IncorrectAgentDomain();\n // Check that the correct tip values for the message were provided\n _verifyReceiptTips(rcpt.messageHash(), paddedTips, headerHash, bodyHash);\n // Store Notary signature for the Receipt\n uint256 sigIndex = _saveSignature(rcptSignature);\n // This will revert if Receipt Notary is in Dispute\n wasAccepted = InterfaceSummit(summit).acceptReceipt({\n rcptNotaryIndex: info.rcptNotaryStatus.index,\n attNotaryIndex: info.attNotaryStatus.index,\n sigIndex: sigIndex,\n attNonce: info.attNonce,\n paddedTips: paddedTips,\n rcptPayload: rcptPayload\n });\n if (wasAccepted) {\n emit ReceiptAccepted(info.rcptNotaryStatus.domain, info.notary, rcptPayload, rcptSignature);\n }\n }\n\n /// @inheritdoc InterfaceInbox\n function submitReceiptReport(bytes memory rcptPayload, bytes memory rcptSignature, bytes memory rrSignature)\n external\n returns (bool wasAccepted)\n {\n // This will revert if payload is not a receipt\n Receipt rcpt = rcptPayload.castToReceipt();\n // This will revert if the receipt signer is not a known Guard\n (AgentStatus memory guardStatus,) = _verifyReceiptReport(rcpt, rrSignature);\n // Guard needs to be Active\n guardStatus.verifyActive();\n // This will revert if report signer is not a known Notary\n (AgentStatus memory notaryStatus,) = _verifyReceipt(rcpt, rcptSignature);\n // Notary needs to be Active/Unstaking\n notaryStatus.verifyActiveUnstaking();\n _saveReport(rcptPayload, rrSignature);\n // This will revert if either actor is already in dispute\n IAgentManager(agentManager).openDispute(guardStatus.index, notaryStatus.index);\n return true;\n }\n\n /// @inheritdoc InterfaceInbox\n function passReceipt(uint32 attNotaryIndex, uint32 attNonce, uint256 paddedTips, bytes memory rcptPayload)\n external\n returns (bool wasAccepted)\n {\n // Only Destination can pass receipts\n if (msg.sender != destination) revert CallerNotDestination();\n return InterfaceSummit(summit).acceptReceipt({\n rcptNotaryIndex: attNotaryIndex,\n attNotaryIndex: attNotaryIndex,\n sigIndex: type(uint256).max,\n attNonce: attNonce,\n paddedTips: paddedTips,\n rcptPayload: rcptPayload\n });\n }\n\n // ══════════════════════════════════════════ VERIFY AGENT STATEMENTS ══════════════════════════════════════════════\n\n /// @inheritdoc InterfaceInbox\n function verifyAttestation(bytes memory attPayload, bytes memory attSignature)\n external\n returns (bool isValidAttestation)\n {\n // This will revert if payload is not an attestation\n Attestation att = attPayload.castToAttestation();\n // This will revert if the attestation signer is not a known Notary\n (AgentStatus memory status, address notary) = _verifyAttestation(att, attSignature);\n // Notary needs to be Active/Unstaking\n status.verifyActiveUnstaking();\n isValidAttestation = ISnapshotHub(summit).isValidAttestation(attPayload);\n if (!isValidAttestation) {\n emit InvalidAttestation(attPayload, attSignature);\n IAgentManager(agentManager).slashAgent(status.domain, notary, msg.sender);\n }\n }\n\n /// @inheritdoc InterfaceInbox\n function verifyAttestationReport(bytes memory attPayload, bytes memory arSignature)\n external\n returns (bool isValidReport)\n {\n // This will revert if payload is not an attestation\n Attestation att = attPayload.castToAttestation();\n // This will revert if the report signer is not a known Guard\n (AgentStatus memory status, address guard) = _verifyAttestationReport(att, arSignature);\n // Guard needs to be Active/Unstaking\n status.verifyActiveUnstaking();\n // Report is valid IF AND ONLY IF the reported attestation in invalid\n isValidReport = !ISnapshotHub(summit).isValidAttestation(attPayload);\n if (!isValidReport) {\n emit InvalidAttestationReport(attPayload, arSignature);\n IAgentManager(agentManager).slashAgent(status.domain, guard, msg.sender);\n }\n }\n\n // ══════════════════════════════════════════════ INTERNAL VIEWS ═══════════════════════════════════════════════════\n\n /// @dev Verifies that tips proof matches the message hash.\n function _verifyReceiptTips(bytes32 msgHash, uint256 paddedTips, bytes32 headerHash, bytes32 bodyHash)\n internal\n pure\n {\n Tips tips = TipsLib.wrapPadded(paddedTips);\n // full message leaf is (header, baseMessage), while base message leaf is (tips, remainingBody).\n if (MerkleMath.getParent(headerHash, MerkleMath.getParent(tips.leaf(), bodyHash)) != msgHash) {\n revert IncorrectTipsProof();\n }\n }\n}\n","language":"Solidity","languageVersion":"0.8.17","compilerVersion":"0.8.17","compilerOptions":"--combined-json bin,bin-runtime,srcmap,srcmap-runtime,abi,userdoc,devdoc,metadata,hashes --optimize --optimize-runs 10000 --allow-paths ., ./, ../","srcMap":"","srcMapRuntime":"","abiDefinition":[{"inputs":[{"internalType":"bytes","name":"statePayload","type":"bytes"}],"name":"isValidState","outputs":[{"internalType":"bool","name":"isValid","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"statesAmount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"suggestLatestState","outputs":[{"internalType":"bytes","name":"statePayload","type":"bytes"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint32","name":"nonce","type":"uint32"}],"name":"suggestState","outputs":[{"internalType":"bytes","name":"statePayload","type":"bytes"}],"stateMutability":"view","type":"function"}],"userDoc":{"kind":"user","methods":{"isValidState(bytes)":{"notice":"Check that a given state is valid: matches the historical state of Origin contract. Note: any Agent including an invalid state in their snapshot will be slashed upon providing the snapshot and agent signature for it to Origin contract."},"statesAmount()":{"notice":"Returns the amount of saved states so far."},"suggestLatestState()":{"notice":"Suggest the data (state after latest sent message) to sign for an Agent. Note: signing the suggested state data will will never lead to slashing of the actor, assuming they have confirmed that the block, which number is included in the data, is not subject to reorganization (which is different for every observed chain)."},"suggestState(uint32)":{"notice":"Given the historical nonce, suggest the state data to sign for an Agent. Note: signing the suggested state data will will never lead to slashing of the actor, assuming they have confirmed that the block, which number is included in the data, is not subject to reorganization (which is different for every observed chain)."}},"version":1},"developerDoc":{"kind":"dev","methods":{"isValidState(bytes)":{"details":"Will revert if any of these is true: - State payload is not properly formatted.","params":{"statePayload":"Raw payload with state data"},"returns":{"isValid":" Whether the provided state is valid"}},"statesAmount()":{"details":"This includes the initial state of \"empty Origin Merkle Tree\"."},"suggestLatestState()":{"returns":{"statePayload":" Raw payload with the latest state data"}},"suggestState(uint32)":{"params":{"nonce":"Historical nonce to form a state"},"returns":{"statePayload":" Raw payload with historical state data"}}},"version":1},"metadata":"{\"compiler\":{\"version\":\"0.8.17+commit.8df45f5f\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"statePayload\",\"type\":\"bytes\"}],\"name\":\"isValidState\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"isValid\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"statesAmount\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"suggestLatestState\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"statePayload\",\"type\":\"bytes\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint32\",\"name\":\"nonce\",\"type\":\"uint32\"}],\"name\":\"suggestState\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"statePayload\",\"type\":\"bytes\"}],\"stateMutability\":\"view\",\"type\":\"function\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{\"isValidState(bytes)\":{\"details\":\"Will revert if any of these is true: - State payload is not properly formatted.\",\"params\":{\"statePayload\":\"Raw payload with state data\"},\"returns\":{\"isValid\":\" Whether the provided state is valid\"}},\"statesAmount()\":{\"details\":\"This includes the initial state of \\\"empty Origin Merkle Tree\\\".\"},\"suggestLatestState()\":{\"returns\":{\"statePayload\":\" Raw payload with the latest state data\"}},\"suggestState(uint32)\":{\"params\":{\"nonce\":\"Historical nonce to form a state\"},\"returns\":{\"statePayload\":\" Raw payload with historical state data\"}}},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{\"isValidState(bytes)\":{\"notice\":\"Check that a given state is valid: matches the historical state of Origin contract. Note: any Agent including an invalid state in their snapshot will be slashed upon providing the snapshot and agent signature for it to Origin contract.\"},\"statesAmount()\":{\"notice\":\"Returns the amount of saved states so far.\"},\"suggestLatestState()\":{\"notice\":\"Suggest the data (state after latest sent message) to sign for an Agent. Note: signing the suggested state data will will never lead to slashing of the actor, assuming they have confirmed that the block, which number is included in the data, is not subject to reorganization (which is different for every observed chain).\"},\"suggestState(uint32)\":{\"notice\":\"Given the historical nonce, suggest the state data to sign for an Agent. Note: signing the suggested state data will will never lead to slashing of the actor, assuming they have confirmed that the block, which number is included in the data, is not subject to reorganization (which is different for every observed chain).\"}},\"version\":1}},\"settings\":{\"compilationTarget\":{\"solidity/Inbox.sol\":\"IStateHub\"},\"evmVersion\":\"london\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\"},\"optimizer\":{\"enabled\":true,\"runs\":10000},\"remappings\":[]},\"sources\":{\"solidity/Inbox.sol\":{\"keccak256\":\"0x9b516081a036814c0169e20e484d4a5499066b7a6f48fada952b5e844a1ca3e5\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://32bde393b3f24ef4307d9626d4143f337b3c0bd34e17bb969fd5a15221d96987\",\"dweb:/ipfs/QmTkt2XZRtgsbSpmsVQUM3c4ebETQoDVYbmEV9yheBghnr\"]}},\"version\":1}"},"hashes":{"isValidState(bytes)":"a9dcf22d","statesAmount()":"f2437942","suggestLatestState()":"c0b56f7c","suggestState(uint32)":"b4596b4b"}},"solidity/Inbox.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/InboxEvents.sol\n\nabstract contract InboxEvents {\n /**\n * @notice Emitted when a snapshot is accepted by the Summit contract.\n * @param domain Domain where the signed Agent is active (ZERO for Guards)\n * @param agent Agent who signed the snapshot\n * @param snapPayload Raw payload with snapshot data\n * @param snapSignature Agent signature for the snapshot\n */\n event SnapshotAccepted(uint32 indexed domain, address indexed agent, bytes snapPayload, bytes snapSignature);\n\n /**\n * @notice Emitted when a snapshot is accepted by the Summit contract.\n * @param domain Domain where the signed Notary is active\n * @param notary Notary who signed the attestation\n * @param rcptPayload Raw payload with receipt data\n * @param rcptSignature Notary signature for the receipt\n */\n event ReceiptAccepted(uint32 domain, address notary, bytes rcptPayload, bytes rcptSignature);\n\n /**\n * @notice Emitted when a proof of invalid attestation is submitted.\n * @param attPayload Raw payload with Attestation data\n * @param attSignature Notary signature for the attestation\n */\n event InvalidAttestation(bytes attPayload, bytes attSignature);\n\n /**\n * @notice Emitted when a proof of invalid attestation report is submitted.\n * @param arPayload Raw payload with report data\n * @param arSignature Guard signature for the report\n */\n event InvalidAttestationReport(bytes arPayload, bytes arSignature);\n}\n\n// contracts/events/StatementInboxEvents.sol\n\nabstract contract StatementInboxEvents {\n // ════════════════════════════════════════════ STATEMENT ACCEPTED ═════════════════════════════════════════════════\n\n /**\n * @notice Emitted when a snapshot is accepted by the Destination contract.\n * @param domain Domain where the signed Notary is active\n * @param notary Notary who signed the attestation\n * @param attPayload Raw payload with attestation data\n * @param attSignature Notary signature for the attestation\n */\n event AttestationAccepted(uint32 domain, address notary, bytes attPayload, bytes attSignature);\n\n // ═════════════════════════════════════════ INVALID STATEMENT PROVED ══════════════════════════════════════════════\n\n /**\n * @notice Emitted when a proof of invalid receipt statement is submitted.\n * @param rcptPayload Raw payload with the receipt statement\n * @param rcptSignature Notary signature for the receipt statement\n */\n event InvalidReceipt(bytes rcptPayload, bytes rcptSignature);\n\n /**\n * @notice Emitted when a proof of invalid receipt report is submitted.\n * @param rrPayload Raw payload with report data\n * @param rrSignature Guard signature for the report\n */\n event InvalidReceiptReport(bytes rrPayload, bytes rrSignature);\n\n /**\n * @notice Emitted when a proof of invalid state in the signed attestation is submitted.\n * @param stateIndex Index of invalid state in the snapshot\n * @param statePayload Raw payload with state data\n * @param attPayload Raw payload with Attestation data for snapshot\n * @param attSignature Notary signature for the attestation\n */\n event InvalidStateWithAttestation(uint8 stateIndex, bytes statePayload, bytes attPayload, bytes attSignature);\n\n /**\n * @notice Emitted when a proof of invalid state in the signed snapshot is submitted.\n * @param stateIndex Index of invalid state in the snapshot\n * @param snapPayload Raw payload with snapshot data\n * @param snapSignature Agent signature for the snapshot\n */\n event InvalidStateWithSnapshot(uint8 stateIndex, bytes snapPayload, bytes snapSignature);\n\n /**\n * @notice Emitted when a proof of invalid state report is submitted.\n * @param srPayload Raw payload with report data\n * @param srSignature Guard signature for the report\n */\n event InvalidStateReport(bytes srPayload, bytes srSignature);\n}\n\n// contracts/interfaces/ISnapshotHub.sol\n\ninterface ISnapshotHub {\n /**\n * @notice Check that a given attestation is valid: matches the historical attestation\n * derived from an accepted Notary snapshot.\n * @dev Will revert if any of these is true:\n * - Attestation payload is not properly formatted.\n * @param attPayload Raw payload with attestation data\n * @return isValid Whether the provided attestation is valid\n */\n function isValidAttestation(bytes memory attPayload) external view returns (bool isValid);\n\n /**\n * @notice Returns saved attestation with the given nonce.\n * @dev Reverts if attestation with given nonce hasn't been created yet.\n * @param attNonce Nonce for the attestation\n * @return attPayload Raw payload with formatted Attestation data\n * @return agentRoot Agent root hash used for the attestation\n * @return snapGas Snapshot gas data used for the attestation\n */\n function getAttestation(uint32 attNonce)\n external\n view\n returns (bytes memory attPayload, bytes32 agentRoot, uint256[] memory snapGas);\n\n /**\n * @notice Returns the state with the highest known nonce submitted by a given Agent.\n * @param origin Domain of origin chain\n * @param agent Agent address\n * @return statePayload Raw payload with agent's latest state for origin\n */\n function getLatestAgentState(uint32 origin, address agent) external view returns (bytes memory statePayload);\n\n /**\n * @notice Returns latest saved attestation for a Notary.\n * @param notary Notary address\n * @return attPayload Raw payload with formatted Attestation data\n * @return agentRoot Agent root hash used for the attestation\n * @return snapGas Snapshot gas data used for the attestation\n */\n function getLatestNotaryAttestation(address notary)\n external\n view\n returns (bytes memory attPayload, bytes32 agentRoot, uint256[] memory snapGas);\n\n /**\n * @notice Returns Guard snapshot from the list of all accepted Guard snapshots.\n * @dev Reverts if snapshot with given index hasn't been accepted yet.\n * @param index Snapshot index in the list of all Guard snapshots\n * @return snapPayload Raw payload with Guard snapshot\n * @return snapSignature Raw payload with Guard signature for snapshot\n */\n function getGuardSnapshot(uint256 index)\n external\n view\n returns (bytes memory snapPayload, bytes memory snapSignature);\n\n /**\n * @notice Returns Notary snapshot from the list of all accepted Guard snapshots.\n * @dev Reverts if snapshot with given index hasn't been accepted yet.\n * @param index Snapshot index in the list of all Notary snapshots\n * @return snapPayload Raw payload with Notary snapshot\n * @return snapSignature Raw payload with Notary signature for snapshot\n */\n function getNotarySnapshot(uint256 index)\n external\n view\n returns (bytes memory snapPayload, bytes memory snapSignature);\n\n /**\n * @notice Returns Notary snapshot that was used for creating a given attestation.\n * @dev Reverts if any of these is true:\n * - Attestation payload is not properly formatted.\n * - Attestation is invalid (doesn't have a matching Notary snapshot).\n * @param attPayload Raw payload with attestation data\n * @return snapPayload Raw payload with Notary snapshot\n * @return snapSignature Raw payload with Notary signature for snapshot\n */\n function getNotarySnapshot(bytes memory attPayload)\n external\n view\n returns (bytes memory snapPayload, bytes memory snapSignature);\n\n /**\n * @notice Returns proof of inclusion of (root, origin) fields of a given snapshot's state\n * into the Snapshot Merkle Tree for a given attestation.\n * @dev Reverts if any of these is true:\n * - Attestation with given nonce hasn't been created yet.\n * - State index is out of range of snapshot list.\n * @param attNonce Nonce for the attestation\n * @param stateIndex Index of state in the attestation's snapshot\n * @return snapProof The snapshot proof\n */\n function getSnapshotProof(uint32 attNonce, uint8 stateIndex) external view returns (bytes32[] memory snapProof);\n}\n\n// contracts/interfaces/IStateHub.sol\n\ninterface IStateHub {\n /**\n * @notice Check that a given state is valid: matches the historical state of Origin contract.\n * Note: any Agent including an invalid state in their snapshot will be slashed\n * upon providing the snapshot and agent signature for it to Origin contract.\n * @dev Will revert if any of these is true:\n * - State payload is not properly formatted.\n * @param statePayload Raw payload with state data\n * @return isValid Whether the provided state is valid\n */\n function isValidState(bytes memory statePayload) external view returns (bool isValid);\n\n /**\n * @notice Returns the amount of saved states so far.\n * @dev This includes the initial state of \"empty Origin Merkle Tree\".\n */\n function statesAmount() external view returns (uint256);\n\n /**\n * @notice Suggest the data (state after latest sent message) to sign for an Agent.\n * Note: signing the suggested state data will will never lead to slashing of the actor,\n * assuming they have confirmed that the block, which number is included in the data,\n * is not subject to reorganization (which is different for every observed chain).\n * @return statePayload Raw payload with the latest state data\n */\n function suggestLatestState() external view returns (bytes memory statePayload);\n\n /**\n * @notice Given the historical nonce, suggest the state data to sign for an Agent.\n * Note: signing the suggested state data will will never lead to slashing of the actor,\n * assuming they have confirmed that the block, which number is included in the data,\n * is not subject to reorganization (which is different for every observed chain).\n * @param nonce Historical nonce to form a state\n * @return statePayload Raw payload with historical state data\n */\n function suggestState(uint32 nonce) external view returns (bytes memory statePayload);\n}\n\n// contracts/interfaces/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/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// node_modules/@openzeppelin/contracts/utils/math/Math.sol\n\n// OpenZeppelin Contracts (last updated v4.9.0) (utils/math/Math.sol)\n\n/**\n * @dev Standard math utilities missing in the Solidity language.\n */\nlibrary Math {\n enum Rounding {\n Down, // Toward negative infinity\n Up, // Toward infinity\n Zero // Toward zero\n }\n\n /**\n * @dev Returns the largest of two numbers.\n */\n function max(uint256 a, uint256 b) internal pure returns (uint256) {\n return a \u003e b ? a : b;\n }\n\n /**\n * @dev Returns the smallest of two numbers.\n */\n function min(uint256 a, uint256 b) internal pure returns (uint256) {\n return a \u003c b ? a : b;\n }\n\n /**\n * @dev Returns the average of two numbers. The result is rounded towards\n * zero.\n */\n function average(uint256 a, uint256 b) internal pure returns (uint256) {\n // (a + b) / 2 can overflow.\n return (a \u0026 b) + (a ^ b) / 2;\n }\n\n /**\n * @dev Returns the ceiling of the division of two numbers.\n *\n * This differs from standard division with `/` in that it rounds up instead\n * of rounding down.\n */\n function ceilDiv(uint256 a, uint256 b) internal pure returns (uint256) {\n // (a + b - 1) / b can overflow on addition, so we distribute.\n return a == 0 ? 0 : (a - 1) / b + 1;\n }\n\n /**\n * @notice Calculates floor(x * y / denominator) with full precision. Throws if result overflows a uint256 or denominator == 0\n * @dev Original credit to Remco Bloemen under MIT license (https://xn--2-umb.com/21/muldiv)\n * with further edits by Uniswap Labs also under MIT license.\n */\n function mulDiv(uint256 x, uint256 y, uint256 denominator) internal pure returns (uint256 result) {\n unchecked {\n // 512-bit multiply [prod1 prod0] = x * y. Compute the product mod 2^256 and mod 2^256 - 1, then use\n // use the Chinese Remainder Theorem to reconstruct the 512 bit result. The result is stored in two 256\n // variables such that product = prod1 * 2^256 + prod0.\n uint256 prod0; // Least significant 256 bits of the product\n uint256 prod1; // Most significant 256 bits of the product\n assembly {\n let mm := mulmod(x, y, not(0))\n prod0 := mul(x, y)\n prod1 := sub(sub(mm, prod0), lt(mm, prod0))\n }\n\n // Handle non-overflow cases, 256 by 256 division.\n if (prod1 == 0) {\n // Solidity will revert if denominator == 0, unlike the div opcode on its own.\n // The surrounding unchecked block does not change this fact.\n // See https://docs.soliditylang.org/en/latest/control-structures.html#checked-or-unchecked-arithmetic.\n return prod0 / denominator;\n }\n\n // Make sure the result is less than 2^256. Also prevents denominator == 0.\n require(denominator \u003e prod1, \"Math: mulDiv overflow\");\n\n ///////////////////////////////////////////////\n // 512 by 256 division.\n ///////////////////////////////////////////////\n\n // Make division exact by subtracting the remainder from [prod1 prod0].\n uint256 remainder;\n assembly {\n // Compute remainder using mulmod.\n remainder := mulmod(x, y, denominator)\n\n // Subtract 256 bit number from 512 bit number.\n prod1 := sub(prod1, gt(remainder, prod0))\n prod0 := sub(prod0, remainder)\n }\n\n // Factor powers of two out of denominator and compute largest power of two divisor of denominator. Always \u003e= 1.\n // See https://cs.stackexchange.com/q/138556/92363.\n\n // Does not overflow because the denominator cannot be zero at this stage in the function.\n uint256 twos = denominator \u0026 (~denominator + 1);\n assembly {\n // Divide denominator by twos.\n denominator := div(denominator, twos)\n\n // Divide [prod1 prod0] by twos.\n prod0 := div(prod0, twos)\n\n // Flip twos such that it is 2^256 / twos. If twos is zero, then it becomes one.\n twos := add(div(sub(0, twos), twos), 1)\n }\n\n // Shift in bits from prod1 into prod0.\n prod0 |= prod1 * twos;\n\n // Invert denominator mod 2^256. Now that denominator is an odd number, it has an inverse modulo 2^256 such\n // that denominator * inv = 1 mod 2^256. Compute the inverse by starting with a seed that is correct for\n // four bits. That is, denominator * inv = 1 mod 2^4.\n uint256 inverse = (3 * denominator) ^ 2;\n\n // Use the Newton-Raphson iteration to improve the precision. Thanks to Hensel's lifting lemma, this also works\n // in modular arithmetic, doubling the correct bits in each step.\n inverse *= 2 - denominator * inverse; // inverse mod 2^8\n inverse *= 2 - denominator * inverse; // inverse mod 2^16\n inverse *= 2 - denominator * inverse; // inverse mod 2^32\n inverse *= 2 - denominator * inverse; // inverse mod 2^64\n inverse *= 2 - denominator * inverse; // inverse mod 2^128\n inverse *= 2 - denominator * inverse; // inverse mod 2^256\n\n // Because the division is now exact we can divide by multiplying with the modular inverse of denominator.\n // This will give us the correct result modulo 2^256. Since the preconditions guarantee that the outcome is\n // less than 2^256, this is the final result. We don't need to compute the high bits of the result and prod1\n // is no longer required.\n result = prod0 * inverse;\n return result;\n }\n }\n\n /**\n * @notice Calculates x * y / denominator with full precision, following the selected rounding direction.\n */\n function mulDiv(uint256 x, uint256 y, uint256 denominator, Rounding rounding) internal pure returns (uint256) {\n uint256 result = mulDiv(x, y, denominator);\n if (rounding == Rounding.Up \u0026\u0026 mulmod(x, y, denominator) \u003e 0) {\n result += 1;\n }\n return result;\n }\n\n /**\n * @dev Returns the square root of a number. If the number is not a perfect square, the value is rounded down.\n *\n * Inspired by Henry S. Warren, Jr.'s \"Hacker's Delight\" (Chapter 11).\n */\n function sqrt(uint256 a) internal pure returns (uint256) {\n if (a == 0) {\n return 0;\n }\n\n // For our first guess, we get the biggest power of 2 which is smaller than the square root of the target.\n //\n // We know that the \"msb\" (most significant bit) of our target number `a` is a power of 2 such that we have\n // `msb(a) \u003c= a \u003c 2*msb(a)`. This value can be written `msb(a)=2**k` with `k=log2(a)`.\n //\n // This can be rewritten `2**log2(a) \u003c= a \u003c 2**(log2(a) + 1)`\n // → `sqrt(2**k) \u003c= sqrt(a) \u003c sqrt(2**(k+1))`\n // → `2**(k/2) \u003c= sqrt(a) \u003c 2**((k+1)/2) \u003c= 2**(k/2 + 1)`\n //\n // Consequently, `2**(log2(a) / 2)` is a good first approximation of `sqrt(a)` with at least 1 correct bit.\n uint256 result = 1 \u003c\u003c (log2(a) \u003e\u003e 1);\n\n // At this point `result` is an estimation with one bit of precision. We know the true value is a uint128,\n // since it is the square root of a uint256. Newton's method converges quadratically (precision doubles at\n // every iteration). We thus need at most 7 iteration to turn our partial result with one bit of precision\n // into the expected uint128 result.\n unchecked {\n result = (result + a / result) \u003e\u003e 1;\n result = (result + a / result) \u003e\u003e 1;\n result = (result + a / result) \u003e\u003e 1;\n result = (result + a / result) \u003e\u003e 1;\n result = (result + a / result) \u003e\u003e 1;\n result = (result + a / result) \u003e\u003e 1;\n result = (result + a / result) \u003e\u003e 1;\n return min(result, a / result);\n }\n }\n\n /**\n * @notice Calculates sqrt(a), following the selected rounding direction.\n */\n function sqrt(uint256 a, Rounding rounding) internal pure returns (uint256) {\n unchecked {\n uint256 result = sqrt(a);\n return result + (rounding == Rounding.Up \u0026\u0026 result * result \u003c a ? 1 : 0);\n }\n }\n\n /**\n * @dev Return the log in base 2, rounded down, of a positive value.\n * Returns 0 if given 0.\n */\n function log2(uint256 value) internal pure returns (uint256) {\n uint256 result = 0;\n unchecked {\n if (value \u003e\u003e 128 \u003e 0) {\n value \u003e\u003e= 128;\n result += 128;\n }\n if (value \u003e\u003e 64 \u003e 0) {\n value \u003e\u003e= 64;\n result += 64;\n }\n if (value \u003e\u003e 32 \u003e 0) {\n value \u003e\u003e= 32;\n result += 32;\n }\n if (value \u003e\u003e 16 \u003e 0) {\n value \u003e\u003e= 16;\n result += 16;\n }\n if (value \u003e\u003e 8 \u003e 0) {\n value \u003e\u003e= 8;\n result += 8;\n }\n if (value \u003e\u003e 4 \u003e 0) {\n value \u003e\u003e= 4;\n result += 4;\n }\n if (value \u003e\u003e 2 \u003e 0) {\n value \u003e\u003e= 2;\n result += 2;\n }\n if (value \u003e\u003e 1 \u003e 0) {\n result += 1;\n }\n }\n return result;\n }\n\n /**\n * @dev Return the log in base 2, following the selected rounding direction, of a positive value.\n * Returns 0 if given 0.\n */\n function log2(uint256 value, Rounding rounding) internal pure returns (uint256) {\n unchecked {\n uint256 result = log2(value);\n return result + (rounding == Rounding.Up \u0026\u0026 1 \u003c\u003c result \u003c value ? 1 : 0);\n }\n }\n\n /**\n * @dev Return the log in base 10, rounded down, of a positive value.\n * Returns 0 if given 0.\n */\n function log10(uint256 value) internal pure returns (uint256) {\n uint256 result = 0;\n unchecked {\n if (value \u003e= 10 ** 64) {\n value /= 10 ** 64;\n result += 64;\n }\n if (value \u003e= 10 ** 32) {\n value /= 10 ** 32;\n result += 32;\n }\n if (value \u003e= 10 ** 16) {\n value /= 10 ** 16;\n result += 16;\n }\n if (value \u003e= 10 ** 8) {\n value /= 10 ** 8;\n result += 8;\n }\n if (value \u003e= 10 ** 4) {\n value /= 10 ** 4;\n result += 4;\n }\n if (value \u003e= 10 ** 2) {\n value /= 10 ** 2;\n result += 2;\n }\n if (value \u003e= 10 ** 1) {\n result += 1;\n }\n }\n return result;\n }\n\n /**\n * @dev Return the log in base 10, following the selected rounding direction, of a positive value.\n * Returns 0 if given 0.\n */\n function log10(uint256 value, Rounding rounding) internal pure returns (uint256) {\n unchecked {\n uint256 result = log10(value);\n return result + (rounding == Rounding.Up \u0026\u0026 10 ** result \u003c value ? 1 : 0);\n }\n }\n\n /**\n * @dev Return the log in base 256, rounded down, of a positive value.\n * Returns 0 if given 0.\n *\n * Adding one to the result gives the number of pairs of hex symbols needed to represent `value` as a hex string.\n */\n function log256(uint256 value) internal pure returns (uint256) {\n uint256 result = 0;\n unchecked {\n if (value \u003e\u003e 128 \u003e 0) {\n value \u003e\u003e= 128;\n result += 16;\n }\n if (value \u003e\u003e 64 \u003e 0) {\n value \u003e\u003e= 64;\n result += 8;\n }\n if (value \u003e\u003e 32 \u003e 0) {\n value \u003e\u003e= 32;\n result += 4;\n }\n if (value \u003e\u003e 16 \u003e 0) {\n value \u003e\u003e= 16;\n result += 2;\n }\n if (value \u003e\u003e 8 \u003e 0) {\n result += 1;\n }\n }\n return result;\n }\n\n /**\n * @dev Return the log in base 256, following the selected rounding direction, of a positive value.\n * Returns 0 if given 0.\n */\n function log256(uint256 value, Rounding rounding) internal pure returns (uint256) {\n unchecked {\n uint256 result = log256(value);\n return result + (rounding == Rounding.Up \u0026\u0026 1 \u003c\u003c (result \u003c\u003c 3) \u003c value ? 1 : 0);\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/utils/math/SignedMath.sol\n\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/math/SignedMath.sol)\n\n/**\n * @dev Standard signed math utilities missing in the Solidity language.\n */\nlibrary SignedMath {\n /**\n * @dev Returns the largest of two signed numbers.\n */\n function max(int256 a, int256 b) internal pure returns (int256) {\n return a \u003e b ? a : b;\n }\n\n /**\n * @dev Returns the smallest of two signed numbers.\n */\n function min(int256 a, int256 b) internal pure returns (int256) {\n return a \u003c b ? a : b;\n }\n\n /**\n * @dev Returns the average of two signed numbers without overflow.\n * The result is rounded towards zero.\n */\n function average(int256 a, int256 b) internal pure returns (int256) {\n // Formula from the book \"Hacker's Delight\"\n int256 x = (a \u0026 b) + ((a ^ b) \u003e\u003e 1);\n return x + (int256(uint256(x) \u003e\u003e 255) \u0026 (a ^ b));\n }\n\n /**\n * @dev Returns the absolute unsigned value of a signed value.\n */\n function abs(int256 n) internal pure returns (uint256) {\n unchecked {\n // must be unchecked in order to support `n = type(int256).min`\n return uint256(n \u003e= 0 ? n : -n);\n }\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// 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/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/InterfaceSummit.sol\n\ninterface InterfaceSummit {\n // ══════════════════════════════════════════ ACCEPT AGENT STATEMENTS ══════════════════════════════════════════════\n\n /**\n * @notice Accepts a receipt, which local `AgentManager` verified to have been signed by an active Notary.\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 * - Notary who signed the receipt is referenced as the \"Receipt Notary\".\n * - Notary who signed the attestation on destination chain is referenced as the \"Attestation Notary\".\n * \u003e Will revert if any of these is true:\n * \u003e - Called by anyone other than local `AgentManager`.\n * \u003e - Receipt body payload is not properly formatted.\n * \u003e - Receipt signer is in Dispute.\n * \u003e - Receipt's snapshot root is unknown.\n * @param rcptNotaryIndex Index of Receipt Notary in Agent Merkle Tree\n * @param attNotaryIndex Index of Attestation Notary in Agent Merkle Tree\n * @param sigIndex Index of stored Notary signature\n * @param attNonce Nonce of the attestation used for proving the executed message\n * @param paddedTips Padded encoded paid tips information\n * @param rcptPayload Raw payload with message execution receipt\n * @return wasAccepted Whether the receipt was accepted\n */\n function acceptReceipt(\n uint32 rcptNotaryIndex,\n uint32 attNotaryIndex,\n uint256 sigIndex,\n uint32 attNonce,\n uint256 paddedTips,\n bytes memory rcptPayload\n ) external returns (bool wasAccepted);\n\n /**\n * @notice Accepts a snapshot, which local `AgentManager` verified to have been signed by an active Guard.\n * \u003e Snapshot is a list of states for a set of Origin contracts residing on any of the chains.\n * All the states in the Guard-signed snapshot become available for Notary signing.\n * \u003e Will revert if any of these is true:\n * \u003e - Called by anyone other than local `AgentManager`.\n * \u003e - Snapshot payload is not properly formatted.\n * \u003e - Snapshot contains a state older then the Guard has previously submitted.\n * @param guardIndex Index of Guard in Agent Merkle Tree\n * @param sigIndex Index of stored Agent signature\n * @param snapPayload Raw payload with snapshot data\n */\n function acceptGuardSnapshot(uint32 guardIndex, uint256 sigIndex, bytes memory snapPayload) external;\n\n /**\n * @notice Accepts a snapshot, which local `AgentManager` verified to have been signed by an active Notary.\n * \u003e Snapshot is a list of states for a set of Origin contracts residing on any of the chains.\n * Snapshot Merkle Root is calculated and saved for valid snapshots, i.e.\n * snapshots which are only using states previously submitted by any of the Guards.\n * - Notary could use states singed by the same of different Guards 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 - Called by anyone other than local `AgentManager`.\n * \u003e - Snapshot payload is not properly formatted.\n * \u003e - Snapshot contains a state older then the Notary has previously submitted.\n * \u003e - Snapshot contains a state that no Guard has previously submitted.\n * @param notaryIndex Index of Notary in Agent Merkle Tree\n * @param sigIndex Index of stored Agent signature\n * @param agentRoot Current root of the Agent Merkle Tree\n * @param snapPayload Raw payload with snapshot data\n * @return attPayload Raw payload with data for attestation derived from Notary snapshot.\n */\n function acceptNotarySnapshot(uint32 notaryIndex, uint256 sigIndex, bytes32 agentRoot, bytes memory snapPayload)\n external\n returns (bytes memory attPayload);\n\n // ════════════════════════════════════════════════ TIPS LOGIC ═════════════════════════════════════════════════════\n\n /**\n * @notice Distributes tips using the first Receipt from the \"receipt quarantine queue\".\n * Possible scenarios:\n * - Receipt queue is empty =\u003e does nothing\n * - Receipt optimistic period is not over =\u003e does nothing\n * - Either of Notaries present in Receipt was slashed =\u003e receipt is deleted from the queue\n * - Either of Notaries present in Receipt in Dispute =\u003e receipt is moved to the end of queue\n * - None of the above =\u003e receipt tips are distributed\n * @dev Returned value makes it possible to do the following: `while (distributeTips()) {}`\n * @return queuePopped Whether the first element was popped from the queue\n */\n function distributeTips() external returns (bool queuePopped);\n\n /**\n * @notice Withdraws locked base message tips from requested domain Origin to the recipient.\n * This is done by a call to a local Origin contract, or by a manager message to the remote chain.\n * @dev This will revert, if the pending balance of origin tips (earned-claimed) is lower than requested.\n * @param origin Domain of chain to withdraw tips on\n * @param amount Amount of tips to withdraw\n */\n function withdrawTips(uint32 origin, uint256 amount) external;\n\n // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════\n\n /**\n * @notice Returns earned and claimed tips for the actor.\n * Note: Tips for address(0) belong to the Treasury.\n * @param actor Address of the actor\n * @param origin Domain where the tips were initially paid\n * @return earned Total amount of origin tips the actor has earned so far\n * @return claimed Total amount of origin tips the actor has claimed so far\n */\n function actorTips(address actor, uint32 origin) external view returns (uint128 earned, uint128 claimed);\n\n /**\n * @notice Returns the amount of receipts in the \"Receipt Quarantine Queue\".\n */\n function receiptQueueLength() external view returns (uint256);\n\n /**\n * @notice Returns the state with the highest known nonce\n * submitted by any of the currently active Guards.\n * @param origin Domain of origin chain\n * @return statePayload Raw payload with latest active Guard state for origin\n */\n function getLatestState(uint32 origin) external view returns (bytes memory statePayload);\n}\n\n// node_modules/@openzeppelin/contracts/utils/Strings.sol\n\n// OpenZeppelin Contracts (last updated v4.9.0) (utils/Strings.sol)\n\n/**\n * @dev String operations.\n */\nlibrary Strings {\n bytes16 private constant _SYMBOLS = \"0123456789abcdef\";\n uint8 private constant _ADDRESS_LENGTH = 20;\n\n /**\n * @dev Converts a `uint256` to its ASCII `string` decimal representation.\n */\n function toString(uint256 value) internal pure returns (string memory) {\n unchecked {\n uint256 length = Math.log10(value) + 1;\n string memory buffer = new string(length);\n uint256 ptr;\n /// @solidity memory-safe-assembly\n assembly {\n ptr := add(buffer, add(32, length))\n }\n while (true) {\n ptr--;\n /// @solidity memory-safe-assembly\n assembly {\n mstore8(ptr, byte(mod(value, 10), _SYMBOLS))\n }\n value /= 10;\n if (value == 0) break;\n }\n return buffer;\n }\n }\n\n /**\n * @dev Converts a `int256` to its ASCII `string` decimal representation.\n */\n function toString(int256 value) internal pure returns (string memory) {\n return string(abi.encodePacked(value \u003c 0 ? \"-\" : \"\", toString(SignedMath.abs(value))));\n }\n\n /**\n * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation.\n */\n function toHexString(uint256 value) internal pure returns (string memory) {\n unchecked {\n return toHexString(value, Math.log256(value) + 1);\n }\n }\n\n /**\n * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length.\n */\n function toHexString(uint256 value, uint256 length) internal pure returns (string memory) {\n bytes memory buffer = new bytes(2 * length + 2);\n buffer[0] = \"0\";\n buffer[1] = \"x\";\n for (uint256 i = 2 * length + 1; i \u003e 1; --i) {\n buffer[i] = _SYMBOLS[value \u0026 0xf];\n value \u003e\u003e= 4;\n }\n require(value == 0, \"Strings: hex length insufficient\");\n return string(buffer);\n }\n\n /**\n * @dev Converts an `address` with fixed length of 20 bytes to its not checksummed ASCII `string` hexadecimal representation.\n */\n function toHexString(address addr) internal pure returns (string memory) {\n return toHexString(uint256(uint160(addr)), _ADDRESS_LENGTH);\n }\n\n /**\n * @dev Returns true if the two strings are equal.\n */\n function equal(string memory a, string memory b) internal pure returns (bool) {\n return keccak256(bytes(a)) == keccak256(bytes(b));\n }\n}\n\n// node_modules/@openzeppelin/contracts-upgradeable/utils/ContextUpgradeable.sol\n\n// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)\n\n/**\n * @dev Provides information about the current execution context, including the\n * sender of the transaction and its data. While these are generally available\n * via msg.sender and msg.data, they should not be accessed in such a direct\n * manner, since when dealing with meta-transactions the account sending and\n * paying for execution may not be the actual sender (as far as an application\n * is concerned).\n *\n * This contract is only required for intermediate, library-like contracts.\n */\nabstract contract ContextUpgradeable is Initializable {\n function __Context_init() internal onlyInitializing {\n }\n\n function __Context_init_unchained() internal onlyInitializing {\n }\n function _msgSender() internal view virtual returns (address) {\n return msg.sender;\n }\n\n function _msgData() internal view virtual returns (bytes calldata) {\n return msg.data;\n }\n\n /**\n * @dev This empty reserved space is put in place to allow future versions to add new\n * variables without shifting down storage in the inheritance chain.\n * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\n */\n uint256[50] private __gap;\n}\n\n// contracts/libs/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/utils/cryptography/ECDSA.sol\n\n// OpenZeppelin Contracts (last updated v4.9.0) (utils/cryptography/ECDSA.sol)\n\n/**\n * @dev Elliptic Curve Digital Signature Algorithm (ECDSA) operations.\n *\n * These functions can be used to verify that a message was signed by the holder\n * of the private keys of a given address.\n */\nlibrary ECDSA {\n enum RecoverError {\n NoError,\n InvalidSignature,\n InvalidSignatureLength,\n InvalidSignatureS,\n InvalidSignatureV // Deprecated in v4.8\n }\n\n function _throwError(RecoverError error) private pure {\n if (error == RecoverError.NoError) {\n return; // no error: do nothing\n } else if (error == RecoverError.InvalidSignature) {\n revert(\"ECDSA: invalid signature\");\n } else if (error == RecoverError.InvalidSignatureLength) {\n revert(\"ECDSA: invalid signature length\");\n } else if (error == RecoverError.InvalidSignatureS) {\n revert(\"ECDSA: invalid signature 's' value\");\n }\n }\n\n /**\n * @dev Returns the address that signed a hashed message (`hash`) with\n * `signature` or error string. This address can then be used for verification purposes.\n *\n * The `ecrecover` EVM opcode allows for malleable (non-unique) signatures:\n * this function rejects them by requiring the `s` value to be in the lower\n * half order, and the `v` value to be either 27 or 28.\n *\n * IMPORTANT: `hash` _must_ be the result of a hash operation for the\n * verification to be secure: it is possible to craft signatures that\n * recover to arbitrary addresses for non-hashed data. A safe way to ensure\n * this is by receiving a hash of the original message (which may otherwise\n * be too long), and then calling {toEthSignedMessageHash} on it.\n *\n * Documentation for signature generation:\n * - with https://web3js.readthedocs.io/en/v1.3.4/web3-eth-accounts.html#sign[Web3.js]\n * - with https://docs.ethers.io/v5/api/signer/#Signer-signMessage[ethers]\n *\n * _Available since v4.3._\n */\n function tryRecover(bytes32 hash, bytes memory signature) internal pure returns (address, RecoverError) {\n if (signature.length == 65) {\n bytes32 r;\n bytes32 s;\n uint8 v;\n // ecrecover takes the signature parameters, and the only way to get them\n // currently is to use assembly.\n /// @solidity memory-safe-assembly\n assembly {\n r := mload(add(signature, 0x20))\n s := mload(add(signature, 0x40))\n v := byte(0, mload(add(signature, 0x60)))\n }\n return tryRecover(hash, v, r, s);\n } else {\n return (address(0), RecoverError.InvalidSignatureLength);\n }\n }\n\n /**\n * @dev Returns the address that signed a hashed message (`hash`) with\n * `signature`. This address can then be used for verification purposes.\n *\n * The `ecrecover` EVM opcode allows for malleable (non-unique) signatures:\n * this function rejects them by requiring the `s` value to be in the lower\n * half order, and the `v` value to be either 27 or 28.\n *\n * IMPORTANT: `hash` _must_ be the result of a hash operation for the\n * verification to be secure: it is possible to craft signatures that\n * recover to arbitrary addresses for non-hashed data. A safe way to ensure\n * this is by receiving a hash of the original message (which may otherwise\n * be too long), and then calling {toEthSignedMessageHash} on it.\n */\n function recover(bytes32 hash, bytes memory signature) internal pure returns (address) {\n (address recovered, RecoverError error) = tryRecover(hash, signature);\n _throwError(error);\n return recovered;\n }\n\n /**\n * @dev Overload of {ECDSA-tryRecover} that receives the `r` and `vs` short-signature fields separately.\n *\n * See https://eips.ethereum.org/EIPS/eip-2098[EIP-2098 short signatures]\n *\n * _Available since v4.3._\n */\n function tryRecover(bytes32 hash, bytes32 r, bytes32 vs) internal pure returns (address, RecoverError) {\n bytes32 s = vs \u0026 bytes32(0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff);\n uint8 v = uint8((uint256(vs) \u003e\u003e 255) + 27);\n return tryRecover(hash, v, r, s);\n }\n\n /**\n * @dev Overload of {ECDSA-recover} that receives the `r and `vs` short-signature fields separately.\n *\n * _Available since v4.2._\n */\n function recover(bytes32 hash, bytes32 r, bytes32 vs) internal pure returns (address) {\n (address recovered, RecoverError error) = tryRecover(hash, r, vs);\n _throwError(error);\n return recovered;\n }\n\n /**\n * @dev Overload of {ECDSA-tryRecover} that receives the `v`,\n * `r` and `s` signature fields separately.\n *\n * _Available since v4.3._\n */\n function tryRecover(bytes32 hash, uint8 v, bytes32 r, bytes32 s) internal pure returns (address, RecoverError) {\n // EIP-2 still allows signature malleability for ecrecover(). Remove this possibility and make the signature\n // unique. Appendix F in the Ethereum Yellow paper (https://ethereum.github.io/yellowpaper/paper.pdf), defines\n // the valid range for s in (301): 0 \u003c s \u003c secp256k1n ÷ 2 + 1, and for v in (302): v ∈ {27, 28}. Most\n // signatures from current libraries generate a unique signature with an s-value in the lower half order.\n //\n // If your library generates malleable signatures, such as s-values in the upper range, calculate a new s-value\n // with 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141 - s1 and flip v from 27 to 28 or\n // vice versa. If your library also generates signatures with 0/1 for v instead 27/28, add 27 to v to accept\n // these malleable signatures as well.\n if (uint256(s) \u003e 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0) {\n return (address(0), RecoverError.InvalidSignatureS);\n }\n\n // If the signature is valid (and not malleable), return the signer address\n address signer = ecrecover(hash, v, r, s);\n if (signer == address(0)) {\n return (address(0), RecoverError.InvalidSignature);\n }\n\n return (signer, RecoverError.NoError);\n }\n\n /**\n * @dev Overload of {ECDSA-recover} that receives the `v`,\n * `r` and `s` signature fields separately.\n */\n function recover(bytes32 hash, uint8 v, bytes32 r, bytes32 s) internal pure returns (address) {\n (address recovered, RecoverError error) = tryRecover(hash, v, r, s);\n _throwError(error);\n return recovered;\n }\n\n /**\n * @dev Returns an Ethereum Signed Message, created from a `hash`. This\n * produces hash corresponding to the one signed with the\n * https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`]\n * JSON-RPC method as part of EIP-191.\n *\n * See {recover}.\n */\n function toEthSignedMessageHash(bytes32 hash) internal pure returns (bytes32 message) {\n // 32 is the length in bytes of hash,\n // enforced by the type signature above\n /// @solidity memory-safe-assembly\n assembly {\n mstore(0x00, \"\\x19Ethereum Signed Message:\\n32\")\n mstore(0x1c, hash)\n message := keccak256(0x00, 0x3c)\n }\n }\n\n /**\n * @dev Returns an Ethereum Signed Message, created from `s`. This\n * produces hash corresponding to the one signed with the\n * https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`]\n * JSON-RPC method as part of EIP-191.\n *\n * See {recover}.\n */\n function toEthSignedMessageHash(bytes memory s) internal pure returns (bytes32) {\n return keccak256(abi.encodePacked(\"\\x19Ethereum Signed Message:\\n\", Strings.toString(s.length), s));\n }\n\n /**\n * @dev Returns an Ethereum Signed Typed Data, created from a\n * `domainSeparator` and a `structHash`. This produces hash corresponding\n * to the one signed with the\n * https://eips.ethereum.org/EIPS/eip-712[`eth_signTypedData`]\n * JSON-RPC method as part of EIP-712.\n *\n * See {recover}.\n */\n function toTypedDataHash(bytes32 domainSeparator, bytes32 structHash) internal pure returns (bytes32 data) {\n /// @solidity memory-safe-assembly\n assembly {\n let ptr := mload(0x40)\n mstore(ptr, \"\\x19\\x01\")\n mstore(add(ptr, 0x02), domainSeparator)\n mstore(add(ptr, 0x22), structHash)\n data := keccak256(ptr, 0x42)\n }\n }\n\n /**\n * @dev Returns an Ethereum Signed Data with intended validator, created from a\n * `validator` and `data` according to the version 0 of EIP-191.\n *\n * See {recover}.\n */\n function toDataWithIntendedValidatorHash(address validator, bytes memory data) internal pure returns (bytes32) {\n return keccak256(abi.encodePacked(\"\\x19\\x00\", validator, data));\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/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/inbox/StatementInbox.sol\n\n// ══════════════════════════════ LIBRARY IMPORTS ══════════════════════════════\n\n// ═════════════════════════════ INTERNAL IMPORTS ══════════════════════════════\n\n// ═════════════════════════════ EXTERNAL IMPORTS ══════════════════════════════\n\n/// @notice `StatementInbox` is the entry point for all agent-signed statements. It verifies the\n/// agent signatures, and passes the unsigned statements to the contract to consume it via `acceptX` functions. Is is\n/// also used to verify the agent-signed statements and initiate the agent slashing, should the statement be invalid.\n/// `StatementInbox` is responsible for the following:\n/// - Accepting State and Receipt Reports to initiate a dispute between Guard and Notary.\n/// - Storing all the Guard Reports with the Guard signature leading to a dispute.\n/// - Verifying State/State Reports referencing the local chain and slashing the signer if statement is invalid.\n/// - Verifying Receipt/Receipt Reports referencing the local chain and slashing the signer if statement is invalid.\nabstract contract StatementInbox is MessagingBase, StatementInboxEvents, IStatementInbox {\n using AttestationLib for bytes;\n using ReceiptLib for bytes;\n using StateLib for bytes;\n using SnapshotLib for bytes;\n\n struct StoredReport {\n uint256 sigIndex;\n bytes statementPayload;\n }\n\n // ══════════════════════════════════════════════════ STORAGE ══════════════════════════════════════════════════════\n\n address public agentManager;\n address public origin;\n address public destination;\n\n // TODO: optimize this\n bytes[] internal _storedSignatures;\n StoredReport[] internal _storedReports;\n\n /// @dev gap for upgrade safety\n uint256[45] private __GAP; // solhint-disable-line var-name-mixedcase\n\n // ════════════════════════════════════════════════ INITIALIZER ════════════════════════════════════════════════════\n\n /// @dev Initializes the contract:\n /// - Sets up `msg.sender` as the owner of the contract.\n /// - Sets up `agentManager`, `origin`, and `destination`.\n // solhint-disable-next-line func-name-mixedcase\n function __StatementInbox_init(address agentManager_, address origin_, address destination_)\n internal\n onlyInitializing\n {\n agentManager = agentManager_;\n origin = origin_;\n destination = destination_;\n __Ownable2Step_init();\n }\n\n // ══════════════════════════════════════════ SUBMIT AGENT STATEMENTS ══════════════════════════════════════════════\n\n /// @inheritdoc IStatementInbox\n // solhint-disable-next-line ordering\n function submitStateReportWithSnapshot(\n uint8 stateIndex,\n bytes memory srSignature,\n bytes memory snapPayload,\n bytes memory snapSignature\n ) external returns (bool wasAccepted) {\n // This will revert if payload is not a snapshot\n Snapshot snapshot = snapPayload.castToSnapshot();\n // This will revert if the snapshot signer is not a known Notary\n (AgentStatus memory notaryStatus,) =\n _verifySnapshot({snapshot: snapshot, snapSignature: snapSignature, verifyNotary: true});\n // Notary needs to be Active/Unstaking\n notaryStatus.verifyActiveUnstaking();\n // Check if Notary is active on this chain\n _verifyNotaryDomain(notaryStatus.domain);\n // This will revert if state index is out of range\n State state = snapshot.state(stateIndex);\n // This will revert if the report signer is not an known Guard\n (AgentStatus memory guardStatus,) = _verifyStateReport(state, srSignature);\n // Check that Guard is active\n guardStatus.verifyActive();\n _saveReport(state.unwrap().clone(), srSignature);\n // This will revert if either actor is already in dispute\n IAgentManager(agentManager).openDispute(guardStatus.index, notaryStatus.index);\n return true;\n }\n\n /// @inheritdoc IStatementInbox\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 // This will revert if payload is not a snapshot\n Snapshot snapshot = snapPayload.castToSnapshot();\n // This will revert if state index is out of range\n State state = snapshot.state(stateIndex);\n // This will revert if the report signer is not an known Guard\n (AgentStatus memory guardStatus,) = _verifyStateReport(state, srSignature);\n // Check that Guard is active\n guardStatus.verifyActive();\n // This will revert if payload is not an attestation\n Attestation att = attPayload.castToAttestation();\n // This will revert if signer is not an known Notary\n (AgentStatus memory notaryStatus,) = _verifyAttestation(att, attSignature);\n // Notary needs to be Active/Unstaking\n notaryStatus.verifyActiveUnstaking();\n // Check if Notary is active on this chain\n _verifyNotaryDomain(notaryStatus.domain);\n if (snapshot.calculateRoot() != att.snapRoot()) revert IncorrectSnapshotRoot();\n _saveReport(state.unwrap().clone(), srSignature);\n // This will revert if either actor is already in dispute\n IAgentManager(agentManager).openDispute(guardStatus.index, notaryStatus.index);\n return true;\n }\n\n /// @inheritdoc IStatementInbox\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 // This will revert if payload is not a state\n State state = statePayload.castToState();\n // This will revert if the report signer is not an known Guard\n (AgentStatus memory guardStatus,) = _verifyStateReport(state, srSignature);\n // Check that Guard is active\n guardStatus.verifyActive();\n // This will revert if payload is not an attestation\n Attestation att = attPayload.castToAttestation();\n // This will revert if signer is not a known Notary\n (AgentStatus memory notaryStatus,) = _verifyAttestation(att, attSignature);\n // Notary needs to be Active/Unstaking\n notaryStatus.verifyActiveUnstaking();\n // Check if Notary is active on this chain\n _verifyNotaryDomain(notaryStatus.domain);\n // This will revert if any of these is true:\n // - Attestation root is not equal to Merkle Root derived from State and Snapshot Proof.\n // - Snapshot Proof's first element does not match the State metadata.\n // - Snapshot Proof length exceeds Snapshot tree Height.\n // - State index is out of range.\n _verifySnapshotMerkle(att, stateIndex, state, snapProof);\n _saveReport(statePayload, srSignature);\n // This will revert if either actor is already in dispute\n IAgentManager(agentManager).openDispute(guardStatus.index, notaryStatus.index);\n return true;\n }\n\n // ══════════════════════════════════════════ VERIFY AGENT STATEMENTS ══════════════════════════════════════════════\n\n /// @inheritdoc IStatementInbox\n function verifyReceipt(bytes memory rcptPayload, bytes memory rcptSignature)\n external\n returns (bool isValidReceipt)\n {\n // This will revert if payload is not a receipt\n Receipt rcpt = rcptPayload.castToReceipt();\n // This will revert if the attestation signer is not a known Notary\n (AgentStatus memory status, address notary) = _verifyReceipt(rcpt, rcptSignature);\n // Notary needs to be Active/Unstaking\n status.verifyActiveUnstaking();\n isValidReceipt = IExecutionHub(destination).isValidReceipt(rcptPayload);\n if (!isValidReceipt) {\n emit InvalidReceipt(rcptPayload, rcptSignature);\n IAgentManager(agentManager).slashAgent(status.domain, notary, msg.sender);\n }\n }\n\n /// @inheritdoc IStatementInbox\n function verifyReceiptReport(bytes memory rcptPayload, bytes memory rrSignature)\n external\n returns (bool isValidReport)\n {\n // This will revert if payload is not a receipt\n Receipt rcpt = rcptPayload.castToReceipt();\n // This will revert if the report signer is not a known Guard\n (AgentStatus memory status, address guard) = _verifyReceiptReport(rcpt, rrSignature);\n // Guard needs to be Active/Unstaking\n status.verifyActiveUnstaking();\n // Report is valid IF AND ONLY IF the reported receipt in invalid\n isValidReport = !IExecutionHub(destination).isValidReceipt(rcptPayload);\n if (!isValidReport) {\n emit InvalidReceiptReport(rcptPayload, rrSignature);\n IAgentManager(agentManager).slashAgent(status.domain, guard, msg.sender);\n }\n }\n\n /// @inheritdoc IStatementInbox\n function verifyStateWithAttestation(\n uint8 stateIndex,\n bytes memory snapPayload,\n bytes memory attPayload,\n bytes memory attSignature\n ) external returns (bool isValidState) {\n // This will revert if payload is not an attestation\n Attestation att = attPayload.castToAttestation();\n // This will revert if the attestation signer is not a known Notary\n (AgentStatus memory status, address notary) = _verifyAttestation(att, attSignature);\n // Notary needs to be Active/Unstaking\n status.verifyActiveUnstaking();\n // This will revert if payload is not a snapshot\n Snapshot snapshot = snapPayload.castToSnapshot();\n if (snapshot.calculateRoot() != att.snapRoot()) revert IncorrectSnapshotRoot();\n // This will revert if state does not refer to this chain\n bytes memory statePayload = snapshot.state(stateIndex).unwrap().clone();\n isValidState = IStateHub(origin).isValidState(statePayload);\n if (!isValidState) {\n emit InvalidStateWithAttestation(stateIndex, statePayload, attPayload, attSignature);\n IAgentManager(agentManager).slashAgent(status.domain, notary, msg.sender);\n }\n }\n\n /// @inheritdoc IStatementInbox\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 // This will revert if payload is not an attestation\n Attestation att = attPayload.castToAttestation();\n // This will revert if the attestation signer is not a known Notary\n (AgentStatus memory status, address notary) = _verifyAttestation(att, attSignature);\n // Notary needs to be Active/Unstaking\n status.verifyActiveUnstaking();\n // This will revert if payload is not a state\n State state = statePayload.castToState();\n // This will revert if any of these is true:\n // - Attestation root is not equal to Merkle Root derived from State and Snapshot Proof.\n // - Snapshot Proof's first element does not match the State metadata.\n // - Snapshot Proof length exceeds Snapshot tree Height.\n // - State index is out of range.\n _verifySnapshotMerkle(att, stateIndex, state, snapProof);\n // This will revert if state does not refer to this chain\n isValidState = IStateHub(origin).isValidState(statePayload);\n if (!isValidState) {\n emit InvalidStateWithAttestation(stateIndex, statePayload, attPayload, attSignature);\n IAgentManager(agentManager).slashAgent(status.domain, notary, msg.sender);\n }\n }\n\n /// @inheritdoc IStatementInbox\n function verifyStateWithSnapshot(uint8 stateIndex, bytes memory snapPayload, bytes memory snapSignature)\n external\n returns (bool isValidState)\n {\n // This will revert if payload is not a snapshot\n Snapshot snapshot = snapPayload.castToSnapshot();\n // This will revert if the snapshot signer is not a known Guard/Notary\n (AgentStatus memory status, address agent) =\n _verifySnapshot({snapshot: snapshot, snapSignature: snapSignature, verifyNotary: false});\n // Agent needs to be Active/Unstaking\n status.verifyActiveUnstaking();\n // This will revert if state does not refer to this chain\n isValidState = IStateHub(origin).isValidState(snapshot.state(stateIndex).unwrap().clone());\n if (!isValidState) {\n emit InvalidStateWithSnapshot(stateIndex, snapPayload, snapSignature);\n IAgentManager(agentManager).slashAgent(status.domain, agent, msg.sender);\n }\n }\n\n /// @inheritdoc IStatementInbox\n function verifyStateReport(bytes memory statePayload, bytes memory srSignature)\n external\n returns (bool isValidReport)\n {\n // This will revert if payload is not a state\n State state = statePayload.castToState();\n // This will revert if the report signer is not a known Guard\n (AgentStatus memory status, address guard) = _verifyStateReport(state, srSignature);\n // Guard needs to be Active/Unstaking\n status.verifyActiveUnstaking();\n // Report is valid IF AND ONLY IF the reported state in invalid\n // This will revert if the reported state does not refer to this chain\n isValidReport = !IStateHub(origin).isValidState(statePayload);\n if (!isValidReport) {\n emit InvalidStateReport(statePayload, srSignature);\n IAgentManager(agentManager).slashAgent(status.domain, guard, msg.sender);\n }\n }\n\n // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════\n\n /// @inheritdoc IStatementInbox\n function getReportsAmount() external view returns (uint256) {\n return _storedReports.length;\n }\n\n /// @inheritdoc IStatementInbox\n function getGuardReport(uint256 index)\n external\n view\n returns (bytes memory statementPayload, bytes memory reportSignature)\n {\n if (index \u003e= _storedReports.length) revert IndexOutOfRange();\n StoredReport memory storedReport = _storedReports[index];\n statementPayload = storedReport.statementPayload;\n reportSignature = _storedSignatures[storedReport.sigIndex];\n }\n\n /// @inheritdoc IStatementInbox\n function getStoredSignature(uint256 index) external view returns (bytes memory) {\n return _storedSignatures[index];\n }\n\n // ══════════════════════════════════════════════ INTERNAL LOGIC ═══════════════════════════════════════════════════\n\n /// @dev Saves the statement reported by Guard as invalid and the Guard Report signature.\n function _saveReport(bytes memory statementPayload, bytes memory reportSignature) internal {\n uint256 sigIndex = _saveSignature(reportSignature);\n _storedReports.push(StoredReport(sigIndex, statementPayload));\n }\n\n /// @dev Saves the signature and returns its index.\n function _saveSignature(bytes memory signature) internal returns (uint256 sigIndex) {\n sigIndex = _storedSignatures.length;\n _storedSignatures.push(signature);\n }\n\n // ═══════════════════════════════════════════════ AGENT CHECKS ════════════════════════════════════════════════════\n\n /**\n * @dev Recovers a signer from a hashed message, and a EIP-191 signature for it.\n * Will revert, if the signer is not a known agent.\n * @dev Agent flag could be any of these: Active/Unstaking/Resting/Fraudulent/Slashed\n * Further checks need to be performed in a caller function.\n * @param hashedStatement Hash of the statement that was signed by an Agent\n * @param signature Agent signature for the hashed statement\n * @return status Struct representing agent status:\n * - flag Unknown/Active/Unstaking/Resting/Fraudulent/Slashed\n * - domain Domain where agent is/was active\n * - index Index of agent in the Agent Merkle Tree\n * @return agent Agent that signed the statement\n */\n function _recoverAgent(bytes32 hashedStatement, bytes memory signature)\n internal\n view\n returns (AgentStatus memory status, address agent)\n {\n bytes32 ethSignedMsg = ECDSA.toEthSignedMessageHash(hashedStatement);\n agent = ECDSA.recover(ethSignedMsg, signature);\n status = IAgentManager(agentManager).agentStatus(agent);\n // Discard signature of unknown agents.\n // Further flag checks are supposed to be performed in a caller function.\n status.verifyKnown();\n }\n\n /// @dev Verifies that Notary signature is active on local domain.\n function _verifyNotaryDomain(uint32 notaryDomain) internal view {\n // Notary needs to be from the local domain (if contract is not deployed on Synapse Chain).\n // Or Notary could be from any domain (if contract is deployed on Synapse Chain).\n if (notaryDomain != localDomain \u0026\u0026 localDomain != synapseDomain) revert IncorrectAgentDomain();\n }\n\n // ════════════════════════════════════════ ATTESTATION RELATED CHECKS ═════════════════════════════════════════════\n\n /**\n * @dev Internal function to verify the signed attestation payload.\n * Reverts if any of these is true:\n * - Attestation signer is not a known Notary.\n * @param att Typed memory view over attestation payload\n * @param attSignature Notary signature for the attestation\n * @return status Struct representing agent status, see {_recoverAgent}\n * @return notary Notary that signed the snapshot\n */\n function _verifyAttestation(Attestation att, bytes memory attSignature)\n internal\n view\n returns (AgentStatus memory status, address notary)\n {\n // This will revert if signer is not a known agent\n (status, notary) = _recoverAgent(att.hashValid(), attSignature);\n // Attestation signer needs to be a Notary, not a Guard\n if (status.domain == 0) revert AgentNotNotary();\n }\n\n /**\n * @dev Internal function to verify the signed attestation report payload.\n * Reverts if any of these is true:\n * - Report signer is not a known Guard.\n * @param att Typed memory view over attestation payload that Guard reports as invalid\n * @param arSignature Guard signature for the \"invalid attestation\" report\n * @return status Struct representing guard status, see {_recoverAgent}\n * @return guard Guard that signed the report\n */\n function _verifyAttestationReport(Attestation att, bytes memory arSignature)\n internal\n view\n returns (AgentStatus memory status, address guard)\n {\n // This will revert if signer is not a known agent\n (status, guard) = _recoverAgent(att.hashInvalid(), arSignature);\n // Report signer needs to be a Guard, not a Notary\n if (status.domain != 0) revert AgentNotGuard();\n }\n\n // ══════════════════════════════════════════ RECEIPT RELATED CHECKS ═══════════════════════════════════════════════\n\n /**\n * @dev Internal function to verify the signed receipt payload.\n * Reverts if any of these is true:\n * - Receipt signer is not a known Notary.\n * @param rcpt Typed memory view over receipt payload\n * @param rcptSignature Notary signature for the receipt\n * @return status Struct representing agent status, see {_recoverAgent}\n * @return notary Notary that signed the snapshot\n */\n function _verifyReceipt(Receipt rcpt, bytes memory rcptSignature)\n internal\n view\n returns (AgentStatus memory status, address notary)\n {\n // This will revert if signer is not a known agent\n (status, notary) = _recoverAgent(rcpt.hashValid(), rcptSignature);\n // Receipt signer needs to be a Notary, not a Guard\n if (status.domain == 0) revert AgentNotNotary();\n }\n\n /**\n * @dev Internal function to verify the signed receipt report payload.\n * Reverts if any of these is true:\n * - Report signer is not a known Guard.\n * @param rcpt Typed memory view over receipt payload that Guard reports as invalid\n * @param rrSignature Guard signature for the \"invalid receipt\" report\n * @return status Struct representing guard status, see {_recoverAgent}\n * @return guard Guard that signed the report\n */\n function _verifyReceiptReport(Receipt rcpt, bytes memory rrSignature)\n internal\n view\n returns (AgentStatus memory status, address guard)\n {\n // This will revert if signer is not a known agent\n (status, guard) = _recoverAgent(rcpt.hashInvalid(), rrSignature);\n // Report signer needs to be a Guard, not a Notary\n if (status.domain != 0) revert AgentNotGuard();\n }\n\n // ═══════════════════════════════════════ STATE/SNAPSHOT RELATED CHECKS ═══════════════════════════════════════════\n\n /**\n * @dev Internal function to verify the signed snapshot report payload.\n * Reverts if any of these is true:\n * - Report signer is not a known Guard.\n * @param state Typed memory view over state payload that Guard reports as invalid\n * @param srSignature Guard signature for the report\n * @return status Struct representing guard status, see {_recoverAgent}\n * @return guard Guard that signed the report\n */\n function _verifyStateReport(State state, bytes memory srSignature)\n internal\n view\n returns (AgentStatus memory status, address guard)\n {\n // This will revert if signer is not a known agent\n (status, guard) = _recoverAgent(state.hashInvalid(), srSignature);\n // Report signer needs to be a Guard, not a Notary\n if (status.domain != 0) revert AgentNotGuard();\n }\n\n /**\n * @dev Internal function to verify the signed snapshot payload.\n * Reverts if any of these is true:\n * - Snapshot signer is not a known Agent.\n * - Snapshot signer is not a Notary (if verifyNotary is true).\n * @param snapshot Typed memory view over snapshot payload\n * @param snapSignature Agent signature for the snapshot\n * @param verifyNotary If true, snapshot signer needs to be a Notary, not a Guard\n * @return status Struct representing agent status, see {_recoverAgent}\n * @return agent Agent that signed the snapshot\n */\n function _verifySnapshot(Snapshot snapshot, bytes memory snapSignature, bool verifyNotary)\n internal\n view\n returns (AgentStatus memory status, address agent)\n {\n // This will revert if signer is not a known agent\n (status, agent) = _recoverAgent(snapshot.hashValid(), snapSignature);\n // If requested, snapshot signer needs to be a Notary, not a Guard\n if (verifyNotary \u0026\u0026 status.domain == 0) revert AgentNotNotary();\n }\n\n // ═══════════════════════════════════════════ MERKLE RELATED CHECKS ═══════════════════════════════════════════════\n\n /**\n * @dev Internal function to verify that snapshot roots match.\n * Reverts if any of these is true:\n * - Attestation root is not equal to Merkle Root derived from State and Snapshot Proof.\n * - Snapshot Proof's first element does not match the State metadata.\n * - Snapshot Proof length exceeds Snapshot tree Height.\n * - State index is out of range.\n * @param att Typed memory view over Attestation\n * @param stateIndex Index of state in the snapshot\n * @param state Typed memory view over the provided state payload\n * @param snapProof Raw payload with snapshot data\n */\n function _verifySnapshotMerkle(Attestation att, uint8 stateIndex, State state, bytes32[] memory snapProof)\n internal\n pure\n {\n // Snapshot proof first element should match State metadata (aka \"right sub-leaf\")\n (, bytes32 rightSubLeaf) = state.subLeafs();\n if (snapProof[0] != rightSubLeaf) revert IncorrectSnapshotProof();\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(state.root(), state.origin(), snapProof, stateIndex);\n // Snapshot root should match the attestation root\n if (att.snapRoot() != snapshotRoot) revert IncorrectSnapshotRoot();\n }\n}\n\n// contracts/inbox/Inbox.sol\n\n// ══════════════════════════════ LIBRARY IMPORTS ══════════════════════════════\n\n// ═════════════════════════════ INTERNAL IMPORTS ══════════════════════════════\n\n/// @notice `Inbox` is the child of `StatementInbox` contract, that is used on Synapse Chain.\n/// In addition to the functionality of `StatementInbox`, it also:\n/// - Accepts Guard and Notary Snapshots and passes them to `Summit` contract.\n/// - Accepts Notary-signed Receipts and passes them to `Summit` contract.\n/// - Accepts Receipt Reports to initiate a dispute between Guard and Notary.\n/// - Verifies Attestations and Attestation Reports, and slashes the signer if they are invalid.\ncontract Inbox is StatementInbox, InboxEvents, InterfaceInbox {\n using AttestationLib for bytes;\n using ReceiptLib for bytes;\n using SnapshotLib for bytes;\n\n // Struct to get around stack too deep error. TODO: revisit this\n struct ReceiptInfo {\n AgentStatus rcptNotaryStatus;\n address notary;\n uint32 attNonce;\n AgentStatus attNotaryStatus;\n }\n\n // ══════════════════════════════════════════════════ STORAGE ══════════════════════════════════════════════════════\n\n // The address of the Summit contract.\n address public summit;\n\n // ═════════════════════════════════════════ CONSTRUCTOR \u0026 INITIALIZER ═════════════════════════════════════════════\n\n constructor(uint32 synapseDomain_) MessagingBase(\"0.0.3\", synapseDomain_) {\n if (localDomain != synapseDomain) revert MustBeSynapseDomain();\n }\n\n /// @notice Initializes `Inbox` contract:\n /// - Sets `msg.sender` as the owner of the contract\n /// - Sets `agentManager`, `origin`, `destination` and `summit` addresses\n function initialize(address agentManager_, address origin_, address destination_, address summit_)\n external\n initializer\n {\n __StatementInbox_init(agentManager_, origin_, destination_);\n summit = summit_;\n }\n\n // ══════════════════════════════════════════ SUBMIT AGENT STATEMENTS ══════════════════════════════════════════════\n\n /// @inheritdoc InterfaceInbox\n function submitSnapshot(bytes memory snapPayload, bytes memory snapSignature)\n external\n returns (bytes memory attPayload, bytes32 agentRoot_, uint256[] memory snapGas)\n {\n // This will revert if payload is not a snapshot\n Snapshot snapshot = snapPayload.castToSnapshot();\n // This will revert if the signer is not a known Guard/Notary\n (AgentStatus memory status, address agent) =\n _verifySnapshot({snapshot: snapshot, snapSignature: snapSignature, verifyNotary: false});\n // Check that Agent is active\n status.verifyActive();\n // Store Agent signature for the Snapshot\n uint256 sigIndex = _saveSignature(snapSignature);\n if (status.domain == 0) {\n // Guard that is in Dispute could still submit new snapshots, so we don't check that\n InterfaceSummit(summit).acceptGuardSnapshot({\n guardIndex: status.index,\n sigIndex: sigIndex,\n snapPayload: snapPayload\n });\n } else {\n // Get current agentRoot from AgentManager\n agentRoot_ = IAgentManager(agentManager).agentRoot();\n // This will revert if Notary is in Dispute\n attPayload = InterfaceSummit(summit).acceptNotarySnapshot({\n notaryIndex: status.index,\n sigIndex: sigIndex,\n agentRoot: agentRoot_,\n snapPayload: snapPayload\n });\n ChainGas[] memory snapGas_ = snapshot.snapGas();\n // Pass created attestation to Destination to enable executing messages coming to Synapse Chain\n InterfaceDestination(destination).acceptAttestation(\n status.index, type(uint256).max, attPayload, agentRoot_, snapGas_\n );\n // Use assembly to cast ChainGas[] to uint256[] without copying. Highest bits are left zeroed.\n // solhint-disable-next-line no-inline-assembly\n assembly {\n snapGas := snapGas_\n }\n }\n emit SnapshotAccepted(status.domain, agent, snapPayload, snapSignature);\n }\n\n /// @inheritdoc InterfaceInbox\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 // Struct to get around stack too deep error.\n ReceiptInfo memory info;\n // This will revert if payload is not a receipt\n Receipt rcpt = rcptPayload.castToReceipt();\n // This will revert if the receipt signer is not a known Notary\n (info.rcptNotaryStatus, info.notary) = _verifyReceipt(rcpt, rcptSignature);\n // Receipt Notary needs to be Active\n info.rcptNotaryStatus.verifyActive();\n info.attNonce = IExecutionHub(destination).getAttestationNonce(rcpt.snapshotRoot());\n if (info.attNonce == 0) revert IncorrectSnapshotRoot();\n // Attestation Notary domain needs to match the destination domain\n info.attNotaryStatus = IAgentManager(agentManager).agentStatus(rcpt.attNotary());\n if (info.attNotaryStatus.domain != rcpt.destination()) revert IncorrectAgentDomain();\n // Check that the correct tip values for the message were provided\n _verifyReceiptTips(rcpt.messageHash(), paddedTips, headerHash, bodyHash);\n // Store Notary signature for the Receipt\n uint256 sigIndex = _saveSignature(rcptSignature);\n // This will revert if Receipt Notary is in Dispute\n wasAccepted = InterfaceSummit(summit).acceptReceipt({\n rcptNotaryIndex: info.rcptNotaryStatus.index,\n attNotaryIndex: info.attNotaryStatus.index,\n sigIndex: sigIndex,\n attNonce: info.attNonce,\n paddedTips: paddedTips,\n rcptPayload: rcptPayload\n });\n if (wasAccepted) {\n emit ReceiptAccepted(info.rcptNotaryStatus.domain, info.notary, rcptPayload, rcptSignature);\n }\n }\n\n /// @inheritdoc InterfaceInbox\n function submitReceiptReport(bytes memory rcptPayload, bytes memory rcptSignature, bytes memory rrSignature)\n external\n returns (bool wasAccepted)\n {\n // This will revert if payload is not a receipt\n Receipt rcpt = rcptPayload.castToReceipt();\n // This will revert if the receipt signer is not a known Guard\n (AgentStatus memory guardStatus,) = _verifyReceiptReport(rcpt, rrSignature);\n // Guard needs to be Active\n guardStatus.verifyActive();\n // This will revert if report signer is not a known Notary\n (AgentStatus memory notaryStatus,) = _verifyReceipt(rcpt, rcptSignature);\n // Notary needs to be Active/Unstaking\n notaryStatus.verifyActiveUnstaking();\n _saveReport(rcptPayload, rrSignature);\n // This will revert if either actor is already in dispute\n IAgentManager(agentManager).openDispute(guardStatus.index, notaryStatus.index);\n return true;\n }\n\n /// @inheritdoc InterfaceInbox\n function passReceipt(uint32 attNotaryIndex, uint32 attNonce, uint256 paddedTips, bytes memory rcptPayload)\n external\n returns (bool wasAccepted)\n {\n // Only Destination can pass receipts\n if (msg.sender != destination) revert CallerNotDestination();\n return InterfaceSummit(summit).acceptReceipt({\n rcptNotaryIndex: attNotaryIndex,\n attNotaryIndex: attNotaryIndex,\n sigIndex: type(uint256).max,\n attNonce: attNonce,\n paddedTips: paddedTips,\n rcptPayload: rcptPayload\n });\n }\n\n // ══════════════════════════════════════════ VERIFY AGENT STATEMENTS ══════════════════════════════════════════════\n\n /// @inheritdoc InterfaceInbox\n function verifyAttestation(bytes memory attPayload, bytes memory attSignature)\n external\n returns (bool isValidAttestation)\n {\n // This will revert if payload is not an attestation\n Attestation att = attPayload.castToAttestation();\n // This will revert if the attestation signer is not a known Notary\n (AgentStatus memory status, address notary) = _verifyAttestation(att, attSignature);\n // Notary needs to be Active/Unstaking\n status.verifyActiveUnstaking();\n isValidAttestation = ISnapshotHub(summit).isValidAttestation(attPayload);\n if (!isValidAttestation) {\n emit InvalidAttestation(attPayload, attSignature);\n IAgentManager(agentManager).slashAgent(status.domain, notary, msg.sender);\n }\n }\n\n /// @inheritdoc InterfaceInbox\n function verifyAttestationReport(bytes memory attPayload, bytes memory arSignature)\n external\n returns (bool isValidReport)\n {\n // This will revert if payload is not an attestation\n Attestation att = attPayload.castToAttestation();\n // This will revert if the report signer is not a known Guard\n (AgentStatus memory status, address guard) = _verifyAttestationReport(att, arSignature);\n // Guard needs to be Active/Unstaking\n status.verifyActiveUnstaking();\n // Report is valid IF AND ONLY IF the reported attestation in invalid\n isValidReport = !ISnapshotHub(summit).isValidAttestation(attPayload);\n if (!isValidReport) {\n emit InvalidAttestationReport(attPayload, arSignature);\n IAgentManager(agentManager).slashAgent(status.domain, guard, msg.sender);\n }\n }\n\n // ══════════════════════════════════════════════ INTERNAL VIEWS ═══════════════════════════════════════════════════\n\n /// @dev Verifies that tips proof matches the message hash.\n function _verifyReceiptTips(bytes32 msgHash, uint256 paddedTips, bytes32 headerHash, bytes32 bodyHash)\n internal\n pure\n {\n Tips tips = TipsLib.wrapPadded(paddedTips);\n // full message leaf is (header, baseMessage), while base message leaf is (tips, remainingBody).\n if (MerkleMath.getParent(headerHash, MerkleMath.getParent(tips.leaf(), bodyHash)) != msgHash) {\n revert IncorrectTipsProof();\n }\n }\n}\n","language":"Solidity","languageVersion":"0.8.17","compilerVersion":"0.8.17","compilerOptions":"--combined-json bin,bin-runtime,srcmap,srcmap-runtime,abi,userdoc,devdoc,metadata,hashes --optimize --optimize-runs 10000 --allow-paths ., ./, ../","srcMap":"","srcMapRuntime":"","abiDefinition":[{"inputs":[{"internalType":"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/Inbox.sol\":\"IStatementInbox\"},\"evmVersion\":\"london\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\"},\"optimizer\":{\"enabled\":true,\"runs\":10000},\"remappings\":[]},\"sources\":{\"solidity/Inbox.sol\":{\"keccak256\":\"0x9b516081a036814c0169e20e484d4a5499066b7a6f48fada952b5e844a1ca3e5\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://32bde393b3f24ef4307d9626d4143f337b3c0bd34e17bb969fd5a15221d96987\",\"dweb:/ipfs/QmTkt2XZRtgsbSpmsVQUM3c4ebETQoDVYbmEV9yheBghnr\"]}},\"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/Inbox.sol:Inbox":{"code":"0x6101006040523480156200001257600080fd5b5060405162004d1638038062004d16833981016040819052620000359162000146565b60408051808201909152600580825264302e302e3360d81b60208301526080528181620000628162000175565b60a08181525050506200007f620000bb60201b620021181760201c565b63ffffffff90811660c0819052911660e0819052149050620000b457604051632b3a807f60e01b815260040160405180910390fd5b506200019d565b6000620000d346620000d860201b620021281760201c565b905090565b600063ffffffff821115620001425760405162461bcd60e51b815260206004820152602660248201527f53616665436173743a2076616c756520646f65736e27742066697420696e203360448201526532206269747360d01b606482015260840160405180910390fd5b5090565b6000602082840312156200015957600080fd5b815163ffffffff811681146200016e57600080fd5b9392505050565b8051602080830151919081101562000197576000198160200360031b1b821691505b50919050565b60805160a05160c05160e051614b2a620001ec6000396000818161031b01526124560152600081816103d40152818161241f015261247d015260006102a7015260006102840152614b2a6000f3fe608060405234801561001057600080fd5b50600436106101f05760003560e01c80638d3638f41161010f578063c25aa585116100a2578063e3097af811610071578063e3097af8146104d3578063e30c3978146104e6578063f2fde38b146104f7578063f8c8765e1461050a57600080fd5b8063c25aa58514610479578063c495912b1461048c578063ddeffa66146104ad578063dfe39675146104c057600080fd5b80639fbcb9cb116100de5780639fbcb9cb1461042d578063b269681d14610440578063b2a4b45514610453578063be7e63da1461046657600080fd5b80638d3638f4146103cf5780638da5cb5b146103f657806391af2e5d14610407578063938b5f321461041a57600080fd5b8063715018a61161018757806379ba50971161015657806379ba50971461038e5780637d9978ae146103965780638671012e146103a957806389246503146103bc57600080fd5b8063715018a61461030c578063717b863814610316578063756ed01d146103525780637622f78d1461036357600080fd5b80634bb73ea5116101c35780634bb73ea51461025657806354fd4d501461027857806360fc8466146102d95780636b47b3bc146102f957600080fd5b80630ca77473146101f5578063243b92241461021d57806331e8df5a14610230578063333138e214610243575b600080fd5b610208610203366004613cf9565b61051d565b60405190151581526020015b60405180910390f35b61020861022b366004613d73565b6106a9565b61020861023e366004613cf9565b610810565b610208610251366004613e31565b6108fb565b610269610264366004613cf9565b610a09565b60405161021493929190613f1a565b604080518082019091527f000000000000000000000000000000000000000000000000000000000000000081527f000000000000000000000000000000000000000000000000000000000000000060208201525b6040516102149190613f76565b6102ec6102e7366004613f89565b610cf5565b6040516102149190613ffe565b610208610307366004614096565b610e57565b610314610f3f565b005b61033d7f000000000000000000000000000000000000000000000000000000000000000081565b60405163ffffffff9091168152602001610214565b60cd54604051908152602001610214565b60c954610376906001600160a01b031681565b6040516001600160a01b039091168152602001610214565b610314610f49565b6102086103a4366004613e31565b610ff6565b6102086103b73660046140f6565b6111f9565b6102086103ca36600461416a565b611381565b61033d7f000000000000000000000000000000000000000000000000000000000000000081565b6033546001600160a01b0316610376565b610208610415366004613cf9565b611465565b60ca54610376906001600160a01b031681565b60fb54610376906001600160a01b031681565b60cb54610376906001600160a01b031681565b6102086104613660046141b9565b611550565b6102086104743660046142ad565b61185f565b610208610487366004613cf9565b6118cd565b61049f61049a36600461438e565b6119b7565b6040516102149291906143a7565b6102cc6104bb36600461438e565b611b7c565b6102086104ce366004613cf9565b611c2b565b6102086104e13660046143cc565b611d16565b6065546001600160a01b0316610376565b61031461050536600461444f565b611ec3565b61031461051836600461446a565b611f4c565b600080610529846121c2565b905060008061053883866121db565b915091506105458261225a565b60fb546040517f4362fd110000000000000000000000000000000000000000000000000000000081526001600160a01b0390911690634362fd119061058e908990600401613f76565b602060405180830381865afa1580156105ab573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105cf91906144be565b9350836106a0577f5ce497fe75d0d52e5ee139d2cd651d0ff00692a94d7052cb37faef5592d74b2b86866040516106079291906143a7565b60405180910390a160c95460208301516040517f2853a0e600000000000000000000000000000000000000000000000000000000815263ffffffff90911660048201526001600160a01b03838116602483015233604483015290911690632853a0e690606401600060405180830381600087803b15801561068757600080fd5b505af115801561069b573d6000803e3d6000fd5b505050505b50505092915050565b6000806106b5856122c7565b905060006106c68260ff8a166122da565b905060006106d48289612361565b5090506106e0816123d1565b60006106eb876121c2565b905060006106f982886121db565b5090506107058161225a565b610712816020015161241d565b61071b826124dc565b610724866124ed565b1461075b576040517f2546f9ea00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61077261076c856125c6565b6125c6565b8b612605565b60c9546040848101518382015191517fa2155c3400000000000000000000000000000000000000000000000000000000815263ffffffff9182166004820152911660248201526001600160a01b039091169063a2155c3490604401600060405180830381600087803b1580156107e757600080fd5b505af11580156107fb573d6000803e3d6000fd5b5060019e9d5050505050505050505050505050565b60008061081c846121c2565b905060008061082b838661269f565b915091506108388261225a565b60fb546040517f4362fd110000000000000000000000000000000000000000000000000000000081526001600160a01b0390911690634362fd1190610881908990600401613f76565b602060405180830381865afa15801561089e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108c291906144be565b159350836106a0577f6f83f9b71f5c687c7dd205d520001d4e5adc1f16e4e2ee5b798c720d643e5a9e86866040516106079291906143a7565b600080610907846122c7565b90506000610917828560016126c8565b5090506109238161225a565b610930816020015161241d565b600061093f8360ff8a166122da565b9050600061094d8289612361565b509050610959816123d1565b61096b610965836125c6565b89612605565b60c9546040828101518582015191517fa2155c3400000000000000000000000000000000000000000000000000000000815263ffffffff9182166004820152911660248201526001600160a01b039091169063a2155c3490604401600060405180830381600087803b1580156109e057600080fd5b505af11580156109f4573d6000803e3d6000fd5b5050505060019450505050505b949350505050565b6060600060606000610a1a866122c7565b9050600080610a2b838860006126c8565b91509150610a38826123d1565b6000610a4388612750565b9050826020015163ffffffff16600003610ade5760fb5460408085015190517f9cc1bb310000000000000000000000000000000000000000000000000000000081526001600160a01b0390921691639cc1bb3191610aa79185908e906004016144e0565b600060405180830381600087803b158015610ac157600080fd5b505af1158015610ad5573d6000803e3d6000fd5b50505050610c9c565b60c960009054906101000a90046001600160a01b03166001600160a01b03166336cba43c6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610b31573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b559190614505565b60fb5460408086015190517ef340540000000000000000000000000000000000000000000000000000000081529298506001600160a01b039091169162f3405491610ba89185908b908f9060040161451e565b6000604051808303816000875af1158015610bc7573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052610bef9190810190614553565b96506000610bfc85612793565b60cb5460408087015190517f39fe27360000000000000000000000000000000000000000000000000000000081529293506001600160a01b03909116916339fe273691610c5591600019908d908d9088906004016145c1565b6020604051808303816000875af1158015610c74573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c9891906144be565b5094505b816001600160a01b0316836020015163ffffffff167f5ca3d740e03650b41813a4b418830f6ba39700ae010fe8c4d1bca0e8676b9c568b8b604051610ce29291906143a7565b60405180910390a3505050509250925092565b6060818067ffffffffffffffff811115610d1157610d11613c1b565b604051908082528060200260200182016040528015610d5757816020015b604080518082019091526000815260606020820152815260200190600190039081610d2f5790505b5091503660005b828110156106a057858582818110610d7857610d78614643565b9050602002810190610d8a9190614672565b91506000848281518110610da057610da0614643565b60200260200101519050306001600160a01b0316838060200190610dc491906146b0565b604051610dd2929190614715565b600060405180830381855af49150503d8060008114610e0d576040519150601f19603f3d011682016040523d82523d6000602084013e610e12565b606091505b5060208301521515808252833517610e4e577f4d6a23280000000000000000000000000000000000000000000000000000000060005260046000fd5b50600101610d5e565b60cb546000906001600160a01b03163314610e9e576040517f6efcc49f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60fb546040517fc79a431b0000000000000000000000000000000000000000000000000000000081526001600160a01b039091169063c79a431b90610ef39088908190600019908a908a908a90600401614725565b6020604051808303816000875af1158015610f12573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f3691906144be565b95945050505050565b610f47612882565b565b60655433906001600160a01b03168114610fea576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602960248201527f4f776e61626c6532537465703a2063616c6c6572206973206e6f74207468652060448201527f6e6577206f776e6572000000000000000000000000000000000000000000000060648201526084015b60405180910390fd5b610ff3816128f6565b50565b600080611002846121c2565b905060008061101183866121db565b9150915061101e8261225a565b6000611029886122c7565b9050611034846124dc565b61103d826124ed565b14611074576040517f2546f9ea00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600061108c6107676110898460ff8e166122da565b90565b60ca546040517fa9dcf22d0000000000000000000000000000000000000000000000000000000081529192506001600160a01b03169063a9dcf22d906110d6908490600401613f76565b602060405180830381865afa1580156110f3573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061111791906144be565b9550856111ec577f802f82273c009c05274153f0f1bde4e9e06244157a2914d4b84d266a3fa82ff18a828a8a604051611153949392919061476e565b60405180910390a160c95460208501516040517f2853a0e600000000000000000000000000000000000000000000000000000000815263ffffffff90911660048201526001600160a01b03858116602483015233604483015290911690632853a0e690606401600060405180830381600087803b1580156111d357600080fd5b505af11580156111e7573d6000803e3d6000fd5b505050505b5050505050949350505050565b600080611205846122c7565b9050600080611216838660006126c8565b915091506112238261225a565b60ca546001600160a01b031663a9dcf22d6112476107676110898760ff8d166122da565b6040518263ffffffff1660e01b81526004016112639190613f76565b602060405180830381865afa158015611280573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906112a491906144be565b935083611377577ff649e0d8f524df47b57dbcc2cda237f72096391dff21abc122acebd5112f4de08787876040516112de939291906147b0565b60405180910390a160c95460208301516040517f2853a0e600000000000000000000000000000000000000000000000000000000815263ffffffff90911660048201526001600160a01b03838116602483015233604483015290911690632853a0e690606401600060405180830381600087803b15801561135e57600080fd5b505af1158015611372573d6000803e3d6000fd5b505050505b5050509392505050565b60008061138d85612927565b9050600061139b828561293a565b5090506113a7816123d1565b60006113b38387612963565b5090506113bf8161225a565b6113c98786612605565b60c9546040838101518382015191517fa2155c3400000000000000000000000000000000000000000000000000000000815263ffffffff9182166004820152911660248201526001600160a01b039091169063a2155c3490604401600060405180830381600087803b15801561143e57600080fd5b505af1158015611452573d6000803e3d6000fd5b50505050600193505050505b9392505050565b60008061147184612927565b9050600080611480838661293a565b9150915061148d8261225a565b60cb546040517fe2f006f70000000000000000000000000000000000000000000000000000000081526001600160a01b039091169063e2f006f7906114d6908990600401613f76565b602060405180830381865afa1580156114f3573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061151791906144be565b159350836106a0577fa0cb383b7028fbeae86e018eb9fe765c15c869483a584edbb95bf5509344658786866040516106079291906143a7565b600061155a613bb9565b600061156588612927565b90506115718188612963565b6001600160a01b0316602084015280835261158b906123d1565b60cb546001600160a01b0316634f1275676115a58361298c565b6040518263ffffffff1660e01b81526004016115c391815260200190565b602060405180830381865afa1580156115e0573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061160491906147de565b63ffffffff166040830181905260000361164a576040517f2546f9ea00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60c9546001600160a01b03166328f3fac96116648361299b565b6040517fffffffff0000000000000000000000000000000000000000000000000000000060e084901b1681526001600160a01b039091166004820152602401606060405180830381865afa1580156116c0573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906116e491906147fb565b60608301526116f2816129a8565b63ffffffff1682606001516020015163ffffffff161461173e576040517f1612d2ee00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61175261174a826129b9565b8787876129c8565b600061175d88612750565b905060fb60009054906101000a90046001600160a01b03166001600160a01b031663c79a431b8460000151604001518560600151604001518487604001518c8f6040518763ffffffff1660e01b81526004016117be96959493929190614725565b6020604051808303816000875af11580156117dd573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061180191906144be565b93508315611853577f9377955fede38ca63bc09f7b3fae7dd349934c78c058963a6d3c05d4eed0411283600001516020015184602001518b8b60405161184a9493929190614871565b60405180910390a15b50505095945050505050565b60008061186b87612a27565b905060006118798288612361565b509050611885816123d1565b6000611890866121c2565b9050600061189e82876121db565b5090506118aa8161225a565b6118b7816020015161241d565b6118c3828c868b612a35565b6107728a8a612605565b6000806118d984612927565b90506000806118e88386612963565b915091506118f58261225a565b60cb546040517fe2f006f70000000000000000000000000000000000000000000000000000000081526001600160a01b039091169063e2f006f79061193e908990600401613f76565b602060405180830381865afa15801561195b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061197f91906144be565b9350836106a0577f4d4c3a87f0d5fbcea3c51d5baa727fceedb200dd7c9287f7ef85b60b794d6a8d86866040516106079291906143a7565b60cd54606090819083106119f7576040517f1390f2a100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600060cd8481548110611a0c57611a0c614643565b906000526020600020906002020160405180604001604052908160008201548152602001600182018054611a3f906148b1565b80601f0160208091040260200160405190810160405280929190818152602001828054611a6b906148b1565b8015611ab85780601f10611a8d57610100808354040283529160200191611ab8565b820191906000526020600020905b815481529060010190602001808311611a9b57829003601f168201915b50505050508152505090508060200151925060cc816000015181548110611ae157611ae1614643565b906000526020600020018054611af6906148b1565b80601f0160208091040260200160405190810160405280929190818152602001828054611b22906148b1565b8015611b6f5780601f10611b4457610100808354040283529160200191611b6f565b820191906000526020600020905b815481529060010190602001808311611b5257829003601f168201915b5050505050915050915091565b606060cc8281548110611b9157611b91614643565b906000526020600020018054611ba6906148b1565b80601f0160208091040260200160405190810160405280929190818152602001828054611bd2906148b1565b8015611c1f5780601f10611bf457610100808354040283529160200191611c1f565b820191906000526020600020905b815481529060010190602001808311611c0257829003601f168201915b50505050509050919050565b600080611c3784612a27565b9050600080611c468386612361565b91509150611c538261225a565b60ca546040517fa9dcf22d0000000000000000000000000000000000000000000000000000000081526001600160a01b039091169063a9dcf22d90611c9c908990600401613f76565b602060405180830381865afa158015611cb9573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611cdd91906144be565b159350836106a0577f9b0db5e74572fe0188dcef5afafe498161864c5706c3003c98ee506ae5c0282d86866040516106079291906143a7565b600080611d22846121c2565b9050600080611d3183866121db565b91509150611d3e8261225a565b6000611d4989612a27565b9050611d57848b838b612a35565b60ca546040517fa9dcf22d0000000000000000000000000000000000000000000000000000000081526001600160a01b039091169063a9dcf22d90611da0908c90600401613f76565b602060405180830381865afa158015611dbd573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611de191906144be565b945084611eb6577f802f82273c009c05274153f0f1bde4e9e06244157a2914d4b84d266a3fa82ff18a8a8989604051611e1d949392919061476e565b60405180910390a160c95460208401516040517f2853a0e600000000000000000000000000000000000000000000000000000000815263ffffffff90911660048201526001600160a01b03848116602483015233604483015290911690632853a0e690606401600060405180830381600087803b158015611e9d57600080fd5b505af1158015611eb1573d6000803e3d6000fd5b505050505b5050505095945050505050565b611ecb612882565b606580546001600160a01b0383167fffffffffffffffffffffffff00000000000000000000000000000000000000009091168117909155611f146033546001600160a01b031690565b6001600160a01b03167f38d16b8cac22d99fc7c124b9cd0de2d3fa1faef420bfe791d8c362d765e2270060405160405180910390a350565b600054610100900460ff1615808015611f6c5750600054600160ff909116105b80611f865750303b158015611f86575060005460ff166001145b612012576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a65640000000000000000000000000000000000006064820152608401610fe1565b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001179055801561207057600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff166101001790555b61207b858585612af7565b60fb80547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b038416179055801561211157600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b5050505050565b600061212346612128565b905090565b600063ffffffff8211156121be576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f53616665436173743a2076616c756520646f65736e27742066697420696e203360448201527f32206269747300000000000000000000000000000000000000000000000000006064820152608401610fe1565b5090565b60006121d56121d083612bf0565b612c03565b92915050565b604080516060810182526000808252602082018190529181018290529061220a61220485612c44565b84612c72565b6020820151919350915063ffffffff16600003612253576040517fa998e1ca00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b9250929050565b60018151600581111561226f5761226f6148fe565b14158015612290575060028151600581111561228d5761228d6148fe565b14155b15610ff3576040517fec3d0d8500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60006121d56122d583612bf0565b612d64565b600082816122ea600c603261495c565b6122f4908561496f565b90506fffffffffffffffffffffffffffffffff82168110612341576040517f1390f2a100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610f3661235c82612354600c603261495c565b859190612da5565b612e16565b604080516060810182526000808252602082018190529181018290529061238a61220485612e57565b6020820151919350915063ffffffff1615612253576040517f70488f8b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6001815160058111156123e6576123e66148fe565b14610ff3576040517f486fcee200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b7f000000000000000000000000000000000000000000000000000000000000000063ffffffff168163ffffffff16141580156124a557507f000000000000000000000000000000000000000000000000000000000000000063ffffffff167f000000000000000000000000000000000000000000000000000000000000000063ffffffff1614155b15610ff3576040517f1612d2ee00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60006121d5816020845b9190612e83565b6000806124f983612f6f565b905060008167ffffffffffffffff81111561251657612516613c1b565b60405190808252806020026020018201604052801561253f578160200160208202803683370190505b50905060005b8281101561258c5761255f61255a86836122da565b612f99565b82828151811061257157612571614643565b602090810291909101015261258581614986565b9050612545565b506125a28161259d600160066149a0565b612fd8565b806000815181106125b5576125b5614643565b602002602001015192505050919050565b604051806125d783602083016130cb565b506fffffffffffffffffffffffffffffffff83166000601f8201601f19168301602001604052509052919050565b600061261082612750565b604080518082019091528181526020810185815260cd8054600181018255600091909152825160029091027f83978b4c69c48dd978ab43fe30f077615294f938fb7f936d9eb340e51ea7db2e8101918255915193945091927f83978b4c69c48dd978ab43fe30f077615294f938fb7f936d9eb340e51ea7db2f9091019061269790826149f9565b505050505050565b604080516060810182526000808252602082018190529181018290529061238a6122048561317b565b60408051606081018252600080825260208201819052918101829052906126f76126f1866131a7565b85612c72565b90925090508280156127115750602082015163ffffffff16155b15612748576040517fa998e1ca00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b935093915050565b60cc80546001810182556000919091527f47197230e1e4b29fc0bd84d7d78966c0925452aff72a2a121538b102457e9ebe810161278d83826149f9565b50919050565b606060006127a083612f6f565b90508067ffffffffffffffff8111156127bb576127bb613c1b565b6040519080825280602002602001820160405280156127e4578160200160208202803683370190505b50915060005b8181101561287b5760006127fe85836122da565b905061283761280c826131d3565b612815836131e5565b63ffffffff1660209190911b6fffffffffffffffffffffffff00000000161790565b84838151811061284957612849614643565b6fffffffffffffffffffffffffffffffff909216602092830291909101909101525061287481614986565b90506127ea565b5050919050565b6033546001600160a01b03163314610f47576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610fe1565b606580547fffffffffffffffffffffffff0000000000000000000000000000000000000000169055610ff3816131f4565b60006121d561293583612bf0565b61325e565b604080516060810182526000808252602082018190529181018290529061238a6122048561329f565b604080516060810182526000808252602082018190529181018290529061220a612204856132cb565b60006121d560286020846124e6565b60006121d58260496132f7565b60006121d5600480845b9190613301565b60006121d560086020846124e6565b6000839050846129f0846129eb6129e58560009081526020902090565b86613322565b613322565b14612111576040517fd681cbdc00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60006121d561235c83612bf0565b6000612a408361336e565b9150508082600081518110612a5757612a57614643565b602002602001015114612a96576040517fe6ef47cc00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000612ab4612aa4856124dc565b612aad866131e5565b858861339d565b905080612ac0876124dc565b14612697576040517f2546f9ea00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600054610100900460ff16612b8e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401610fe1565b60c980546001600160a01b038086167fffffffffffffffffffffffff00000000000000000000000000000000000000009283161790925560ca805485841690831617905560cb805492841692909116919091179055612beb6133fd565b505050565b805160009060208301610a01818361349c565b6000612c0e826134ff565b6121be576040517feb92662c00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60006121d57f3464bf887f210604c594030208052a323ac6628785466262d752417691201641835b9061351e565b60408051606081018252600080825260208201819052918101919091527f19457468657265756d205369676e6564204d6573736167653a0a3332000000006000908152601c849052603c8120612cc8818561355b565b60c9546040517f28f3fac90000000000000000000000000000000000000000000000000000000081526001600160a01b0380841660048301529294509116906328f3fac990602401606060405180830381865afa158015612d2d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612d5191906147fb565b9250612d5c8361357f565b509250929050565b6000612d6f826135cb565b6121be576040517fb963c35a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600080612db28560801c90565b9050612dbd85613621565b83612dc8868461495c565b612dd2919061495c565b1115612e0a576040517fa3b99ded00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610f368482018461349c565b6000612e2182613647565b6121be576040517f6ba041c400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60006121d57f43713cd927f8eb63b519f3b180bd5f3708ebbe93666be9ba4b9624b7bc57e66383612c6c565b600081600003612e955750600061145e565b6020821115612ed0576040517f31d784a800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6fffffffffffffffffffffffffffffffff8416612eed838561495c565b1115612f25576040517fa3b99ded00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600382901b6000612f368660801c90565b909401517f8000000000000000000000000000000000000000000000000000000000000000600019929092019190911d16949350505050565b6000612f7d600c603261495c565b6121d5906fffffffffffffffffffffffffffffffff8416614ab9565b6000806000612fa78461336e565b6040805160208082019490945280820192909252805180830382018152606090920190528051910120949350505050565b81516001821b811115613017576040517fc5360feb00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60005b828110156130c55760005b828110156130b6576000816001019050600086838151811061304957613049614643565b60200260200101519050600085831061306357600061307e565b87838151811061307557613075614643565b60200260200101515b905061308a8282613322565b88600186901c815181106130a0576130a0614643565b6020908102919091010152505050600201613025565b506001918201821c910161301a565b50505050565b6040516000906fffffffffffffffffffffffffffffffff841690608085901c9080851015613125576040517f4b2a158c00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008386858560045afa905080613168576040517f7c7d772f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b608086901b84175b979650505050505050565b60006121d57fccfadb9c399e4e4257b6d0c3f92e1f9a9c00b1802b55a2f7d511702faa76909083612c6c565b60006121d57ff304ae6578b1582b0b5b512e0a7070d6f76973b1f360f99dd500082d3bc9487783612c6c565b60006121d56110896032600c856129b2565b60006121d560206004846129b2565b603380546001600160a01b038381167fffffffffffffffffffffffff0000000000000000000000000000000000000000831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b60006132698261366d565b6121be576040517f76b4e13c00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60006121d57fdf42b2c0137811ba604f5c79e20c4d6b94770aa819cc524eca444056544f8ab783612c6c565b60006121d57fb38669e8ca41a27fcd85729b868e8ab047d0f142073a017213e58f0a91e88ef383612c6c565b600061145e838360145b60008061330f858585612e83565b602084900360031b1c9150509392505050565b600082158015613330575081155b1561333d575060006121d5565b60408051602081018590529081018390526060016040516020818303038152906040528051906020012090506121d5565b60008082613385613380826024613689565b613696565b92506133956133808260246136c1565b915050915091565b60006101fe600183901b16604081106133e2576040517f1390f2a100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60006133ee8787613727565b9050613170828287600661376a565b600054610100900460ff16613494576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401610fe1565b610f47613812565b6000806134a9838561495c565b90506040518111156134b9575060005b806000036134f3576040517f10bef38600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b608084901b8317610a01565b6000604e6fffffffffffffffffffffffffffffffff83165b1492915050565b60008161352a84613696565b6040805160208101939093528201526060015b60405160208183030381529060405280519060200120905092915050565b600080600061356a85856138b2565b91509150613577816138f4565b509392505050565b600081516005811115613594576135946148fe565b03610ff3576040517fdc449cb700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60006fffffffffffffffffffffffffffffffff8216816135ed600c603261495c565b6135f79083614ab9565b905081613606600c603261495c565b613610908361496f565b148015610a015750610a0181613aa7565b60006fffffffffffffffffffffffffffffffff82166136408360801c90565b0192915050565b6000613655600c603261495c565b6fffffffffffffffffffffffffffffffff8316613517565b600060856fffffffffffffffffffffffffffffffff8316613517565b600061145e838284612da5565b6000806136a38360801c90565b6fffffffffffffffffffffffffffffffff9390931690922092915050565b60006fffffffffffffffffffffffffffffffff831680831115613710576040517fa3b99ded00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610a018361371e8660801c90565b0184830361349c565b6000828260405160200161353d92919091825260e01b7fffffffff0000000000000000000000000000000000000000000000000000000016602082015260240190565b8151600090828111156137a9576040517fc5360feb00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b84915060005b818110156137e6576137dc838683815181106137cd576137cd614643565b60200260200101518984613acc565b92506001016137af565b50805b83811015613808576137fe8360008984613acc565b92506001016137e9565b5050949350505050565b600054610100900460ff166138a9576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401610fe1565b610f47336128f6565b60008082516041036138e85760208301516040840151606085015160001a6138dc87828585613af5565b94509450505050612253565b50600090506002612253565b6000816004811115613908576139086148fe565b036139105750565b6001816004811115613924576139246148fe565b0361398b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f45434453413a20696e76616c6964207369676e617475726500000000000000006044820152606401610fe1565b600281600481111561399f5761399f6148fe565b03613a06576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f45434453413a20696e76616c6964207369676e6174757265206c656e677468006044820152606401610fe1565b6003816004811115613a1a57613a1a6148fe565b03610ff3576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602260248201527f45434453413a20696e76616c6964207369676e6174757265202773272076616c60448201527f75650000000000000000000000000000000000000000000000000000000000006064820152608401610fe1565b600081158015906121d55750613abf600160066149a0565b6001901b82111592915050565b6000600183831c168103613aeb57613ae48585613322565b9050610a01565b613ae48486613322565b6000807f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a0831115613b2c5750600090506003613bb0565b6040805160008082526020820180845289905260ff881692820192909252606081018690526080810185905260019060a0016020604051602081039080840390855afa158015613b80573d6000803e3d6000fd5b5050604051601f1901519150506001600160a01b038116613ba957600060019250925050613bb0565b9150600090505b94509492505050565b6040805160e0810190915260006080820181815260a0830182905260c0830191909152819081526000602082018190526040820152606001613c166040805160608101909152806000815260006020820181905260409091015290565b905290565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b604051601f8201601f1916810167ffffffffffffffff81118282101715613c7357613c73613c1b565b604052919050565b600067ffffffffffffffff821115613c9557613c95613c1b565b50601f01601f191660200190565b600082601f830112613cb457600080fd5b8135613cc7613cc282613c7b565b613c4a565b818152846020838601011115613cdc57600080fd5b816020850160208301376000918101602001919091529392505050565b60008060408385031215613d0c57600080fd5b823567ffffffffffffffff80821115613d2457600080fd5b613d3086838701613ca3565b93506020850135915080821115613d4657600080fd5b50613d5385828601613ca3565b9150509250929050565b803560ff81168114613d6e57600080fd5b919050565b600080600080600060a08688031215613d8b57600080fd5b613d9486613d5d565b9450602086013567ffffffffffffffff80821115613db157600080fd5b613dbd89838a01613ca3565b95506040880135915080821115613dd357600080fd5b613ddf89838a01613ca3565b94506060880135915080821115613df557600080fd5b613e0189838a01613ca3565b93506080880135915080821115613e1757600080fd5b50613e2488828901613ca3565b9150509295509295909350565b60008060008060808587031215613e4757600080fd5b613e5085613d5d565b9350602085013567ffffffffffffffff80821115613e6d57600080fd5b613e7988838901613ca3565b94506040870135915080821115613e8f57600080fd5b613e9b88838901613ca3565b93506060870135915080821115613eb157600080fd5b50613ebe87828801613ca3565b91505092959194509250565b60005b83811015613ee5578181015183820152602001613ecd565b50506000910152565b60008151808452613f06816020860160208601613eca565b601f01601f19169290920160200192915050565b606081526000613f2d6060830186613eee565b6020838101869052838203604085015284518083528582019282019060005b81811015613f6857845183529383019391830191600101613f4c565b509098975050505050505050565b60208152600061145e6020830184613eee565b60008060208385031215613f9c57600080fd5b823567ffffffffffffffff80821115613fb457600080fd5b818501915085601f830112613fc857600080fd5b813581811115613fd757600080fd5b8660208260051b8501011115613fec57600080fd5b60209290920196919550909350505050565b60006020808301818452808551808352604092508286019150828160051b87010184880160005b83811015613f68578883037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc0018552815180511515845287015187840187905261407187850182613eee565b9588019593505090860190600101614025565b63ffffffff81168114610ff357600080fd5b600080600080608085870312156140ac57600080fd5b84356140b781614084565b935060208501356140c781614084565b925060408501359150606085013567ffffffffffffffff8111156140ea57600080fd5b613ebe87828801613ca3565b60008060006060848603121561410b57600080fd5b61411484613d5d565b9250602084013567ffffffffffffffff8082111561413157600080fd5b61413d87838801613ca3565b9350604086013591508082111561415357600080fd5b5061416086828701613ca3565b9150509250925092565b60008060006060848603121561417f57600080fd5b833567ffffffffffffffff8082111561419757600080fd5b6141a387838801613ca3565b9450602086013591508082111561413157600080fd5b600080600080600060a086880312156141d157600080fd5b853567ffffffffffffffff808211156141e957600080fd5b6141f589838a01613ca3565b9650602088013591508082111561420b57600080fd5b5061421888828901613ca3565b959895975050505060408401359360608101359360809091013592509050565b600082601f83011261424957600080fd5b8135602067ffffffffffffffff82111561426557614265613c1b565b8160051b614274828201613c4a565b928352848101820192828101908785111561428e57600080fd5b83870192505b8483101561317057823582529183019190830190614294565b60008060008060008060c087890312156142c657600080fd5b6142cf87613d5d565b9550602087013567ffffffffffffffff808211156142ec57600080fd5b6142f88a838b01613ca3565b9650604089013591508082111561430e57600080fd5b61431a8a838b01613ca3565b9550606089013591508082111561433057600080fd5b61433c8a838b01614238565b9450608089013591508082111561435257600080fd5b61435e8a838b01613ca3565b935060a089013591508082111561437457600080fd5b5061438189828a01613ca3565b9150509295509295509295565b6000602082840312156143a057600080fd5b5035919050565b6040815260006143ba6040830185613eee565b8281036020840152610f368185613eee565b600080600080600060a086880312156143e457600080fd5b6143ed86613d5d565b9450602086013567ffffffffffffffff8082111561440a57600080fd5b61441689838a01613ca3565b9550604088013591508082111561442c57600080fd5b613ddf89838a01614238565b80356001600160a01b0381168114613d6e57600080fd5b60006020828403121561446157600080fd5b61145e82614438565b6000806000806080858703121561448057600080fd5b61448985614438565b935061449760208601614438565b92506144a560408601614438565b91506144b360608601614438565b905092959194509250565b6000602082840312156144d057600080fd5b8151801515811461145e57600080fd5b63ffffffff84168152826020820152606060408201526000610f366060830184613eee565b60006020828403121561451757600080fd5b5051919050565b63ffffffff851681528360208201528260408201526080606082015260006145496080830184613eee565b9695505050505050565b60006020828403121561456557600080fd5b815167ffffffffffffffff81111561457c57600080fd5b8201601f8101841361458d57600080fd5b805161459b613cc282613c7b565b8181528560208385010111156145b057600080fd5b610f36826020830160208601613eca565b63ffffffff8616815260006020868184015260a060408401526145e760a0840187613eee565b60608401869052838103608085015284518082528286019183019060005b818110156146335783516fffffffffffffffffffffffffffffffff1683529284019291840191600101614605565b50909a9950505050505050505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b600082357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc18336030181126146a657600080fd5b9190910192915050565b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe18436030181126146e557600080fd5b83018035915067ffffffffffffffff82111561470057600080fd5b60200191503681900382131561225357600080fd5b8183823760009101908152919050565b600063ffffffff8089168352808816602084015286604084015280861660608401525083608083015260c060a083015261476260c0830184613eee565b98975050505050505050565b60ff8516815260806020820152600061478a6080830186613eee565b828103604084015261479c8186613eee565b905082810360608401526131708185613eee565b60ff841681526060602082015260006147cc6060830185613eee565b82810360408401526145498185613eee565b6000602082840312156147f057600080fd5b815161145e81614084565b60006060828403121561480d57600080fd5b6040516060810181811067ffffffffffffffff8211171561483057614830613c1b565b60405282516006811061484257600080fd5b8152602083015161485281614084565b6020820152604083015161486581614084565b60408201529392505050565b63ffffffff851681526001600160a01b038416602082015260806040820152600061489f6080830185613eee565b82810360608401526131708185613eee565b600181811c908216806148c557607f821691505b60208210810361278d577f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b808201808211156121d5576121d561492d565b80820281158282048414176121d5576121d561492d565b600060001982036149995761499961492d565b5060010190565b818103818111156121d5576121d561492d565b601f821115612beb57600081815260208120601f850160051c810160208610156149da5750805b601f850160051c820191505b81811015612697578281556001016149e6565b815167ffffffffffffffff811115614a1357614a13613c1b565b614a2781614a2184546148b1565b846149b3565b602080601f831160018114614a5c5760008415614a445750858301515b600019600386901b1c1916600185901b178555612697565b600085815260208120601f198616915b82811015614a8b57888601518255948401946001909101908401614a6c565b5085821015614aa95787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b600082614aef577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b50049056fea26469706673582212209750e141609e1affd8326f71c1584e563dbf2844350223eab568a94af45ce12764736f6c63430008110033","runtime-code":"0x608060405234801561001057600080fd5b50600436106101f05760003560e01c80638d3638f41161010f578063c25aa585116100a2578063e3097af811610071578063e3097af8146104d3578063e30c3978146104e6578063f2fde38b146104f7578063f8c8765e1461050a57600080fd5b8063c25aa58514610479578063c495912b1461048c578063ddeffa66146104ad578063dfe39675146104c057600080fd5b80639fbcb9cb116100de5780639fbcb9cb1461042d578063b269681d14610440578063b2a4b45514610453578063be7e63da1461046657600080fd5b80638d3638f4146103cf5780638da5cb5b146103f657806391af2e5d14610407578063938b5f321461041a57600080fd5b8063715018a61161018757806379ba50971161015657806379ba50971461038e5780637d9978ae146103965780638671012e146103a957806389246503146103bc57600080fd5b8063715018a61461030c578063717b863814610316578063756ed01d146103525780637622f78d1461036357600080fd5b80634bb73ea5116101c35780634bb73ea51461025657806354fd4d501461027857806360fc8466146102d95780636b47b3bc146102f957600080fd5b80630ca77473146101f5578063243b92241461021d57806331e8df5a14610230578063333138e214610243575b600080fd5b610208610203366004613cf9565b61051d565b60405190151581526020015b60405180910390f35b61020861022b366004613d73565b6106a9565b61020861023e366004613cf9565b610810565b610208610251366004613e31565b6108fb565b610269610264366004613cf9565b610a09565b60405161021493929190613f1a565b604080518082019091527f000000000000000000000000000000000000000000000000000000000000000081527f000000000000000000000000000000000000000000000000000000000000000060208201525b6040516102149190613f76565b6102ec6102e7366004613f89565b610cf5565b6040516102149190613ffe565b610208610307366004614096565b610e57565b610314610f3f565b005b61033d7f000000000000000000000000000000000000000000000000000000000000000081565b60405163ffffffff9091168152602001610214565b60cd54604051908152602001610214565b60c954610376906001600160a01b031681565b6040516001600160a01b039091168152602001610214565b610314610f49565b6102086103a4366004613e31565b610ff6565b6102086103b73660046140f6565b6111f9565b6102086103ca36600461416a565b611381565b61033d7f000000000000000000000000000000000000000000000000000000000000000081565b6033546001600160a01b0316610376565b610208610415366004613cf9565b611465565b60ca54610376906001600160a01b031681565b60fb54610376906001600160a01b031681565b60cb54610376906001600160a01b031681565b6102086104613660046141b9565b611550565b6102086104743660046142ad565b61185f565b610208610487366004613cf9565b6118cd565b61049f61049a36600461438e565b6119b7565b6040516102149291906143a7565b6102cc6104bb36600461438e565b611b7c565b6102086104ce366004613cf9565b611c2b565b6102086104e13660046143cc565b611d16565b6065546001600160a01b0316610376565b61031461050536600461444f565b611ec3565b61031461051836600461446a565b611f4c565b600080610529846121c2565b905060008061053883866121db565b915091506105458261225a565b60fb546040517f4362fd110000000000000000000000000000000000000000000000000000000081526001600160a01b0390911690634362fd119061058e908990600401613f76565b602060405180830381865afa1580156105ab573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105cf91906144be565b9350836106a0577f5ce497fe75d0d52e5ee139d2cd651d0ff00692a94d7052cb37faef5592d74b2b86866040516106079291906143a7565b60405180910390a160c95460208301516040517f2853a0e600000000000000000000000000000000000000000000000000000000815263ffffffff90911660048201526001600160a01b03838116602483015233604483015290911690632853a0e690606401600060405180830381600087803b15801561068757600080fd5b505af115801561069b573d6000803e3d6000fd5b505050505b50505092915050565b6000806106b5856122c7565b905060006106c68260ff8a166122da565b905060006106d48289612361565b5090506106e0816123d1565b60006106eb876121c2565b905060006106f982886121db565b5090506107058161225a565b610712816020015161241d565b61071b826124dc565b610724866124ed565b1461075b576040517f2546f9ea00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61077261076c856125c6565b6125c6565b8b612605565b60c9546040848101518382015191517fa2155c3400000000000000000000000000000000000000000000000000000000815263ffffffff9182166004820152911660248201526001600160a01b039091169063a2155c3490604401600060405180830381600087803b1580156107e757600080fd5b505af11580156107fb573d6000803e3d6000fd5b5060019e9d5050505050505050505050505050565b60008061081c846121c2565b905060008061082b838661269f565b915091506108388261225a565b60fb546040517f4362fd110000000000000000000000000000000000000000000000000000000081526001600160a01b0390911690634362fd1190610881908990600401613f76565b602060405180830381865afa15801561089e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108c291906144be565b159350836106a0577f6f83f9b71f5c687c7dd205d520001d4e5adc1f16e4e2ee5b798c720d643e5a9e86866040516106079291906143a7565b600080610907846122c7565b90506000610917828560016126c8565b5090506109238161225a565b610930816020015161241d565b600061093f8360ff8a166122da565b9050600061094d8289612361565b509050610959816123d1565b61096b610965836125c6565b89612605565b60c9546040828101518582015191517fa2155c3400000000000000000000000000000000000000000000000000000000815263ffffffff9182166004820152911660248201526001600160a01b039091169063a2155c3490604401600060405180830381600087803b1580156109e057600080fd5b505af11580156109f4573d6000803e3d6000fd5b5050505060019450505050505b949350505050565b6060600060606000610a1a866122c7565b9050600080610a2b838860006126c8565b91509150610a38826123d1565b6000610a4388612750565b9050826020015163ffffffff16600003610ade5760fb5460408085015190517f9cc1bb310000000000000000000000000000000000000000000000000000000081526001600160a01b0390921691639cc1bb3191610aa79185908e906004016144e0565b600060405180830381600087803b158015610ac157600080fd5b505af1158015610ad5573d6000803e3d6000fd5b50505050610c9c565b60c960009054906101000a90046001600160a01b03166001600160a01b03166336cba43c6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610b31573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b559190614505565b60fb5460408086015190517ef340540000000000000000000000000000000000000000000000000000000081529298506001600160a01b039091169162f3405491610ba89185908b908f9060040161451e565b6000604051808303816000875af1158015610bc7573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052610bef9190810190614553565b96506000610bfc85612793565b60cb5460408087015190517f39fe27360000000000000000000000000000000000000000000000000000000081529293506001600160a01b03909116916339fe273691610c5591600019908d908d9088906004016145c1565b6020604051808303816000875af1158015610c74573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c9891906144be565b5094505b816001600160a01b0316836020015163ffffffff167f5ca3d740e03650b41813a4b418830f6ba39700ae010fe8c4d1bca0e8676b9c568b8b604051610ce29291906143a7565b60405180910390a3505050509250925092565b6060818067ffffffffffffffff811115610d1157610d11613c1b565b604051908082528060200260200182016040528015610d5757816020015b604080518082019091526000815260606020820152815260200190600190039081610d2f5790505b5091503660005b828110156106a057858582818110610d7857610d78614643565b9050602002810190610d8a9190614672565b91506000848281518110610da057610da0614643565b60200260200101519050306001600160a01b0316838060200190610dc491906146b0565b604051610dd2929190614715565b600060405180830381855af49150503d8060008114610e0d576040519150601f19603f3d011682016040523d82523d6000602084013e610e12565b606091505b5060208301521515808252833517610e4e577f4d6a23280000000000000000000000000000000000000000000000000000000060005260046000fd5b50600101610d5e565b60cb546000906001600160a01b03163314610e9e576040517f6efcc49f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60fb546040517fc79a431b0000000000000000000000000000000000000000000000000000000081526001600160a01b039091169063c79a431b90610ef39088908190600019908a908a908a90600401614725565b6020604051808303816000875af1158015610f12573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f3691906144be565b95945050505050565b610f47612882565b565b60655433906001600160a01b03168114610fea576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602960248201527f4f776e61626c6532537465703a2063616c6c6572206973206e6f74207468652060448201527f6e6577206f776e6572000000000000000000000000000000000000000000000060648201526084015b60405180910390fd5b610ff3816128f6565b50565b600080611002846121c2565b905060008061101183866121db565b9150915061101e8261225a565b6000611029886122c7565b9050611034846124dc565b61103d826124ed565b14611074576040517f2546f9ea00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600061108c6107676110898460ff8e166122da565b90565b60ca546040517fa9dcf22d0000000000000000000000000000000000000000000000000000000081529192506001600160a01b03169063a9dcf22d906110d6908490600401613f76565b602060405180830381865afa1580156110f3573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061111791906144be565b9550856111ec577f802f82273c009c05274153f0f1bde4e9e06244157a2914d4b84d266a3fa82ff18a828a8a604051611153949392919061476e565b60405180910390a160c95460208501516040517f2853a0e600000000000000000000000000000000000000000000000000000000815263ffffffff90911660048201526001600160a01b03858116602483015233604483015290911690632853a0e690606401600060405180830381600087803b1580156111d357600080fd5b505af11580156111e7573d6000803e3d6000fd5b505050505b5050505050949350505050565b600080611205846122c7565b9050600080611216838660006126c8565b915091506112238261225a565b60ca546001600160a01b031663a9dcf22d6112476107676110898760ff8d166122da565b6040518263ffffffff1660e01b81526004016112639190613f76565b602060405180830381865afa158015611280573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906112a491906144be565b935083611377577ff649e0d8f524df47b57dbcc2cda237f72096391dff21abc122acebd5112f4de08787876040516112de939291906147b0565b60405180910390a160c95460208301516040517f2853a0e600000000000000000000000000000000000000000000000000000000815263ffffffff90911660048201526001600160a01b03838116602483015233604483015290911690632853a0e690606401600060405180830381600087803b15801561135e57600080fd5b505af1158015611372573d6000803e3d6000fd5b505050505b5050509392505050565b60008061138d85612927565b9050600061139b828561293a565b5090506113a7816123d1565b60006113b38387612963565b5090506113bf8161225a565b6113c98786612605565b60c9546040838101518382015191517fa2155c3400000000000000000000000000000000000000000000000000000000815263ffffffff9182166004820152911660248201526001600160a01b039091169063a2155c3490604401600060405180830381600087803b15801561143e57600080fd5b505af1158015611452573d6000803e3d6000fd5b50505050600193505050505b9392505050565b60008061147184612927565b9050600080611480838661293a565b9150915061148d8261225a565b60cb546040517fe2f006f70000000000000000000000000000000000000000000000000000000081526001600160a01b039091169063e2f006f7906114d6908990600401613f76565b602060405180830381865afa1580156114f3573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061151791906144be565b159350836106a0577fa0cb383b7028fbeae86e018eb9fe765c15c869483a584edbb95bf5509344658786866040516106079291906143a7565b600061155a613bb9565b600061156588612927565b90506115718188612963565b6001600160a01b0316602084015280835261158b906123d1565b60cb546001600160a01b0316634f1275676115a58361298c565b6040518263ffffffff1660e01b81526004016115c391815260200190565b602060405180830381865afa1580156115e0573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061160491906147de565b63ffffffff166040830181905260000361164a576040517f2546f9ea00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60c9546001600160a01b03166328f3fac96116648361299b565b6040517fffffffff0000000000000000000000000000000000000000000000000000000060e084901b1681526001600160a01b039091166004820152602401606060405180830381865afa1580156116c0573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906116e491906147fb565b60608301526116f2816129a8565b63ffffffff1682606001516020015163ffffffff161461173e576040517f1612d2ee00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61175261174a826129b9565b8787876129c8565b600061175d88612750565b905060fb60009054906101000a90046001600160a01b03166001600160a01b031663c79a431b8460000151604001518560600151604001518487604001518c8f6040518763ffffffff1660e01b81526004016117be96959493929190614725565b6020604051808303816000875af11580156117dd573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061180191906144be565b93508315611853577f9377955fede38ca63bc09f7b3fae7dd349934c78c058963a6d3c05d4eed0411283600001516020015184602001518b8b60405161184a9493929190614871565b60405180910390a15b50505095945050505050565b60008061186b87612a27565b905060006118798288612361565b509050611885816123d1565b6000611890866121c2565b9050600061189e82876121db565b5090506118aa8161225a565b6118b7816020015161241d565b6118c3828c868b612a35565b6107728a8a612605565b6000806118d984612927565b90506000806118e88386612963565b915091506118f58261225a565b60cb546040517fe2f006f70000000000000000000000000000000000000000000000000000000081526001600160a01b039091169063e2f006f79061193e908990600401613f76565b602060405180830381865afa15801561195b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061197f91906144be565b9350836106a0577f4d4c3a87f0d5fbcea3c51d5baa727fceedb200dd7c9287f7ef85b60b794d6a8d86866040516106079291906143a7565b60cd54606090819083106119f7576040517f1390f2a100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600060cd8481548110611a0c57611a0c614643565b906000526020600020906002020160405180604001604052908160008201548152602001600182018054611a3f906148b1565b80601f0160208091040260200160405190810160405280929190818152602001828054611a6b906148b1565b8015611ab85780601f10611a8d57610100808354040283529160200191611ab8565b820191906000526020600020905b815481529060010190602001808311611a9b57829003601f168201915b50505050508152505090508060200151925060cc816000015181548110611ae157611ae1614643565b906000526020600020018054611af6906148b1565b80601f0160208091040260200160405190810160405280929190818152602001828054611b22906148b1565b8015611b6f5780601f10611b4457610100808354040283529160200191611b6f565b820191906000526020600020905b815481529060010190602001808311611b5257829003601f168201915b5050505050915050915091565b606060cc8281548110611b9157611b91614643565b906000526020600020018054611ba6906148b1565b80601f0160208091040260200160405190810160405280929190818152602001828054611bd2906148b1565b8015611c1f5780601f10611bf457610100808354040283529160200191611c1f565b820191906000526020600020905b815481529060010190602001808311611c0257829003601f168201915b50505050509050919050565b600080611c3784612a27565b9050600080611c468386612361565b91509150611c538261225a565b60ca546040517fa9dcf22d0000000000000000000000000000000000000000000000000000000081526001600160a01b039091169063a9dcf22d90611c9c908990600401613f76565b602060405180830381865afa158015611cb9573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611cdd91906144be565b159350836106a0577f9b0db5e74572fe0188dcef5afafe498161864c5706c3003c98ee506ae5c0282d86866040516106079291906143a7565b600080611d22846121c2565b9050600080611d3183866121db565b91509150611d3e8261225a565b6000611d4989612a27565b9050611d57848b838b612a35565b60ca546040517fa9dcf22d0000000000000000000000000000000000000000000000000000000081526001600160a01b039091169063a9dcf22d90611da0908c90600401613f76565b602060405180830381865afa158015611dbd573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611de191906144be565b945084611eb6577f802f82273c009c05274153f0f1bde4e9e06244157a2914d4b84d266a3fa82ff18a8a8989604051611e1d949392919061476e565b60405180910390a160c95460208401516040517f2853a0e600000000000000000000000000000000000000000000000000000000815263ffffffff90911660048201526001600160a01b03848116602483015233604483015290911690632853a0e690606401600060405180830381600087803b158015611e9d57600080fd5b505af1158015611eb1573d6000803e3d6000fd5b505050505b5050505095945050505050565b611ecb612882565b606580546001600160a01b0383167fffffffffffffffffffffffff00000000000000000000000000000000000000009091168117909155611f146033546001600160a01b031690565b6001600160a01b03167f38d16b8cac22d99fc7c124b9cd0de2d3fa1faef420bfe791d8c362d765e2270060405160405180910390a350565b600054610100900460ff1615808015611f6c5750600054600160ff909116105b80611f865750303b158015611f86575060005460ff166001145b612012576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a65640000000000000000000000000000000000006064820152608401610fe1565b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001179055801561207057600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff166101001790555b61207b858585612af7565b60fb80547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b038416179055801561211157600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b5050505050565b600061212346612128565b905090565b600063ffffffff8211156121be576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f53616665436173743a2076616c756520646f65736e27742066697420696e203360448201527f32206269747300000000000000000000000000000000000000000000000000006064820152608401610fe1565b5090565b60006121d56121d083612bf0565b612c03565b92915050565b604080516060810182526000808252602082018190529181018290529061220a61220485612c44565b84612c72565b6020820151919350915063ffffffff16600003612253576040517fa998e1ca00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b9250929050565b60018151600581111561226f5761226f6148fe565b14158015612290575060028151600581111561228d5761228d6148fe565b14155b15610ff3576040517fec3d0d8500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60006121d56122d583612bf0565b612d64565b600082816122ea600c603261495c565b6122f4908561496f565b90506fffffffffffffffffffffffffffffffff82168110612341576040517f1390f2a100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610f3661235c82612354600c603261495c565b859190612da5565b612e16565b604080516060810182526000808252602082018190529181018290529061238a61220485612e57565b6020820151919350915063ffffffff1615612253576040517f70488f8b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6001815160058111156123e6576123e66148fe565b14610ff3576040517f486fcee200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b7f000000000000000000000000000000000000000000000000000000000000000063ffffffff168163ffffffff16141580156124a557507f000000000000000000000000000000000000000000000000000000000000000063ffffffff167f000000000000000000000000000000000000000000000000000000000000000063ffffffff1614155b15610ff3576040517f1612d2ee00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60006121d5816020845b9190612e83565b6000806124f983612f6f565b905060008167ffffffffffffffff81111561251657612516613c1b565b60405190808252806020026020018201604052801561253f578160200160208202803683370190505b50905060005b8281101561258c5761255f61255a86836122da565b612f99565b82828151811061257157612571614643565b602090810291909101015261258581614986565b9050612545565b506125a28161259d600160066149a0565b612fd8565b806000815181106125b5576125b5614643565b602002602001015192505050919050565b604051806125d783602083016130cb565b506fffffffffffffffffffffffffffffffff83166000601f8201601f19168301602001604052509052919050565b600061261082612750565b604080518082019091528181526020810185815260cd8054600181018255600091909152825160029091027f83978b4c69c48dd978ab43fe30f077615294f938fb7f936d9eb340e51ea7db2e8101918255915193945091927f83978b4c69c48dd978ab43fe30f077615294f938fb7f936d9eb340e51ea7db2f9091019061269790826149f9565b505050505050565b604080516060810182526000808252602082018190529181018290529061238a6122048561317b565b60408051606081018252600080825260208201819052918101829052906126f76126f1866131a7565b85612c72565b90925090508280156127115750602082015163ffffffff16155b15612748576040517fa998e1ca00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b935093915050565b60cc80546001810182556000919091527f47197230e1e4b29fc0bd84d7d78966c0925452aff72a2a121538b102457e9ebe810161278d83826149f9565b50919050565b606060006127a083612f6f565b90508067ffffffffffffffff8111156127bb576127bb613c1b565b6040519080825280602002602001820160405280156127e4578160200160208202803683370190505b50915060005b8181101561287b5760006127fe85836122da565b905061283761280c826131d3565b612815836131e5565b63ffffffff1660209190911b6fffffffffffffffffffffffff00000000161790565b84838151811061284957612849614643565b6fffffffffffffffffffffffffffffffff909216602092830291909101909101525061287481614986565b90506127ea565b5050919050565b6033546001600160a01b03163314610f47576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610fe1565b606580547fffffffffffffffffffffffff0000000000000000000000000000000000000000169055610ff3816131f4565b60006121d561293583612bf0565b61325e565b604080516060810182526000808252602082018190529181018290529061238a6122048561329f565b604080516060810182526000808252602082018190529181018290529061220a612204856132cb565b60006121d560286020846124e6565b60006121d58260496132f7565b60006121d5600480845b9190613301565b60006121d560086020846124e6565b6000839050846129f0846129eb6129e58560009081526020902090565b86613322565b613322565b14612111576040517fd681cbdc00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60006121d561235c83612bf0565b6000612a408361336e565b9150508082600081518110612a5757612a57614643565b602002602001015114612a96576040517fe6ef47cc00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000612ab4612aa4856124dc565b612aad866131e5565b858861339d565b905080612ac0876124dc565b14612697576040517f2546f9ea00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600054610100900460ff16612b8e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401610fe1565b60c980546001600160a01b038086167fffffffffffffffffffffffff00000000000000000000000000000000000000009283161790925560ca805485841690831617905560cb805492841692909116919091179055612beb6133fd565b505050565b805160009060208301610a01818361349c565b6000612c0e826134ff565b6121be576040517feb92662c00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60006121d57f3464bf887f210604c594030208052a323ac6628785466262d752417691201641835b9061351e565b60408051606081018252600080825260208201819052918101919091527f19457468657265756d205369676e6564204d6573736167653a0a3332000000006000908152601c849052603c8120612cc8818561355b565b60c9546040517f28f3fac90000000000000000000000000000000000000000000000000000000081526001600160a01b0380841660048301529294509116906328f3fac990602401606060405180830381865afa158015612d2d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612d5191906147fb565b9250612d5c8361357f565b509250929050565b6000612d6f826135cb565b6121be576040517fb963c35a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600080612db28560801c90565b9050612dbd85613621565b83612dc8868461495c565b612dd2919061495c565b1115612e0a576040517fa3b99ded00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610f368482018461349c565b6000612e2182613647565b6121be576040517f6ba041c400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60006121d57f43713cd927f8eb63b519f3b180bd5f3708ebbe93666be9ba4b9624b7bc57e66383612c6c565b600081600003612e955750600061145e565b6020821115612ed0576040517f31d784a800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6fffffffffffffffffffffffffffffffff8416612eed838561495c565b1115612f25576040517fa3b99ded00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600382901b6000612f368660801c90565b909401517f8000000000000000000000000000000000000000000000000000000000000000600019929092019190911d16949350505050565b6000612f7d600c603261495c565b6121d5906fffffffffffffffffffffffffffffffff8416614ab9565b6000806000612fa78461336e565b6040805160208082019490945280820192909252805180830382018152606090920190528051910120949350505050565b81516001821b811115613017576040517fc5360feb00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60005b828110156130c55760005b828110156130b6576000816001019050600086838151811061304957613049614643565b60200260200101519050600085831061306357600061307e565b87838151811061307557613075614643565b60200260200101515b905061308a8282613322565b88600186901c815181106130a0576130a0614643565b6020908102919091010152505050600201613025565b506001918201821c910161301a565b50505050565b6040516000906fffffffffffffffffffffffffffffffff841690608085901c9080851015613125576040517f4b2a158c00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008386858560045afa905080613168576040517f7c7d772f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b608086901b84175b979650505050505050565b60006121d57fccfadb9c399e4e4257b6d0c3f92e1f9a9c00b1802b55a2f7d511702faa76909083612c6c565b60006121d57ff304ae6578b1582b0b5b512e0a7070d6f76973b1f360f99dd500082d3bc9487783612c6c565b60006121d56110896032600c856129b2565b60006121d560206004846129b2565b603380546001600160a01b038381167fffffffffffffffffffffffff0000000000000000000000000000000000000000831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b60006132698261366d565b6121be576040517f76b4e13c00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60006121d57fdf42b2c0137811ba604f5c79e20c4d6b94770aa819cc524eca444056544f8ab783612c6c565b60006121d57fb38669e8ca41a27fcd85729b868e8ab047d0f142073a017213e58f0a91e88ef383612c6c565b600061145e838360145b60008061330f858585612e83565b602084900360031b1c9150509392505050565b600082158015613330575081155b1561333d575060006121d5565b60408051602081018590529081018390526060016040516020818303038152906040528051906020012090506121d5565b60008082613385613380826024613689565b613696565b92506133956133808260246136c1565b915050915091565b60006101fe600183901b16604081106133e2576040517f1390f2a100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60006133ee8787613727565b9050613170828287600661376a565b600054610100900460ff16613494576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401610fe1565b610f47613812565b6000806134a9838561495c565b90506040518111156134b9575060005b806000036134f3576040517f10bef38600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b608084901b8317610a01565b6000604e6fffffffffffffffffffffffffffffffff83165b1492915050565b60008161352a84613696565b6040805160208101939093528201526060015b60405160208183030381529060405280519060200120905092915050565b600080600061356a85856138b2565b91509150613577816138f4565b509392505050565b600081516005811115613594576135946148fe565b03610ff3576040517fdc449cb700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60006fffffffffffffffffffffffffffffffff8216816135ed600c603261495c565b6135f79083614ab9565b905081613606600c603261495c565b613610908361496f565b148015610a015750610a0181613aa7565b60006fffffffffffffffffffffffffffffffff82166136408360801c90565b0192915050565b6000613655600c603261495c565b6fffffffffffffffffffffffffffffffff8316613517565b600060856fffffffffffffffffffffffffffffffff8316613517565b600061145e838284612da5565b6000806136a38360801c90565b6fffffffffffffffffffffffffffffffff9390931690922092915050565b60006fffffffffffffffffffffffffffffffff831680831115613710576040517fa3b99ded00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610a018361371e8660801c90565b0184830361349c565b6000828260405160200161353d92919091825260e01b7fffffffff0000000000000000000000000000000000000000000000000000000016602082015260240190565b8151600090828111156137a9576040517fc5360feb00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b84915060005b818110156137e6576137dc838683815181106137cd576137cd614643565b60200260200101518984613acc565b92506001016137af565b50805b83811015613808576137fe8360008984613acc565b92506001016137e9565b5050949350505050565b600054610100900460ff166138a9576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401610fe1565b610f47336128f6565b60008082516041036138e85760208301516040840151606085015160001a6138dc87828585613af5565b94509450505050612253565b50600090506002612253565b6000816004811115613908576139086148fe565b036139105750565b6001816004811115613924576139246148fe565b0361398b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f45434453413a20696e76616c6964207369676e617475726500000000000000006044820152606401610fe1565b600281600481111561399f5761399f6148fe565b03613a06576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f45434453413a20696e76616c6964207369676e6174757265206c656e677468006044820152606401610fe1565b6003816004811115613a1a57613a1a6148fe565b03610ff3576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602260248201527f45434453413a20696e76616c6964207369676e6174757265202773272076616c60448201527f75650000000000000000000000000000000000000000000000000000000000006064820152608401610fe1565b600081158015906121d55750613abf600160066149a0565b6001901b82111592915050565b6000600183831c168103613aeb57613ae48585613322565b9050610a01565b613ae48486613322565b6000807f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a0831115613b2c5750600090506003613bb0565b6040805160008082526020820180845289905260ff881692820192909252606081018690526080810185905260019060a0016020604051602081039080840390855afa158015613b80573d6000803e3d6000fd5b5050604051601f1901519150506001600160a01b038116613ba957600060019250925050613bb0565b9150600090505b94509492505050565b6040805160e0810190915260006080820181815260a0830182905260c0830191909152819081526000602082018190526040820152606001613c166040805160608101909152806000815260006020820181905260409091015290565b905290565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b604051601f8201601f1916810167ffffffffffffffff81118282101715613c7357613c73613c1b565b604052919050565b600067ffffffffffffffff821115613c9557613c95613c1b565b50601f01601f191660200190565b600082601f830112613cb457600080fd5b8135613cc7613cc282613c7b565b613c4a565b818152846020838601011115613cdc57600080fd5b816020850160208301376000918101602001919091529392505050565b60008060408385031215613d0c57600080fd5b823567ffffffffffffffff80821115613d2457600080fd5b613d3086838701613ca3565b93506020850135915080821115613d4657600080fd5b50613d5385828601613ca3565b9150509250929050565b803560ff81168114613d6e57600080fd5b919050565b600080600080600060a08688031215613d8b57600080fd5b613d9486613d5d565b9450602086013567ffffffffffffffff80821115613db157600080fd5b613dbd89838a01613ca3565b95506040880135915080821115613dd357600080fd5b613ddf89838a01613ca3565b94506060880135915080821115613df557600080fd5b613e0189838a01613ca3565b93506080880135915080821115613e1757600080fd5b50613e2488828901613ca3565b9150509295509295909350565b60008060008060808587031215613e4757600080fd5b613e5085613d5d565b9350602085013567ffffffffffffffff80821115613e6d57600080fd5b613e7988838901613ca3565b94506040870135915080821115613e8f57600080fd5b613e9b88838901613ca3565b93506060870135915080821115613eb157600080fd5b50613ebe87828801613ca3565b91505092959194509250565b60005b83811015613ee5578181015183820152602001613ecd565b50506000910152565b60008151808452613f06816020860160208601613eca565b601f01601f19169290920160200192915050565b606081526000613f2d6060830186613eee565b6020838101869052838203604085015284518083528582019282019060005b81811015613f6857845183529383019391830191600101613f4c565b509098975050505050505050565b60208152600061145e6020830184613eee565b60008060208385031215613f9c57600080fd5b823567ffffffffffffffff80821115613fb457600080fd5b818501915085601f830112613fc857600080fd5b813581811115613fd757600080fd5b8660208260051b8501011115613fec57600080fd5b60209290920196919550909350505050565b60006020808301818452808551808352604092508286019150828160051b87010184880160005b83811015613f68578883037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc0018552815180511515845287015187840187905261407187850182613eee565b9588019593505090860190600101614025565b63ffffffff81168114610ff357600080fd5b600080600080608085870312156140ac57600080fd5b84356140b781614084565b935060208501356140c781614084565b925060408501359150606085013567ffffffffffffffff8111156140ea57600080fd5b613ebe87828801613ca3565b60008060006060848603121561410b57600080fd5b61411484613d5d565b9250602084013567ffffffffffffffff8082111561413157600080fd5b61413d87838801613ca3565b9350604086013591508082111561415357600080fd5b5061416086828701613ca3565b9150509250925092565b60008060006060848603121561417f57600080fd5b833567ffffffffffffffff8082111561419757600080fd5b6141a387838801613ca3565b9450602086013591508082111561413157600080fd5b600080600080600060a086880312156141d157600080fd5b853567ffffffffffffffff808211156141e957600080fd5b6141f589838a01613ca3565b9650602088013591508082111561420b57600080fd5b5061421888828901613ca3565b959895975050505060408401359360608101359360809091013592509050565b600082601f83011261424957600080fd5b8135602067ffffffffffffffff82111561426557614265613c1b565b8160051b614274828201613c4a565b928352848101820192828101908785111561428e57600080fd5b83870192505b8483101561317057823582529183019190830190614294565b60008060008060008060c087890312156142c657600080fd5b6142cf87613d5d565b9550602087013567ffffffffffffffff808211156142ec57600080fd5b6142f88a838b01613ca3565b9650604089013591508082111561430e57600080fd5b61431a8a838b01613ca3565b9550606089013591508082111561433057600080fd5b61433c8a838b01614238565b9450608089013591508082111561435257600080fd5b61435e8a838b01613ca3565b935060a089013591508082111561437457600080fd5b5061438189828a01613ca3565b9150509295509295509295565b6000602082840312156143a057600080fd5b5035919050565b6040815260006143ba6040830185613eee565b8281036020840152610f368185613eee565b600080600080600060a086880312156143e457600080fd5b6143ed86613d5d565b9450602086013567ffffffffffffffff8082111561440a57600080fd5b61441689838a01613ca3565b9550604088013591508082111561442c57600080fd5b613ddf89838a01614238565b80356001600160a01b0381168114613d6e57600080fd5b60006020828403121561446157600080fd5b61145e82614438565b6000806000806080858703121561448057600080fd5b61448985614438565b935061449760208601614438565b92506144a560408601614438565b91506144b360608601614438565b905092959194509250565b6000602082840312156144d057600080fd5b8151801515811461145e57600080fd5b63ffffffff84168152826020820152606060408201526000610f366060830184613eee565b60006020828403121561451757600080fd5b5051919050565b63ffffffff851681528360208201528260408201526080606082015260006145496080830184613eee565b9695505050505050565b60006020828403121561456557600080fd5b815167ffffffffffffffff81111561457c57600080fd5b8201601f8101841361458d57600080fd5b805161459b613cc282613c7b565b8181528560208385010111156145b057600080fd5b610f36826020830160208601613eca565b63ffffffff8616815260006020868184015260a060408401526145e760a0840187613eee565b60608401869052838103608085015284518082528286019183019060005b818110156146335783516fffffffffffffffffffffffffffffffff1683529284019291840191600101614605565b50909a9950505050505050505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b600082357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc18336030181126146a657600080fd5b9190910192915050565b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe18436030181126146e557600080fd5b83018035915067ffffffffffffffff82111561470057600080fd5b60200191503681900382131561225357600080fd5b8183823760009101908152919050565b600063ffffffff8089168352808816602084015286604084015280861660608401525083608083015260c060a083015261476260c0830184613eee565b98975050505050505050565b60ff8516815260806020820152600061478a6080830186613eee565b828103604084015261479c8186613eee565b905082810360608401526131708185613eee565b60ff841681526060602082015260006147cc6060830185613eee565b82810360408401526145498185613eee565b6000602082840312156147f057600080fd5b815161145e81614084565b60006060828403121561480d57600080fd5b6040516060810181811067ffffffffffffffff8211171561483057614830613c1b565b60405282516006811061484257600080fd5b8152602083015161485281614084565b6020820152604083015161486581614084565b60408201529392505050565b63ffffffff851681526001600160a01b038416602082015260806040820152600061489f6080830185613eee565b82810360608401526131708185613eee565b600181811c908216806148c557607f821691505b60208210810361278d577f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b808201808211156121d5576121d561492d565b80820281158282048414176121d5576121d561492d565b600060001982036149995761499961492d565b5060010190565b818103818111156121d5576121d561492d565b601f821115612beb57600081815260208120601f850160051c810160208610156149da5750805b601f850160051c820191505b81811015612697578281556001016149e6565b815167ffffffffffffffff811115614a1357614a13613c1b565b614a2781614a2184546148b1565b846149b3565b602080601f831160018114614a5c5760008415614a445750858301515b600019600386901b1c1916600185901b178555612697565b600085815260208120601f198616915b82811015614a8b57888601518255948401946001909101908401614a6c565b5085821015614aa95787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b600082614aef577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b50049056fea26469706673582212209750e141609e1affd8326f71c1584e563dbf2844350223eab568a94af45ce12764736f6c63430008110033","info":{"source":"// SPDX-License-Identifier: MIT\npragma solidity =0.8.17 ^0.8.0 ^0.8.1 ^0.8.2;\n\n// contracts/events/InboxEvents.sol\n\nabstract contract InboxEvents {\n /**\n * @notice Emitted when a snapshot is accepted by the Summit contract.\n * @param domain Domain where the signed Agent is active (ZERO for Guards)\n * @param agent Agent who signed the snapshot\n * @param snapPayload Raw payload with snapshot data\n * @param snapSignature Agent signature for the snapshot\n */\n event SnapshotAccepted(uint32 indexed domain, address indexed agent, bytes snapPayload, bytes snapSignature);\n\n /**\n * @notice Emitted when a snapshot is accepted by the Summit contract.\n * @param domain Domain where the signed Notary is active\n * @param notary Notary who signed the attestation\n * @param rcptPayload Raw payload with receipt data\n * @param rcptSignature Notary signature for the receipt\n */\n event ReceiptAccepted(uint32 domain, address notary, bytes rcptPayload, bytes rcptSignature);\n\n /**\n * @notice Emitted when a proof of invalid attestation is submitted.\n * @param attPayload Raw payload with Attestation data\n * @param attSignature Notary signature for the attestation\n */\n event InvalidAttestation(bytes attPayload, bytes attSignature);\n\n /**\n * @notice Emitted when a proof of invalid attestation report is submitted.\n * @param arPayload Raw payload with report data\n * @param arSignature Guard signature for the report\n */\n event InvalidAttestationReport(bytes arPayload, bytes arSignature);\n}\n\n// contracts/events/StatementInboxEvents.sol\n\nabstract contract StatementInboxEvents {\n // ════════════════════════════════════════════ STATEMENT ACCEPTED ═════════════════════════════════════════════════\n\n /**\n * @notice Emitted when a snapshot is accepted by the Destination contract.\n * @param domain Domain where the signed Notary is active\n * @param notary Notary who signed the attestation\n * @param attPayload Raw payload with attestation data\n * @param attSignature Notary signature for the attestation\n */\n event AttestationAccepted(uint32 domain, address notary, bytes attPayload, bytes attSignature);\n\n // ═════════════════════════════════════════ INVALID STATEMENT PROVED ══════════════════════════════════════════════\n\n /**\n * @notice Emitted when a proof of invalid receipt statement is submitted.\n * @param rcptPayload Raw payload with the receipt statement\n * @param rcptSignature Notary signature for the receipt statement\n */\n event InvalidReceipt(bytes rcptPayload, bytes rcptSignature);\n\n /**\n * @notice Emitted when a proof of invalid receipt report is submitted.\n * @param rrPayload Raw payload with report data\n * @param rrSignature Guard signature for the report\n */\n event InvalidReceiptReport(bytes rrPayload, bytes rrSignature);\n\n /**\n * @notice Emitted when a proof of invalid state in the signed attestation is submitted.\n * @param stateIndex Index of invalid state in the snapshot\n * @param statePayload Raw payload with state data\n * @param attPayload Raw payload with Attestation data for snapshot\n * @param attSignature Notary signature for the attestation\n */\n event InvalidStateWithAttestation(uint8 stateIndex, bytes statePayload, bytes attPayload, bytes attSignature);\n\n /**\n * @notice Emitted when a proof of invalid state in the signed snapshot is submitted.\n * @param stateIndex Index of invalid state in the snapshot\n * @param snapPayload Raw payload with snapshot data\n * @param snapSignature Agent signature for the snapshot\n */\n event InvalidStateWithSnapshot(uint8 stateIndex, bytes snapPayload, bytes snapSignature);\n\n /**\n * @notice Emitted when a proof of invalid state report is submitted.\n * @param srPayload Raw payload with report data\n * @param srSignature Guard signature for the report\n */\n event InvalidStateReport(bytes srPayload, bytes srSignature);\n}\n\n// contracts/interfaces/ISnapshotHub.sol\n\ninterface ISnapshotHub {\n /**\n * @notice Check that a given attestation is valid: matches the historical attestation\n * derived from an accepted Notary snapshot.\n * @dev Will revert if any of these is true:\n * - Attestation payload is not properly formatted.\n * @param attPayload Raw payload with attestation data\n * @return isValid Whether the provided attestation is valid\n */\n function isValidAttestation(bytes memory attPayload) external view returns (bool isValid);\n\n /**\n * @notice Returns saved attestation with the given nonce.\n * @dev Reverts if attestation with given nonce hasn't been created yet.\n * @param attNonce Nonce for the attestation\n * @return attPayload Raw payload with formatted Attestation data\n * @return agentRoot Agent root hash used for the attestation\n * @return snapGas Snapshot gas data used for the attestation\n */\n function getAttestation(uint32 attNonce)\n external\n view\n returns (bytes memory attPayload, bytes32 agentRoot, uint256[] memory snapGas);\n\n /**\n * @notice Returns the state with the highest known nonce submitted by a given Agent.\n * @param origin Domain of origin chain\n * @param agent Agent address\n * @return statePayload Raw payload with agent's latest state for origin\n */\n function getLatestAgentState(uint32 origin, address agent) external view returns (bytes memory statePayload);\n\n /**\n * @notice Returns latest saved attestation for a Notary.\n * @param notary Notary address\n * @return attPayload Raw payload with formatted Attestation data\n * @return agentRoot Agent root hash used for the attestation\n * @return snapGas Snapshot gas data used for the attestation\n */\n function getLatestNotaryAttestation(address notary)\n external\n view\n returns (bytes memory attPayload, bytes32 agentRoot, uint256[] memory snapGas);\n\n /**\n * @notice Returns Guard snapshot from the list of all accepted Guard snapshots.\n * @dev Reverts if snapshot with given index hasn't been accepted yet.\n * @param index Snapshot index in the list of all Guard snapshots\n * @return snapPayload Raw payload with Guard snapshot\n * @return snapSignature Raw payload with Guard signature for snapshot\n */\n function getGuardSnapshot(uint256 index)\n external\n view\n returns (bytes memory snapPayload, bytes memory snapSignature);\n\n /**\n * @notice Returns Notary snapshot from the list of all accepted Guard snapshots.\n * @dev Reverts if snapshot with given index hasn't been accepted yet.\n * @param index Snapshot index in the list of all Notary snapshots\n * @return snapPayload Raw payload with Notary snapshot\n * @return snapSignature Raw payload with Notary signature for snapshot\n */\n function getNotarySnapshot(uint256 index)\n external\n view\n returns (bytes memory snapPayload, bytes memory snapSignature);\n\n /**\n * @notice Returns Notary snapshot that was used for creating a given attestation.\n * @dev Reverts if any of these is true:\n * - Attestation payload is not properly formatted.\n * - Attestation is invalid (doesn't have a matching Notary snapshot).\n * @param attPayload Raw payload with attestation data\n * @return snapPayload Raw payload with Notary snapshot\n * @return snapSignature Raw payload with Notary signature for snapshot\n */\n function getNotarySnapshot(bytes memory attPayload)\n external\n view\n returns (bytes memory snapPayload, bytes memory snapSignature);\n\n /**\n * @notice Returns proof of inclusion of (root, origin) fields of a given snapshot's state\n * into the Snapshot Merkle Tree for a given attestation.\n * @dev Reverts if any of these is true:\n * - Attestation with given nonce hasn't been created yet.\n * - State index is out of range of snapshot list.\n * @param attNonce Nonce for the attestation\n * @param stateIndex Index of state in the attestation's snapshot\n * @return snapProof The snapshot proof\n */\n function getSnapshotProof(uint32 attNonce, uint8 stateIndex) external view returns (bytes32[] memory snapProof);\n}\n\n// contracts/interfaces/IStateHub.sol\n\ninterface IStateHub {\n /**\n * @notice Check that a given state is valid: matches the historical state of Origin contract.\n * Note: any Agent including an invalid state in their snapshot will be slashed\n * upon providing the snapshot and agent signature for it to Origin contract.\n * @dev Will revert if any of these is true:\n * - State payload is not properly formatted.\n * @param statePayload Raw payload with state data\n * @return isValid Whether the provided state is valid\n */\n function isValidState(bytes memory statePayload) external view returns (bool isValid);\n\n /**\n * @notice Returns the amount of saved states so far.\n * @dev This includes the initial state of \"empty Origin Merkle Tree\".\n */\n function statesAmount() external view returns (uint256);\n\n /**\n * @notice Suggest the data (state after latest sent message) to sign for an Agent.\n * Note: signing the suggested state data will will never lead to slashing of the actor,\n * assuming they have confirmed that the block, which number is included in the data,\n * is not subject to reorganization (which is different for every observed chain).\n * @return statePayload Raw payload with the latest state data\n */\n function suggestLatestState() external view returns (bytes memory statePayload);\n\n /**\n * @notice Given the historical nonce, suggest the state data to sign for an Agent.\n * Note: signing the suggested state data will will never lead to slashing of the actor,\n * assuming they have confirmed that the block, which number is included in the data,\n * is not subject to reorganization (which is different for every observed chain).\n * @param nonce Historical nonce to form a state\n * @return statePayload Raw payload with historical state data\n */\n function suggestState(uint32 nonce) external view returns (bytes memory statePayload);\n}\n\n// contracts/interfaces/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/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// node_modules/@openzeppelin/contracts/utils/math/Math.sol\n\n// OpenZeppelin Contracts (last updated v4.9.0) (utils/math/Math.sol)\n\n/**\n * @dev Standard math utilities missing in the Solidity language.\n */\nlibrary Math {\n enum Rounding {\n Down, // Toward negative infinity\n Up, // Toward infinity\n Zero // Toward zero\n }\n\n /**\n * @dev Returns the largest of two numbers.\n */\n function max(uint256 a, uint256 b) internal pure returns (uint256) {\n return a \u003e b ? a : b;\n }\n\n /**\n * @dev Returns the smallest of two numbers.\n */\n function min(uint256 a, uint256 b) internal pure returns (uint256) {\n return a \u003c b ? a : b;\n }\n\n /**\n * @dev Returns the average of two numbers. The result is rounded towards\n * zero.\n */\n function average(uint256 a, uint256 b) internal pure returns (uint256) {\n // (a + b) / 2 can overflow.\n return (a \u0026 b) + (a ^ b) / 2;\n }\n\n /**\n * @dev Returns the ceiling of the division of two numbers.\n *\n * This differs from standard division with `/` in that it rounds up instead\n * of rounding down.\n */\n function ceilDiv(uint256 a, uint256 b) internal pure returns (uint256) {\n // (a + b - 1) / b can overflow on addition, so we distribute.\n return a == 0 ? 0 : (a - 1) / b + 1;\n }\n\n /**\n * @notice Calculates floor(x * y / denominator) with full precision. Throws if result overflows a uint256 or denominator == 0\n * @dev Original credit to Remco Bloemen under MIT license (https://xn--2-umb.com/21/muldiv)\n * with further edits by Uniswap Labs also under MIT license.\n */\n function mulDiv(uint256 x, uint256 y, uint256 denominator) internal pure returns (uint256 result) {\n unchecked {\n // 512-bit multiply [prod1 prod0] = x * y. Compute the product mod 2^256 and mod 2^256 - 1, then use\n // use the Chinese Remainder Theorem to reconstruct the 512 bit result. The result is stored in two 256\n // variables such that product = prod1 * 2^256 + prod0.\n uint256 prod0; // Least significant 256 bits of the product\n uint256 prod1; // Most significant 256 bits of the product\n assembly {\n let mm := mulmod(x, y, not(0))\n prod0 := mul(x, y)\n prod1 := sub(sub(mm, prod0), lt(mm, prod0))\n }\n\n // Handle non-overflow cases, 256 by 256 division.\n if (prod1 == 0) {\n // Solidity will revert if denominator == 0, unlike the div opcode on its own.\n // The surrounding unchecked block does not change this fact.\n // See https://docs.soliditylang.org/en/latest/control-structures.html#checked-or-unchecked-arithmetic.\n return prod0 / denominator;\n }\n\n // Make sure the result is less than 2^256. Also prevents denominator == 0.\n require(denominator \u003e prod1, \"Math: mulDiv overflow\");\n\n ///////////////////////////////////////////////\n // 512 by 256 division.\n ///////////////////////////////////////////////\n\n // Make division exact by subtracting the remainder from [prod1 prod0].\n uint256 remainder;\n assembly {\n // Compute remainder using mulmod.\n remainder := mulmod(x, y, denominator)\n\n // Subtract 256 bit number from 512 bit number.\n prod1 := sub(prod1, gt(remainder, prod0))\n prod0 := sub(prod0, remainder)\n }\n\n // Factor powers of two out of denominator and compute largest power of two divisor of denominator. Always \u003e= 1.\n // See https://cs.stackexchange.com/q/138556/92363.\n\n // Does not overflow because the denominator cannot be zero at this stage in the function.\n uint256 twos = denominator \u0026 (~denominator + 1);\n assembly {\n // Divide denominator by twos.\n denominator := div(denominator, twos)\n\n // Divide [prod1 prod0] by twos.\n prod0 := div(prod0, twos)\n\n // Flip twos such that it is 2^256 / twos. If twos is zero, then it becomes one.\n twos := add(div(sub(0, twos), twos), 1)\n }\n\n // Shift in bits from prod1 into prod0.\n prod0 |= prod1 * twos;\n\n // Invert denominator mod 2^256. Now that denominator is an odd number, it has an inverse modulo 2^256 such\n // that denominator * inv = 1 mod 2^256. Compute the inverse by starting with a seed that is correct for\n // four bits. That is, denominator * inv = 1 mod 2^4.\n uint256 inverse = (3 * denominator) ^ 2;\n\n // Use the Newton-Raphson iteration to improve the precision. Thanks to Hensel's lifting lemma, this also works\n // in modular arithmetic, doubling the correct bits in each step.\n inverse *= 2 - denominator * inverse; // inverse mod 2^8\n inverse *= 2 - denominator * inverse; // inverse mod 2^16\n inverse *= 2 - denominator * inverse; // inverse mod 2^32\n inverse *= 2 - denominator * inverse; // inverse mod 2^64\n inverse *= 2 - denominator * inverse; // inverse mod 2^128\n inverse *= 2 - denominator * inverse; // inverse mod 2^256\n\n // Because the division is now exact we can divide by multiplying with the modular inverse of denominator.\n // This will give us the correct result modulo 2^256. Since the preconditions guarantee that the outcome is\n // less than 2^256, this is the final result. We don't need to compute the high bits of the result and prod1\n // is no longer required.\n result = prod0 * inverse;\n return result;\n }\n }\n\n /**\n * @notice Calculates x * y / denominator with full precision, following the selected rounding direction.\n */\n function mulDiv(uint256 x, uint256 y, uint256 denominator, Rounding rounding) internal pure returns (uint256) {\n uint256 result = mulDiv(x, y, denominator);\n if (rounding == Rounding.Up \u0026\u0026 mulmod(x, y, denominator) \u003e 0) {\n result += 1;\n }\n return result;\n }\n\n /**\n * @dev Returns the square root of a number. If the number is not a perfect square, the value is rounded down.\n *\n * Inspired by Henry S. Warren, Jr.'s \"Hacker's Delight\" (Chapter 11).\n */\n function sqrt(uint256 a) internal pure returns (uint256) {\n if (a == 0) {\n return 0;\n }\n\n // For our first guess, we get the biggest power of 2 which is smaller than the square root of the target.\n //\n // We know that the \"msb\" (most significant bit) of our target number `a` is a power of 2 such that we have\n // `msb(a) \u003c= a \u003c 2*msb(a)`. This value can be written `msb(a)=2**k` with `k=log2(a)`.\n //\n // This can be rewritten `2**log2(a) \u003c= a \u003c 2**(log2(a) + 1)`\n // → `sqrt(2**k) \u003c= sqrt(a) \u003c sqrt(2**(k+1))`\n // → `2**(k/2) \u003c= sqrt(a) \u003c 2**((k+1)/2) \u003c= 2**(k/2 + 1)`\n //\n // Consequently, `2**(log2(a) / 2)` is a good first approximation of `sqrt(a)` with at least 1 correct bit.\n uint256 result = 1 \u003c\u003c (log2(a) \u003e\u003e 1);\n\n // At this point `result` is an estimation with one bit of precision. We know the true value is a uint128,\n // since it is the square root of a uint256. Newton's method converges quadratically (precision doubles at\n // every iteration). We thus need at most 7 iteration to turn our partial result with one bit of precision\n // into the expected uint128 result.\n unchecked {\n result = (result + a / result) \u003e\u003e 1;\n result = (result + a / result) \u003e\u003e 1;\n result = (result + a / result) \u003e\u003e 1;\n result = (result + a / result) \u003e\u003e 1;\n result = (result + a / result) \u003e\u003e 1;\n result = (result + a / result) \u003e\u003e 1;\n result = (result + a / result) \u003e\u003e 1;\n return min(result, a / result);\n }\n }\n\n /**\n * @notice Calculates sqrt(a), following the selected rounding direction.\n */\n function sqrt(uint256 a, Rounding rounding) internal pure returns (uint256) {\n unchecked {\n uint256 result = sqrt(a);\n return result + (rounding == Rounding.Up \u0026\u0026 result * result \u003c a ? 1 : 0);\n }\n }\n\n /**\n * @dev Return the log in base 2, rounded down, of a positive value.\n * Returns 0 if given 0.\n */\n function log2(uint256 value) internal pure returns (uint256) {\n uint256 result = 0;\n unchecked {\n if (value \u003e\u003e 128 \u003e 0) {\n value \u003e\u003e= 128;\n result += 128;\n }\n if (value \u003e\u003e 64 \u003e 0) {\n value \u003e\u003e= 64;\n result += 64;\n }\n if (value \u003e\u003e 32 \u003e 0) {\n value \u003e\u003e= 32;\n result += 32;\n }\n if (value \u003e\u003e 16 \u003e 0) {\n value \u003e\u003e= 16;\n result += 16;\n }\n if (value \u003e\u003e 8 \u003e 0) {\n value \u003e\u003e= 8;\n result += 8;\n }\n if (value \u003e\u003e 4 \u003e 0) {\n value \u003e\u003e= 4;\n result += 4;\n }\n if (value \u003e\u003e 2 \u003e 0) {\n value \u003e\u003e= 2;\n result += 2;\n }\n if (value \u003e\u003e 1 \u003e 0) {\n result += 1;\n }\n }\n return result;\n }\n\n /**\n * @dev Return the log in base 2, following the selected rounding direction, of a positive value.\n * Returns 0 if given 0.\n */\n function log2(uint256 value, Rounding rounding) internal pure returns (uint256) {\n unchecked {\n uint256 result = log2(value);\n return result + (rounding == Rounding.Up \u0026\u0026 1 \u003c\u003c result \u003c value ? 1 : 0);\n }\n }\n\n /**\n * @dev Return the log in base 10, rounded down, of a positive value.\n * Returns 0 if given 0.\n */\n function log10(uint256 value) internal pure returns (uint256) {\n uint256 result = 0;\n unchecked {\n if (value \u003e= 10 ** 64) {\n value /= 10 ** 64;\n result += 64;\n }\n if (value \u003e= 10 ** 32) {\n value /= 10 ** 32;\n result += 32;\n }\n if (value \u003e= 10 ** 16) {\n value /= 10 ** 16;\n result += 16;\n }\n if (value \u003e= 10 ** 8) {\n value /= 10 ** 8;\n result += 8;\n }\n if (value \u003e= 10 ** 4) {\n value /= 10 ** 4;\n result += 4;\n }\n if (value \u003e= 10 ** 2) {\n value /= 10 ** 2;\n result += 2;\n }\n if (value \u003e= 10 ** 1) {\n result += 1;\n }\n }\n return result;\n }\n\n /**\n * @dev Return the log in base 10, following the selected rounding direction, of a positive value.\n * Returns 0 if given 0.\n */\n function log10(uint256 value, Rounding rounding) internal pure returns (uint256) {\n unchecked {\n uint256 result = log10(value);\n return result + (rounding == Rounding.Up \u0026\u0026 10 ** result \u003c value ? 1 : 0);\n }\n }\n\n /**\n * @dev Return the log in base 256, rounded down, of a positive value.\n * Returns 0 if given 0.\n *\n * Adding one to the result gives the number of pairs of hex symbols needed to represent `value` as a hex string.\n */\n function log256(uint256 value) internal pure returns (uint256) {\n uint256 result = 0;\n unchecked {\n if (value \u003e\u003e 128 \u003e 0) {\n value \u003e\u003e= 128;\n result += 16;\n }\n if (value \u003e\u003e 64 \u003e 0) {\n value \u003e\u003e= 64;\n result += 8;\n }\n if (value \u003e\u003e 32 \u003e 0) {\n value \u003e\u003e= 32;\n result += 4;\n }\n if (value \u003e\u003e 16 \u003e 0) {\n value \u003e\u003e= 16;\n result += 2;\n }\n if (value \u003e\u003e 8 \u003e 0) {\n result += 1;\n }\n }\n return result;\n }\n\n /**\n * @dev Return the log in base 256, following the selected rounding direction, of a positive value.\n * Returns 0 if given 0.\n */\n function log256(uint256 value, Rounding rounding) internal pure returns (uint256) {\n unchecked {\n uint256 result = log256(value);\n return result + (rounding == Rounding.Up \u0026\u0026 1 \u003c\u003c (result \u003c\u003c 3) \u003c value ? 1 : 0);\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/utils/math/SignedMath.sol\n\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/math/SignedMath.sol)\n\n/**\n * @dev Standard signed math utilities missing in the Solidity language.\n */\nlibrary SignedMath {\n /**\n * @dev Returns the largest of two signed numbers.\n */\n function max(int256 a, int256 b) internal pure returns (int256) {\n return a \u003e b ? a : b;\n }\n\n /**\n * @dev Returns the smallest of two signed numbers.\n */\n function min(int256 a, int256 b) internal pure returns (int256) {\n return a \u003c b ? a : b;\n }\n\n /**\n * @dev Returns the average of two signed numbers without overflow.\n * The result is rounded towards zero.\n */\n function average(int256 a, int256 b) internal pure returns (int256) {\n // Formula from the book \"Hacker's Delight\"\n int256 x = (a \u0026 b) + ((a ^ b) \u003e\u003e 1);\n return x + (int256(uint256(x) \u003e\u003e 255) \u0026 (a ^ b));\n }\n\n /**\n * @dev Returns the absolute unsigned value of a signed value.\n */\n function abs(int256 n) internal pure returns (uint256) {\n unchecked {\n // must be unchecked in order to support `n = type(int256).min`\n return uint256(n \u003e= 0 ? n : -n);\n }\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// 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/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/InterfaceSummit.sol\n\ninterface InterfaceSummit {\n // ══════════════════════════════════════════ ACCEPT AGENT STATEMENTS ══════════════════════════════════════════════\n\n /**\n * @notice Accepts a receipt, which local `AgentManager` verified to have been signed by an active Notary.\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 * - Notary who signed the receipt is referenced as the \"Receipt Notary\".\n * - Notary who signed the attestation on destination chain is referenced as the \"Attestation Notary\".\n * \u003e Will revert if any of these is true:\n * \u003e - Called by anyone other than local `AgentManager`.\n * \u003e - Receipt body payload is not properly formatted.\n * \u003e - Receipt signer is in Dispute.\n * \u003e - Receipt's snapshot root is unknown.\n * @param rcptNotaryIndex Index of Receipt Notary in Agent Merkle Tree\n * @param attNotaryIndex Index of Attestation Notary in Agent Merkle Tree\n * @param sigIndex Index of stored Notary signature\n * @param attNonce Nonce of the attestation used for proving the executed message\n * @param paddedTips Padded encoded paid tips information\n * @param rcptPayload Raw payload with message execution receipt\n * @return wasAccepted Whether the receipt was accepted\n */\n function acceptReceipt(\n uint32 rcptNotaryIndex,\n uint32 attNotaryIndex,\n uint256 sigIndex,\n uint32 attNonce,\n uint256 paddedTips,\n bytes memory rcptPayload\n ) external returns (bool wasAccepted);\n\n /**\n * @notice Accepts a snapshot, which local `AgentManager` verified to have been signed by an active Guard.\n * \u003e Snapshot is a list of states for a set of Origin contracts residing on any of the chains.\n * All the states in the Guard-signed snapshot become available for Notary signing.\n * \u003e Will revert if any of these is true:\n * \u003e - Called by anyone other than local `AgentManager`.\n * \u003e - Snapshot payload is not properly formatted.\n * \u003e - Snapshot contains a state older then the Guard has previously submitted.\n * @param guardIndex Index of Guard in Agent Merkle Tree\n * @param sigIndex Index of stored Agent signature\n * @param snapPayload Raw payload with snapshot data\n */\n function acceptGuardSnapshot(uint32 guardIndex, uint256 sigIndex, bytes memory snapPayload) external;\n\n /**\n * @notice Accepts a snapshot, which local `AgentManager` verified to have been signed by an active Notary.\n * \u003e Snapshot is a list of states for a set of Origin contracts residing on any of the chains.\n * Snapshot Merkle Root is calculated and saved for valid snapshots, i.e.\n * snapshots which are only using states previously submitted by any of the Guards.\n * - Notary could use states singed by the same of different Guards 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 - Called by anyone other than local `AgentManager`.\n * \u003e - Snapshot payload is not properly formatted.\n * \u003e - Snapshot contains a state older then the Notary has previously submitted.\n * \u003e - Snapshot contains a state that no Guard has previously submitted.\n * @param notaryIndex Index of Notary in Agent Merkle Tree\n * @param sigIndex Index of stored Agent signature\n * @param agentRoot Current root of the Agent Merkle Tree\n * @param snapPayload Raw payload with snapshot data\n * @return attPayload Raw payload with data for attestation derived from Notary snapshot.\n */\n function acceptNotarySnapshot(uint32 notaryIndex, uint256 sigIndex, bytes32 agentRoot, bytes memory snapPayload)\n external\n returns (bytes memory attPayload);\n\n // ════════════════════════════════════════════════ TIPS LOGIC ═════════════════════════════════════════════════════\n\n /**\n * @notice Distributes tips using the first Receipt from the \"receipt quarantine queue\".\n * Possible scenarios:\n * - Receipt queue is empty =\u003e does nothing\n * - Receipt optimistic period is not over =\u003e does nothing\n * - Either of Notaries present in Receipt was slashed =\u003e receipt is deleted from the queue\n * - Either of Notaries present in Receipt in Dispute =\u003e receipt is moved to the end of queue\n * - None of the above =\u003e receipt tips are distributed\n * @dev Returned value makes it possible to do the following: `while (distributeTips()) {}`\n * @return queuePopped Whether the first element was popped from the queue\n */\n function distributeTips() external returns (bool queuePopped);\n\n /**\n * @notice Withdraws locked base message tips from requested domain Origin to the recipient.\n * This is done by a call to a local Origin contract, or by a manager message to the remote chain.\n * @dev This will revert, if the pending balance of origin tips (earned-claimed) is lower than requested.\n * @param origin Domain of chain to withdraw tips on\n * @param amount Amount of tips to withdraw\n */\n function withdrawTips(uint32 origin, uint256 amount) external;\n\n // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════\n\n /**\n * @notice Returns earned and claimed tips for the actor.\n * Note: Tips for address(0) belong to the Treasury.\n * @param actor Address of the actor\n * @param origin Domain where the tips were initially paid\n * @return earned Total amount of origin tips the actor has earned so far\n * @return claimed Total amount of origin tips the actor has claimed so far\n */\n function actorTips(address actor, uint32 origin) external view returns (uint128 earned, uint128 claimed);\n\n /**\n * @notice Returns the amount of receipts in the \"Receipt Quarantine Queue\".\n */\n function receiptQueueLength() external view returns (uint256);\n\n /**\n * @notice Returns the state with the highest known nonce\n * submitted by any of the currently active Guards.\n * @param origin Domain of origin chain\n * @return statePayload Raw payload with latest active Guard state for origin\n */\n function getLatestState(uint32 origin) external view returns (bytes memory statePayload);\n}\n\n// node_modules/@openzeppelin/contracts/utils/Strings.sol\n\n// OpenZeppelin Contracts (last updated v4.9.0) (utils/Strings.sol)\n\n/**\n * @dev String operations.\n */\nlibrary Strings {\n bytes16 private constant _SYMBOLS = \"0123456789abcdef\";\n uint8 private constant _ADDRESS_LENGTH = 20;\n\n /**\n * @dev Converts a `uint256` to its ASCII `string` decimal representation.\n */\n function toString(uint256 value) internal pure returns (string memory) {\n unchecked {\n uint256 length = Math.log10(value) + 1;\n string memory buffer = new string(length);\n uint256 ptr;\n /// @solidity memory-safe-assembly\n assembly {\n ptr := add(buffer, add(32, length))\n }\n while (true) {\n ptr--;\n /// @solidity memory-safe-assembly\n assembly {\n mstore8(ptr, byte(mod(value, 10), _SYMBOLS))\n }\n value /= 10;\n if (value == 0) break;\n }\n return buffer;\n }\n }\n\n /**\n * @dev Converts a `int256` to its ASCII `string` decimal representation.\n */\n function toString(int256 value) internal pure returns (string memory) {\n return string(abi.encodePacked(value \u003c 0 ? \"-\" : \"\", toString(SignedMath.abs(value))));\n }\n\n /**\n * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation.\n */\n function toHexString(uint256 value) internal pure returns (string memory) {\n unchecked {\n return toHexString(value, Math.log256(value) + 1);\n }\n }\n\n /**\n * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length.\n */\n function toHexString(uint256 value, uint256 length) internal pure returns (string memory) {\n bytes memory buffer = new bytes(2 * length + 2);\n buffer[0] = \"0\";\n buffer[1] = \"x\";\n for (uint256 i = 2 * length + 1; i \u003e 1; --i) {\n buffer[i] = _SYMBOLS[value \u0026 0xf];\n value \u003e\u003e= 4;\n }\n require(value == 0, \"Strings: hex length insufficient\");\n return string(buffer);\n }\n\n /**\n * @dev Converts an `address` with fixed length of 20 bytes to its not checksummed ASCII `string` hexadecimal representation.\n */\n function toHexString(address addr) internal pure returns (string memory) {\n return toHexString(uint256(uint160(addr)), _ADDRESS_LENGTH);\n }\n\n /**\n * @dev Returns true if the two strings are equal.\n */\n function equal(string memory a, string memory b) internal pure returns (bool) {\n return keccak256(bytes(a)) == keccak256(bytes(b));\n }\n}\n\n// node_modules/@openzeppelin/contracts-upgradeable/utils/ContextUpgradeable.sol\n\n// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)\n\n/**\n * @dev Provides information about the current execution context, including the\n * sender of the transaction and its data. While these are generally available\n * via msg.sender and msg.data, they should not be accessed in such a direct\n * manner, since when dealing with meta-transactions the account sending and\n * paying for execution may not be the actual sender (as far as an application\n * is concerned).\n *\n * This contract is only required for intermediate, library-like contracts.\n */\nabstract contract ContextUpgradeable is Initializable {\n function __Context_init() internal onlyInitializing {\n }\n\n function __Context_init_unchained() internal onlyInitializing {\n }\n function _msgSender() internal view virtual returns (address) {\n return msg.sender;\n }\n\n function _msgData() internal view virtual returns (bytes calldata) {\n return msg.data;\n }\n\n /**\n * @dev This empty reserved space is put in place to allow future versions to add new\n * variables without shifting down storage in the inheritance chain.\n * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\n */\n uint256[50] private __gap;\n}\n\n// contracts/libs/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/utils/cryptography/ECDSA.sol\n\n// OpenZeppelin Contracts (last updated v4.9.0) (utils/cryptography/ECDSA.sol)\n\n/**\n * @dev Elliptic Curve Digital Signature Algorithm (ECDSA) operations.\n *\n * These functions can be used to verify that a message was signed by the holder\n * of the private keys of a given address.\n */\nlibrary ECDSA {\n enum RecoverError {\n NoError,\n InvalidSignature,\n InvalidSignatureLength,\n InvalidSignatureS,\n InvalidSignatureV // Deprecated in v4.8\n }\n\n function _throwError(RecoverError error) private pure {\n if (error == RecoverError.NoError) {\n return; // no error: do nothing\n } else if (error == RecoverError.InvalidSignature) {\n revert(\"ECDSA: invalid signature\");\n } else if (error == RecoverError.InvalidSignatureLength) {\n revert(\"ECDSA: invalid signature length\");\n } else if (error == RecoverError.InvalidSignatureS) {\n revert(\"ECDSA: invalid signature 's' value\");\n }\n }\n\n /**\n * @dev Returns the address that signed a hashed message (`hash`) with\n * `signature` or error string. This address can then be used for verification purposes.\n *\n * The `ecrecover` EVM opcode allows for malleable (non-unique) signatures:\n * this function rejects them by requiring the `s` value to be in the lower\n * half order, and the `v` value to be either 27 or 28.\n *\n * IMPORTANT: `hash` _must_ be the result of a hash operation for the\n * verification to be secure: it is possible to craft signatures that\n * recover to arbitrary addresses for non-hashed data. A safe way to ensure\n * this is by receiving a hash of the original message (which may otherwise\n * be too long), and then calling {toEthSignedMessageHash} on it.\n *\n * Documentation for signature generation:\n * - with https://web3js.readthedocs.io/en/v1.3.4/web3-eth-accounts.html#sign[Web3.js]\n * - with https://docs.ethers.io/v5/api/signer/#Signer-signMessage[ethers]\n *\n * _Available since v4.3._\n */\n function tryRecover(bytes32 hash, bytes memory signature) internal pure returns (address, RecoverError) {\n if (signature.length == 65) {\n bytes32 r;\n bytes32 s;\n uint8 v;\n // ecrecover takes the signature parameters, and the only way to get them\n // currently is to use assembly.\n /// @solidity memory-safe-assembly\n assembly {\n r := mload(add(signature, 0x20))\n s := mload(add(signature, 0x40))\n v := byte(0, mload(add(signature, 0x60)))\n }\n return tryRecover(hash, v, r, s);\n } else {\n return (address(0), RecoverError.InvalidSignatureLength);\n }\n }\n\n /**\n * @dev Returns the address that signed a hashed message (`hash`) with\n * `signature`. This address can then be used for verification purposes.\n *\n * The `ecrecover` EVM opcode allows for malleable (non-unique) signatures:\n * this function rejects them by requiring the `s` value to be in the lower\n * half order, and the `v` value to be either 27 or 28.\n *\n * IMPORTANT: `hash` _must_ be the result of a hash operation for the\n * verification to be secure: it is possible to craft signatures that\n * recover to arbitrary addresses for non-hashed data. A safe way to ensure\n * this is by receiving a hash of the original message (which may otherwise\n * be too long), and then calling {toEthSignedMessageHash} on it.\n */\n function recover(bytes32 hash, bytes memory signature) internal pure returns (address) {\n (address recovered, RecoverError error) = tryRecover(hash, signature);\n _throwError(error);\n return recovered;\n }\n\n /**\n * @dev Overload of {ECDSA-tryRecover} that receives the `r` and `vs` short-signature fields separately.\n *\n * See https://eips.ethereum.org/EIPS/eip-2098[EIP-2098 short signatures]\n *\n * _Available since v4.3._\n */\n function tryRecover(bytes32 hash, bytes32 r, bytes32 vs) internal pure returns (address, RecoverError) {\n bytes32 s = vs \u0026 bytes32(0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff);\n uint8 v = uint8((uint256(vs) \u003e\u003e 255) + 27);\n return tryRecover(hash, v, r, s);\n }\n\n /**\n * @dev Overload of {ECDSA-recover} that receives the `r and `vs` short-signature fields separately.\n *\n * _Available since v4.2._\n */\n function recover(bytes32 hash, bytes32 r, bytes32 vs) internal pure returns (address) {\n (address recovered, RecoverError error) = tryRecover(hash, r, vs);\n _throwError(error);\n return recovered;\n }\n\n /**\n * @dev Overload of {ECDSA-tryRecover} that receives the `v`,\n * `r` and `s` signature fields separately.\n *\n * _Available since v4.3._\n */\n function tryRecover(bytes32 hash, uint8 v, bytes32 r, bytes32 s) internal pure returns (address, RecoverError) {\n // EIP-2 still allows signature malleability for ecrecover(). Remove this possibility and make the signature\n // unique. Appendix F in the Ethereum Yellow paper (https://ethereum.github.io/yellowpaper/paper.pdf), defines\n // the valid range for s in (301): 0 \u003c s \u003c secp256k1n ÷ 2 + 1, and for v in (302): v ∈ {27, 28}. Most\n // signatures from current libraries generate a unique signature with an s-value in the lower half order.\n //\n // If your library generates malleable signatures, such as s-values in the upper range, calculate a new s-value\n // with 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141 - s1 and flip v from 27 to 28 or\n // vice versa. If your library also generates signatures with 0/1 for v instead 27/28, add 27 to v to accept\n // these malleable signatures as well.\n if (uint256(s) \u003e 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0) {\n return (address(0), RecoverError.InvalidSignatureS);\n }\n\n // If the signature is valid (and not malleable), return the signer address\n address signer = ecrecover(hash, v, r, s);\n if (signer == address(0)) {\n return (address(0), RecoverError.InvalidSignature);\n }\n\n return (signer, RecoverError.NoError);\n }\n\n /**\n * @dev Overload of {ECDSA-recover} that receives the `v`,\n * `r` and `s` signature fields separately.\n */\n function recover(bytes32 hash, uint8 v, bytes32 r, bytes32 s) internal pure returns (address) {\n (address recovered, RecoverError error) = tryRecover(hash, v, r, s);\n _throwError(error);\n return recovered;\n }\n\n /**\n * @dev Returns an Ethereum Signed Message, created from a `hash`. This\n * produces hash corresponding to the one signed with the\n * https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`]\n * JSON-RPC method as part of EIP-191.\n *\n * See {recover}.\n */\n function toEthSignedMessageHash(bytes32 hash) internal pure returns (bytes32 message) {\n // 32 is the length in bytes of hash,\n // enforced by the type signature above\n /// @solidity memory-safe-assembly\n assembly {\n mstore(0x00, \"\\x19Ethereum Signed Message:\\n32\")\n mstore(0x1c, hash)\n message := keccak256(0x00, 0x3c)\n }\n }\n\n /**\n * @dev Returns an Ethereum Signed Message, created from `s`. This\n * produces hash corresponding to the one signed with the\n * https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`]\n * JSON-RPC method as part of EIP-191.\n *\n * See {recover}.\n */\n function toEthSignedMessageHash(bytes memory s) internal pure returns (bytes32) {\n return keccak256(abi.encodePacked(\"\\x19Ethereum Signed Message:\\n\", Strings.toString(s.length), s));\n }\n\n /**\n * @dev Returns an Ethereum Signed Typed Data, created from a\n * `domainSeparator` and a `structHash`. This produces hash corresponding\n * to the one signed with the\n * https://eips.ethereum.org/EIPS/eip-712[`eth_signTypedData`]\n * JSON-RPC method as part of EIP-712.\n *\n * See {recover}.\n */\n function toTypedDataHash(bytes32 domainSeparator, bytes32 structHash) internal pure returns (bytes32 data) {\n /// @solidity memory-safe-assembly\n assembly {\n let ptr := mload(0x40)\n mstore(ptr, \"\\x19\\x01\")\n mstore(add(ptr, 0x02), domainSeparator)\n mstore(add(ptr, 0x22), structHash)\n data := keccak256(ptr, 0x42)\n }\n }\n\n /**\n * @dev Returns an Ethereum Signed Data with intended validator, created from a\n * `validator` and `data` according to the version 0 of EIP-191.\n *\n * See {recover}.\n */\n function toDataWithIntendedValidatorHash(address validator, bytes memory data) internal pure returns (bytes32) {\n return keccak256(abi.encodePacked(\"\\x19\\x00\", validator, data));\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/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/inbox/StatementInbox.sol\n\n// ══════════════════════════════ LIBRARY IMPORTS ══════════════════════════════\n\n// ═════════════════════════════ INTERNAL IMPORTS ══════════════════════════════\n\n// ═════════════════════════════ EXTERNAL IMPORTS ══════════════════════════════\n\n/// @notice `StatementInbox` is the entry point for all agent-signed statements. It verifies the\n/// agent signatures, and passes the unsigned statements to the contract to consume it via `acceptX` functions. Is is\n/// also used to verify the agent-signed statements and initiate the agent slashing, should the statement be invalid.\n/// `StatementInbox` is responsible for the following:\n/// - Accepting State and Receipt Reports to initiate a dispute between Guard and Notary.\n/// - Storing all the Guard Reports with the Guard signature leading to a dispute.\n/// - Verifying State/State Reports referencing the local chain and slashing the signer if statement is invalid.\n/// - Verifying Receipt/Receipt Reports referencing the local chain and slashing the signer if statement is invalid.\nabstract contract StatementInbox is MessagingBase, StatementInboxEvents, IStatementInbox {\n using AttestationLib for bytes;\n using ReceiptLib for bytes;\n using StateLib for bytes;\n using SnapshotLib for bytes;\n\n struct StoredReport {\n uint256 sigIndex;\n bytes statementPayload;\n }\n\n // ══════════════════════════════════════════════════ STORAGE ══════════════════════════════════════════════════════\n\n address public agentManager;\n address public origin;\n address public destination;\n\n // TODO: optimize this\n bytes[] internal _storedSignatures;\n StoredReport[] internal _storedReports;\n\n /// @dev gap for upgrade safety\n uint256[45] private __GAP; // solhint-disable-line var-name-mixedcase\n\n // ════════════════════════════════════════════════ INITIALIZER ════════════════════════════════════════════════════\n\n /// @dev Initializes the contract:\n /// - Sets up `msg.sender` as the owner of the contract.\n /// - Sets up `agentManager`, `origin`, and `destination`.\n // solhint-disable-next-line func-name-mixedcase\n function __StatementInbox_init(address agentManager_, address origin_, address destination_)\n internal\n onlyInitializing\n {\n agentManager = agentManager_;\n origin = origin_;\n destination = destination_;\n __Ownable2Step_init();\n }\n\n // ══════════════════════════════════════════ SUBMIT AGENT STATEMENTS ══════════════════════════════════════════════\n\n /// @inheritdoc IStatementInbox\n // solhint-disable-next-line ordering\n function submitStateReportWithSnapshot(\n uint8 stateIndex,\n bytes memory srSignature,\n bytes memory snapPayload,\n bytes memory snapSignature\n ) external returns (bool wasAccepted) {\n // This will revert if payload is not a snapshot\n Snapshot snapshot = snapPayload.castToSnapshot();\n // This will revert if the snapshot signer is not a known Notary\n (AgentStatus memory notaryStatus,) =\n _verifySnapshot({snapshot: snapshot, snapSignature: snapSignature, verifyNotary: true});\n // Notary needs to be Active/Unstaking\n notaryStatus.verifyActiveUnstaking();\n // Check if Notary is active on this chain\n _verifyNotaryDomain(notaryStatus.domain);\n // This will revert if state index is out of range\n State state = snapshot.state(stateIndex);\n // This will revert if the report signer is not an known Guard\n (AgentStatus memory guardStatus,) = _verifyStateReport(state, srSignature);\n // Check that Guard is active\n guardStatus.verifyActive();\n _saveReport(state.unwrap().clone(), srSignature);\n // This will revert if either actor is already in dispute\n IAgentManager(agentManager).openDispute(guardStatus.index, notaryStatus.index);\n return true;\n }\n\n /// @inheritdoc IStatementInbox\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 // This will revert if payload is not a snapshot\n Snapshot snapshot = snapPayload.castToSnapshot();\n // This will revert if state index is out of range\n State state = snapshot.state(stateIndex);\n // This will revert if the report signer is not an known Guard\n (AgentStatus memory guardStatus,) = _verifyStateReport(state, srSignature);\n // Check that Guard is active\n guardStatus.verifyActive();\n // This will revert if payload is not an attestation\n Attestation att = attPayload.castToAttestation();\n // This will revert if signer is not an known Notary\n (AgentStatus memory notaryStatus,) = _verifyAttestation(att, attSignature);\n // Notary needs to be Active/Unstaking\n notaryStatus.verifyActiveUnstaking();\n // Check if Notary is active on this chain\n _verifyNotaryDomain(notaryStatus.domain);\n if (snapshot.calculateRoot() != att.snapRoot()) revert IncorrectSnapshotRoot();\n _saveReport(state.unwrap().clone(), srSignature);\n // This will revert if either actor is already in dispute\n IAgentManager(agentManager).openDispute(guardStatus.index, notaryStatus.index);\n return true;\n }\n\n /// @inheritdoc IStatementInbox\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 // This will revert if payload is not a state\n State state = statePayload.castToState();\n // This will revert if the report signer is not an known Guard\n (AgentStatus memory guardStatus,) = _verifyStateReport(state, srSignature);\n // Check that Guard is active\n guardStatus.verifyActive();\n // This will revert if payload is not an attestation\n Attestation att = attPayload.castToAttestation();\n // This will revert if signer is not a known Notary\n (AgentStatus memory notaryStatus,) = _verifyAttestation(att, attSignature);\n // Notary needs to be Active/Unstaking\n notaryStatus.verifyActiveUnstaking();\n // Check if Notary is active on this chain\n _verifyNotaryDomain(notaryStatus.domain);\n // This will revert if any of these is true:\n // - Attestation root is not equal to Merkle Root derived from State and Snapshot Proof.\n // - Snapshot Proof's first element does not match the State metadata.\n // - Snapshot Proof length exceeds Snapshot tree Height.\n // - State index is out of range.\n _verifySnapshotMerkle(att, stateIndex, state, snapProof);\n _saveReport(statePayload, srSignature);\n // This will revert if either actor is already in dispute\n IAgentManager(agentManager).openDispute(guardStatus.index, notaryStatus.index);\n return true;\n }\n\n // ══════════════════════════════════════════ VERIFY AGENT STATEMENTS ══════════════════════════════════════════════\n\n /// @inheritdoc IStatementInbox\n function verifyReceipt(bytes memory rcptPayload, bytes memory rcptSignature)\n external\n returns (bool isValidReceipt)\n {\n // This will revert if payload is not a receipt\n Receipt rcpt = rcptPayload.castToReceipt();\n // This will revert if the attestation signer is not a known Notary\n (AgentStatus memory status, address notary) = _verifyReceipt(rcpt, rcptSignature);\n // Notary needs to be Active/Unstaking\n status.verifyActiveUnstaking();\n isValidReceipt = IExecutionHub(destination).isValidReceipt(rcptPayload);\n if (!isValidReceipt) {\n emit InvalidReceipt(rcptPayload, rcptSignature);\n IAgentManager(agentManager).slashAgent(status.domain, notary, msg.sender);\n }\n }\n\n /// @inheritdoc IStatementInbox\n function verifyReceiptReport(bytes memory rcptPayload, bytes memory rrSignature)\n external\n returns (bool isValidReport)\n {\n // This will revert if payload is not a receipt\n Receipt rcpt = rcptPayload.castToReceipt();\n // This will revert if the report signer is not a known Guard\n (AgentStatus memory status, address guard) = _verifyReceiptReport(rcpt, rrSignature);\n // Guard needs to be Active/Unstaking\n status.verifyActiveUnstaking();\n // Report is valid IF AND ONLY IF the reported receipt in invalid\n isValidReport = !IExecutionHub(destination).isValidReceipt(rcptPayload);\n if (!isValidReport) {\n emit InvalidReceiptReport(rcptPayload, rrSignature);\n IAgentManager(agentManager).slashAgent(status.domain, guard, msg.sender);\n }\n }\n\n /// @inheritdoc IStatementInbox\n function verifyStateWithAttestation(\n uint8 stateIndex,\n bytes memory snapPayload,\n bytes memory attPayload,\n bytes memory attSignature\n ) external returns (bool isValidState) {\n // This will revert if payload is not an attestation\n Attestation att = attPayload.castToAttestation();\n // This will revert if the attestation signer is not a known Notary\n (AgentStatus memory status, address notary) = _verifyAttestation(att, attSignature);\n // Notary needs to be Active/Unstaking\n status.verifyActiveUnstaking();\n // This will revert if payload is not a snapshot\n Snapshot snapshot = snapPayload.castToSnapshot();\n if (snapshot.calculateRoot() != att.snapRoot()) revert IncorrectSnapshotRoot();\n // This will revert if state does not refer to this chain\n bytes memory statePayload = snapshot.state(stateIndex).unwrap().clone();\n isValidState = IStateHub(origin).isValidState(statePayload);\n if (!isValidState) {\n emit InvalidStateWithAttestation(stateIndex, statePayload, attPayload, attSignature);\n IAgentManager(agentManager).slashAgent(status.domain, notary, msg.sender);\n }\n }\n\n /// @inheritdoc IStatementInbox\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 // This will revert if payload is not an attestation\n Attestation att = attPayload.castToAttestation();\n // This will revert if the attestation signer is not a known Notary\n (AgentStatus memory status, address notary) = _verifyAttestation(att, attSignature);\n // Notary needs to be Active/Unstaking\n status.verifyActiveUnstaking();\n // This will revert if payload is not a state\n State state = statePayload.castToState();\n // This will revert if any of these is true:\n // - Attestation root is not equal to Merkle Root derived from State and Snapshot Proof.\n // - Snapshot Proof's first element does not match the State metadata.\n // - Snapshot Proof length exceeds Snapshot tree Height.\n // - State index is out of range.\n _verifySnapshotMerkle(att, stateIndex, state, snapProof);\n // This will revert if state does not refer to this chain\n isValidState = IStateHub(origin).isValidState(statePayload);\n if (!isValidState) {\n emit InvalidStateWithAttestation(stateIndex, statePayload, attPayload, attSignature);\n IAgentManager(agentManager).slashAgent(status.domain, notary, msg.sender);\n }\n }\n\n /// @inheritdoc IStatementInbox\n function verifyStateWithSnapshot(uint8 stateIndex, bytes memory snapPayload, bytes memory snapSignature)\n external\n returns (bool isValidState)\n {\n // This will revert if payload is not a snapshot\n Snapshot snapshot = snapPayload.castToSnapshot();\n // This will revert if the snapshot signer is not a known Guard/Notary\n (AgentStatus memory status, address agent) =\n _verifySnapshot({snapshot: snapshot, snapSignature: snapSignature, verifyNotary: false});\n // Agent needs to be Active/Unstaking\n status.verifyActiveUnstaking();\n // This will revert if state does not refer to this chain\n isValidState = IStateHub(origin).isValidState(snapshot.state(stateIndex).unwrap().clone());\n if (!isValidState) {\n emit InvalidStateWithSnapshot(stateIndex, snapPayload, snapSignature);\n IAgentManager(agentManager).slashAgent(status.domain, agent, msg.sender);\n }\n }\n\n /// @inheritdoc IStatementInbox\n function verifyStateReport(bytes memory statePayload, bytes memory srSignature)\n external\n returns (bool isValidReport)\n {\n // This will revert if payload is not a state\n State state = statePayload.castToState();\n // This will revert if the report signer is not a known Guard\n (AgentStatus memory status, address guard) = _verifyStateReport(state, srSignature);\n // Guard needs to be Active/Unstaking\n status.verifyActiveUnstaking();\n // Report is valid IF AND ONLY IF the reported state in invalid\n // This will revert if the reported state does not refer to this chain\n isValidReport = !IStateHub(origin).isValidState(statePayload);\n if (!isValidReport) {\n emit InvalidStateReport(statePayload, srSignature);\n IAgentManager(agentManager).slashAgent(status.domain, guard, msg.sender);\n }\n }\n\n // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════\n\n /// @inheritdoc IStatementInbox\n function getReportsAmount() external view returns (uint256) {\n return _storedReports.length;\n }\n\n /// @inheritdoc IStatementInbox\n function getGuardReport(uint256 index)\n external\n view\n returns (bytes memory statementPayload, bytes memory reportSignature)\n {\n if (index \u003e= _storedReports.length) revert IndexOutOfRange();\n StoredReport memory storedReport = _storedReports[index];\n statementPayload = storedReport.statementPayload;\n reportSignature = _storedSignatures[storedReport.sigIndex];\n }\n\n /// @inheritdoc IStatementInbox\n function getStoredSignature(uint256 index) external view returns (bytes memory) {\n return _storedSignatures[index];\n }\n\n // ══════════════════════════════════════════════ INTERNAL LOGIC ═══════════════════════════════════════════════════\n\n /// @dev Saves the statement reported by Guard as invalid and the Guard Report signature.\n function _saveReport(bytes memory statementPayload, bytes memory reportSignature) internal {\n uint256 sigIndex = _saveSignature(reportSignature);\n _storedReports.push(StoredReport(sigIndex, statementPayload));\n }\n\n /// @dev Saves the signature and returns its index.\n function _saveSignature(bytes memory signature) internal returns (uint256 sigIndex) {\n sigIndex = _storedSignatures.length;\n _storedSignatures.push(signature);\n }\n\n // ═══════════════════════════════════════════════ AGENT CHECKS ════════════════════════════════════════════════════\n\n /**\n * @dev Recovers a signer from a hashed message, and a EIP-191 signature for it.\n * Will revert, if the signer is not a known agent.\n * @dev Agent flag could be any of these: Active/Unstaking/Resting/Fraudulent/Slashed\n * Further checks need to be performed in a caller function.\n * @param hashedStatement Hash of the statement that was signed by an Agent\n * @param signature Agent signature for the hashed statement\n * @return status Struct representing agent status:\n * - flag Unknown/Active/Unstaking/Resting/Fraudulent/Slashed\n * - domain Domain where agent is/was active\n * - index Index of agent in the Agent Merkle Tree\n * @return agent Agent that signed the statement\n */\n function _recoverAgent(bytes32 hashedStatement, bytes memory signature)\n internal\n view\n returns (AgentStatus memory status, address agent)\n {\n bytes32 ethSignedMsg = ECDSA.toEthSignedMessageHash(hashedStatement);\n agent = ECDSA.recover(ethSignedMsg, signature);\n status = IAgentManager(agentManager).agentStatus(agent);\n // Discard signature of unknown agents.\n // Further flag checks are supposed to be performed in a caller function.\n status.verifyKnown();\n }\n\n /// @dev Verifies that Notary signature is active on local domain.\n function _verifyNotaryDomain(uint32 notaryDomain) internal view {\n // Notary needs to be from the local domain (if contract is not deployed on Synapse Chain).\n // Or Notary could be from any domain (if contract is deployed on Synapse Chain).\n if (notaryDomain != localDomain \u0026\u0026 localDomain != synapseDomain) revert IncorrectAgentDomain();\n }\n\n // ════════════════════════════════════════ ATTESTATION RELATED CHECKS ═════════════════════════════════════════════\n\n /**\n * @dev Internal function to verify the signed attestation payload.\n * Reverts if any of these is true:\n * - Attestation signer is not a known Notary.\n * @param att Typed memory view over attestation payload\n * @param attSignature Notary signature for the attestation\n * @return status Struct representing agent status, see {_recoverAgent}\n * @return notary Notary that signed the snapshot\n */\n function _verifyAttestation(Attestation att, bytes memory attSignature)\n internal\n view\n returns (AgentStatus memory status, address notary)\n {\n // This will revert if signer is not a known agent\n (status, notary) = _recoverAgent(att.hashValid(), attSignature);\n // Attestation signer needs to be a Notary, not a Guard\n if (status.domain == 0) revert AgentNotNotary();\n }\n\n /**\n * @dev Internal function to verify the signed attestation report payload.\n * Reverts if any of these is true:\n * - Report signer is not a known Guard.\n * @param att Typed memory view over attestation payload that Guard reports as invalid\n * @param arSignature Guard signature for the \"invalid attestation\" report\n * @return status Struct representing guard status, see {_recoverAgent}\n * @return guard Guard that signed the report\n */\n function _verifyAttestationReport(Attestation att, bytes memory arSignature)\n internal\n view\n returns (AgentStatus memory status, address guard)\n {\n // This will revert if signer is not a known agent\n (status, guard) = _recoverAgent(att.hashInvalid(), arSignature);\n // Report signer needs to be a Guard, not a Notary\n if (status.domain != 0) revert AgentNotGuard();\n }\n\n // ══════════════════════════════════════════ RECEIPT RELATED CHECKS ═══════════════════════════════════════════════\n\n /**\n * @dev Internal function to verify the signed receipt payload.\n * Reverts if any of these is true:\n * - Receipt signer is not a known Notary.\n * @param rcpt Typed memory view over receipt payload\n * @param rcptSignature Notary signature for the receipt\n * @return status Struct representing agent status, see {_recoverAgent}\n * @return notary Notary that signed the snapshot\n */\n function _verifyReceipt(Receipt rcpt, bytes memory rcptSignature)\n internal\n view\n returns (AgentStatus memory status, address notary)\n {\n // This will revert if signer is not a known agent\n (status, notary) = _recoverAgent(rcpt.hashValid(), rcptSignature);\n // Receipt signer needs to be a Notary, not a Guard\n if (status.domain == 0) revert AgentNotNotary();\n }\n\n /**\n * @dev Internal function to verify the signed receipt report payload.\n * Reverts if any of these is true:\n * - Report signer is not a known Guard.\n * @param rcpt Typed memory view over receipt payload that Guard reports as invalid\n * @param rrSignature Guard signature for the \"invalid receipt\" report\n * @return status Struct representing guard status, see {_recoverAgent}\n * @return guard Guard that signed the report\n */\n function _verifyReceiptReport(Receipt rcpt, bytes memory rrSignature)\n internal\n view\n returns (AgentStatus memory status, address guard)\n {\n // This will revert if signer is not a known agent\n (status, guard) = _recoverAgent(rcpt.hashInvalid(), rrSignature);\n // Report signer needs to be a Guard, not a Notary\n if (status.domain != 0) revert AgentNotGuard();\n }\n\n // ═══════════════════════════════════════ STATE/SNAPSHOT RELATED CHECKS ═══════════════════════════════════════════\n\n /**\n * @dev Internal function to verify the signed snapshot report payload.\n * Reverts if any of these is true:\n * - Report signer is not a known Guard.\n * @param state Typed memory view over state payload that Guard reports as invalid\n * @param srSignature Guard signature for the report\n * @return status Struct representing guard status, see {_recoverAgent}\n * @return guard Guard that signed the report\n */\n function _verifyStateReport(State state, bytes memory srSignature)\n internal\n view\n returns (AgentStatus memory status, address guard)\n {\n // This will revert if signer is not a known agent\n (status, guard) = _recoverAgent(state.hashInvalid(), srSignature);\n // Report signer needs to be a Guard, not a Notary\n if (status.domain != 0) revert AgentNotGuard();\n }\n\n /**\n * @dev Internal function to verify the signed snapshot payload.\n * Reverts if any of these is true:\n * - Snapshot signer is not a known Agent.\n * - Snapshot signer is not a Notary (if verifyNotary is true).\n * @param snapshot Typed memory view over snapshot payload\n * @param snapSignature Agent signature for the snapshot\n * @param verifyNotary If true, snapshot signer needs to be a Notary, not a Guard\n * @return status Struct representing agent status, see {_recoverAgent}\n * @return agent Agent that signed the snapshot\n */\n function _verifySnapshot(Snapshot snapshot, bytes memory snapSignature, bool verifyNotary)\n internal\n view\n returns (AgentStatus memory status, address agent)\n {\n // This will revert if signer is not a known agent\n (status, agent) = _recoverAgent(snapshot.hashValid(), snapSignature);\n // If requested, snapshot signer needs to be a Notary, not a Guard\n if (verifyNotary \u0026\u0026 status.domain == 0) revert AgentNotNotary();\n }\n\n // ═══════════════════════════════════════════ MERKLE RELATED CHECKS ═══════════════════════════════════════════════\n\n /**\n * @dev Internal function to verify that snapshot roots match.\n * Reverts if any of these is true:\n * - Attestation root is not equal to Merkle Root derived from State and Snapshot Proof.\n * - Snapshot Proof's first element does not match the State metadata.\n * - Snapshot Proof length exceeds Snapshot tree Height.\n * - State index is out of range.\n * @param att Typed memory view over Attestation\n * @param stateIndex Index of state in the snapshot\n * @param state Typed memory view over the provided state payload\n * @param snapProof Raw payload with snapshot data\n */\n function _verifySnapshotMerkle(Attestation att, uint8 stateIndex, State state, bytes32[] memory snapProof)\n internal\n pure\n {\n // Snapshot proof first element should match State metadata (aka \"right sub-leaf\")\n (, bytes32 rightSubLeaf) = state.subLeafs();\n if (snapProof[0] != rightSubLeaf) revert IncorrectSnapshotProof();\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(state.root(), state.origin(), snapProof, stateIndex);\n // Snapshot root should match the attestation root\n if (att.snapRoot() != snapshotRoot) revert IncorrectSnapshotRoot();\n }\n}\n\n// contracts/inbox/Inbox.sol\n\n// ══════════════════════════════ LIBRARY IMPORTS ══════════════════════════════\n\n// ═════════════════════════════ INTERNAL IMPORTS ══════════════════════════════\n\n/// @notice `Inbox` is the child of `StatementInbox` contract, that is used on Synapse Chain.\n/// In addition to the functionality of `StatementInbox`, it also:\n/// - Accepts Guard and Notary Snapshots and passes them to `Summit` contract.\n/// - Accepts Notary-signed Receipts and passes them to `Summit` contract.\n/// - Accepts Receipt Reports to initiate a dispute between Guard and Notary.\n/// - Verifies Attestations and Attestation Reports, and slashes the signer if they are invalid.\ncontract Inbox is StatementInbox, InboxEvents, InterfaceInbox {\n using AttestationLib for bytes;\n using ReceiptLib for bytes;\n using SnapshotLib for bytes;\n\n // Struct to get around stack too deep error. TODO: revisit this\n struct ReceiptInfo {\n AgentStatus rcptNotaryStatus;\n address notary;\n uint32 attNonce;\n AgentStatus attNotaryStatus;\n }\n\n // ══════════════════════════════════════════════════ STORAGE ══════════════════════════════════════════════════════\n\n // The address of the Summit contract.\n address public summit;\n\n // ═════════════════════════════════════════ CONSTRUCTOR \u0026 INITIALIZER ═════════════════════════════════════════════\n\n constructor(uint32 synapseDomain_) MessagingBase(\"0.0.3\", synapseDomain_) {\n if (localDomain != synapseDomain) revert MustBeSynapseDomain();\n }\n\n /// @notice Initializes `Inbox` contract:\n /// - Sets `msg.sender` as the owner of the contract\n /// - Sets `agentManager`, `origin`, `destination` and `summit` addresses\n function initialize(address agentManager_, address origin_, address destination_, address summit_)\n external\n initializer\n {\n __StatementInbox_init(agentManager_, origin_, destination_);\n summit = summit_;\n }\n\n // ══════════════════════════════════════════ SUBMIT AGENT STATEMENTS ══════════════════════════════════════════════\n\n /// @inheritdoc InterfaceInbox\n function submitSnapshot(bytes memory snapPayload, bytes memory snapSignature)\n external\n returns (bytes memory attPayload, bytes32 agentRoot_, uint256[] memory snapGas)\n {\n // This will revert if payload is not a snapshot\n Snapshot snapshot = snapPayload.castToSnapshot();\n // This will revert if the signer is not a known Guard/Notary\n (AgentStatus memory status, address agent) =\n _verifySnapshot({snapshot: snapshot, snapSignature: snapSignature, verifyNotary: false});\n // Check that Agent is active\n status.verifyActive();\n // Store Agent signature for the Snapshot\n uint256 sigIndex = _saveSignature(snapSignature);\n if (status.domain == 0) {\n // Guard that is in Dispute could still submit new snapshots, so we don't check that\n InterfaceSummit(summit).acceptGuardSnapshot({\n guardIndex: status.index,\n sigIndex: sigIndex,\n snapPayload: snapPayload\n });\n } else {\n // Get current agentRoot from AgentManager\n agentRoot_ = IAgentManager(agentManager).agentRoot();\n // This will revert if Notary is in Dispute\n attPayload = InterfaceSummit(summit).acceptNotarySnapshot({\n notaryIndex: status.index,\n sigIndex: sigIndex,\n agentRoot: agentRoot_,\n snapPayload: snapPayload\n });\n ChainGas[] memory snapGas_ = snapshot.snapGas();\n // Pass created attestation to Destination to enable executing messages coming to Synapse Chain\n InterfaceDestination(destination).acceptAttestation(\n status.index, type(uint256).max, attPayload, agentRoot_, snapGas_\n );\n // Use assembly to cast ChainGas[] to uint256[] without copying. Highest bits are left zeroed.\n // solhint-disable-next-line no-inline-assembly\n assembly {\n snapGas := snapGas_\n }\n }\n emit SnapshotAccepted(status.domain, agent, snapPayload, snapSignature);\n }\n\n /// @inheritdoc InterfaceInbox\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 // Struct to get around stack too deep error.\n ReceiptInfo memory info;\n // This will revert if payload is not a receipt\n Receipt rcpt = rcptPayload.castToReceipt();\n // This will revert if the receipt signer is not a known Notary\n (info.rcptNotaryStatus, info.notary) = _verifyReceipt(rcpt, rcptSignature);\n // Receipt Notary needs to be Active\n info.rcptNotaryStatus.verifyActive();\n info.attNonce = IExecutionHub(destination).getAttestationNonce(rcpt.snapshotRoot());\n if (info.attNonce == 0) revert IncorrectSnapshotRoot();\n // Attestation Notary domain needs to match the destination domain\n info.attNotaryStatus = IAgentManager(agentManager).agentStatus(rcpt.attNotary());\n if (info.attNotaryStatus.domain != rcpt.destination()) revert IncorrectAgentDomain();\n // Check that the correct tip values for the message were provided\n _verifyReceiptTips(rcpt.messageHash(), paddedTips, headerHash, bodyHash);\n // Store Notary signature for the Receipt\n uint256 sigIndex = _saveSignature(rcptSignature);\n // This will revert if Receipt Notary is in Dispute\n wasAccepted = InterfaceSummit(summit).acceptReceipt({\n rcptNotaryIndex: info.rcptNotaryStatus.index,\n attNotaryIndex: info.attNotaryStatus.index,\n sigIndex: sigIndex,\n attNonce: info.attNonce,\n paddedTips: paddedTips,\n rcptPayload: rcptPayload\n });\n if (wasAccepted) {\n emit ReceiptAccepted(info.rcptNotaryStatus.domain, info.notary, rcptPayload, rcptSignature);\n }\n }\n\n /// @inheritdoc InterfaceInbox\n function submitReceiptReport(bytes memory rcptPayload, bytes memory rcptSignature, bytes memory rrSignature)\n external\n returns (bool wasAccepted)\n {\n // This will revert if payload is not a receipt\n Receipt rcpt = rcptPayload.castToReceipt();\n // This will revert if the receipt signer is not a known Guard\n (AgentStatus memory guardStatus,) = _verifyReceiptReport(rcpt, rrSignature);\n // Guard needs to be Active\n guardStatus.verifyActive();\n // This will revert if report signer is not a known Notary\n (AgentStatus memory notaryStatus,) = _verifyReceipt(rcpt, rcptSignature);\n // Notary needs to be Active/Unstaking\n notaryStatus.verifyActiveUnstaking();\n _saveReport(rcptPayload, rrSignature);\n // This will revert if either actor is already in dispute\n IAgentManager(agentManager).openDispute(guardStatus.index, notaryStatus.index);\n return true;\n }\n\n /// @inheritdoc InterfaceInbox\n function passReceipt(uint32 attNotaryIndex, uint32 attNonce, uint256 paddedTips, bytes memory rcptPayload)\n external\n returns (bool wasAccepted)\n {\n // Only Destination can pass receipts\n if (msg.sender != destination) revert CallerNotDestination();\n return InterfaceSummit(summit).acceptReceipt({\n rcptNotaryIndex: attNotaryIndex,\n attNotaryIndex: attNotaryIndex,\n sigIndex: type(uint256).max,\n attNonce: attNonce,\n paddedTips: paddedTips,\n rcptPayload: rcptPayload\n });\n }\n\n // ══════════════════════════════════════════ VERIFY AGENT STATEMENTS ══════════════════════════════════════════════\n\n /// @inheritdoc InterfaceInbox\n function verifyAttestation(bytes memory attPayload, bytes memory attSignature)\n external\n returns (bool isValidAttestation)\n {\n // This will revert if payload is not an attestation\n Attestation att = attPayload.castToAttestation();\n // This will revert if the attestation signer is not a known Notary\n (AgentStatus memory status, address notary) = _verifyAttestation(att, attSignature);\n // Notary needs to be Active/Unstaking\n status.verifyActiveUnstaking();\n isValidAttestation = ISnapshotHub(summit).isValidAttestation(attPayload);\n if (!isValidAttestation) {\n emit InvalidAttestation(attPayload, attSignature);\n IAgentManager(agentManager).slashAgent(status.domain, notary, msg.sender);\n }\n }\n\n /// @inheritdoc InterfaceInbox\n function verifyAttestationReport(bytes memory attPayload, bytes memory arSignature)\n external\n returns (bool isValidReport)\n {\n // This will revert if payload is not an attestation\n Attestation att = attPayload.castToAttestation();\n // This will revert if the report signer is not a known Guard\n (AgentStatus memory status, address guard) = _verifyAttestationReport(att, arSignature);\n // Guard needs to be Active/Unstaking\n status.verifyActiveUnstaking();\n // Report is valid IF AND ONLY IF the reported attestation in invalid\n isValidReport = !ISnapshotHub(summit).isValidAttestation(attPayload);\n if (!isValidReport) {\n emit InvalidAttestationReport(attPayload, arSignature);\n IAgentManager(agentManager).slashAgent(status.domain, guard, msg.sender);\n }\n }\n\n // ══════════════════════════════════════════════ INTERNAL VIEWS ═══════════════════════════════════════════════════\n\n /// @dev Verifies that tips proof matches the message hash.\n function _verifyReceiptTips(bytes32 msgHash, uint256 paddedTips, bytes32 headerHash, bytes32 bodyHash)\n internal\n pure\n {\n Tips tips = TipsLib.wrapPadded(paddedTips);\n // full message leaf is (header, baseMessage), while base message leaf is (tips, remainingBody).\n if (MerkleMath.getParent(headerHash, MerkleMath.getParent(tips.leaf(), bodyHash)) != msgHash) {\n revert IncorrectTipsProof();\n }\n }\n}\n","language":"Solidity","languageVersion":"0.8.17","compilerVersion":"0.8.17","compilerOptions":"--combined-json bin,bin-runtime,srcmap,srcmap-runtime,abi,userdoc,devdoc,metadata,hashes --optimize --optimize-runs 10000 --allow-paths ., ./, ../","srcMap":"277015:10607:0:-:0;;;278105:153;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;248145:172;;;;;;;;;;;;;-1:-1:-1;;;248145:172:0;;;;108646:32;;278163:14;248145:172;108912:24;108926:8;108912:24;:::i;:::-;108904:32;;;;;;108600:343;248248:22:::1;:20;;;;;:22;;:::i;:::-;248234:36;::::0;;::::1;;::::0;;;248280:30;::::1;;::::0;;;278193:28:::1;::::0;-1:-1:-1;278189:62:0::1;;278230:21;;-1:-1:-1::0;;;278230:21:0::1;;;;;;;;;;;278189:62;278105:153:::0;277015:10607;;110487:98;110529:6;110554:24;:13;:22;;;;;:24;;:::i;:::-;110547:31;;110487:98;:::o;75334:187::-;75390:6;75425:16;75416:25;;;75408:76;;;;-1:-1:-1;;;75408:76:0;;803:2:1;75408:76:0;;;785:21:1;842:2;822:18;;;815:30;881:34;861:18;;;854:62;-1:-1:-1;;;932:18:1;;;925:36;978:19;;75408:76:0;;;;;;;;-1:-1:-1;75508:5:0;75334:187::o;14:280:1:-;83:6;136:2;124:9;115:7;111:23;107:32;104:52;;;152:1;149;142:12;104:52;184:9;178:16;234:10;227:5;223:22;216:5;213:33;203:61;;260:1;257;250:12;203:61;283:5;14:280;-1:-1:-1;;;14:280:1:o;299:297::-;417:12;;464:4;453:16;;;447:23;;417:12;482:16;;479:111;;;576:1;572:6;562;556:4;552:17;549:1;545:25;541:38;534:5;530:50;521:59;;479:111;;299:297;;;:::o;601:402::-;277015:10607:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;","srcMapRuntime":"277015:10607:0:-:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;285065:801;;;;;;:::i;:::-;;:::i;:::-;;;1968:14:1;;1961:22;1943:41;;1931:2;1916:18;285065:801:0;;;;;;;;253594:1485;;;;;;:::i;:::-;;:::i;285907:871::-;;;;;;:::i;:::-;;:::i;252235:1317::-;;;;;;:::i;:::-;;:::i;279026:2138::-;;;;;;:::i;:::-;;:::i;:::-;;;;;;;;;:::i;108949:401::-;109120:28;;;;;;;;;109133:7;109120:28;;109142:5;109120:28;;;;108949:401;;;;;;;:::i;106296:1352::-;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;284138:588::-;;;;;;:::i;:::-;;:::i;248542:57::-;;;:::i;:::-;;247660:37;;;;;;;;8344:10:1;8332:23;;;8314:42;;8302:2;8287:18;247660:37:0;8170:192:1;264000:105:0;264077:14;:21;264000:105;;8513:25:1;;;8501:2;8486:18;264000:105:0;8367:177:1;250722:27:0;;;;;-1:-1:-1;;;;;250722:27:0;;;;;;-1:-1:-1;;;;;8713:55:1;;;8695:74;;8683:2;8668:18;250722:27:0;8549:226:1;226274:212:0;;;:::i;258881:1232::-;;;;;;:::i;:::-;;:::i;261694:978::-;;;;;;:::i;:::-;;:::i;283125:972::-;;;;;;:::i;:::-;;:::i;247543:35::-;;;;;222605:85;222677:6;;-1:-1:-1;;;;;222677:6:0;222605:85;;257989:850;;;;;;:::i;:::-;;:::i;250755:21::-;;;;;-1:-1:-1;;;;;250755:21:0;;;277783;;;;;-1:-1:-1;;;;;277783:21:0;;;250782:26;;;;;-1:-1:-1;;;;;250782:26:0;;;281205:1879;;;;;;:::i;:::-;;:::i;255121:1711::-;;;;;;:::i;:::-;;:::i;257172:775::-;;;;;;:::i;:::-;;:::i;264147:420::-;;;;;;:::i;:::-;;:::i;:::-;;;;;;;;:::i;264609:128::-;;;;;;:::i;:::-;;:::i;262714:910::-;;;;;;:::i;:::-;;:::i;260155:1497::-;;;;;;:::i;:::-;;:::i;225387:99::-;225466:13;;-1:-1:-1;;;;;225466:13:0;225387:99;;225679:178;;;;;;:::i;:::-;;:::i;278445:242::-;;;;;;:::i;:::-;;:::i;285065:801::-;285178:23;285278:15;285296:30;:10;:28;:30::i;:::-;285278:48;;285413:25;285440:14;285458:37;285477:3;285482:12;285458:18;:37::i;:::-;285412:83;;;;285552:30;:6;:28;:30::i;:::-;285626:6;;285613:51;;;;;-1:-1:-1;;;;;285626:6:0;;;;285613:39;;:51;;285653:10;;285613:51;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;285592:72;;285679:18;285674:186;;285718:44;285737:10;285749:12;285718:44;;;;;;;:::i;:::-;;;;;;;;285790:12;;285815:13;;;;285776:73;;;;;15989:10:1;15977:23;;;285776:73:0;;;15959:42:1;-1:-1:-1;;;;;16098:15:1;;;16078:18;;;16071:43;285838:10:0;16130:18:1;;;16123:43;285790:12:0;;;;285776:38;;15932:18:1;;285776:73:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;285674:186;285207:659;;;285065:801;;;;:::o;253594:1485::-;253822:16;253907:17;253927:28;:11;:26;:28::i;:::-;253907:48;-1:-1:-1;254024:11:0;254038:26;253907:48;254038:26;;;:14;:26::i;:::-;254024:40;;254146:30;254181:38;254200:5;254207:11;254181:18;:38::i;:::-;254145:74;;;254267:26;:11;:24;:26::i;:::-;254364:15;254382:30;:10;:28;:30::i;:::-;254364:48;;254484:31;254520:37;254539:3;254544:12;254520:18;:37::i;:::-;254483:74;;;254614:36;:12;:34;:36::i;:::-;254711:40;254731:12;:19;;;254711;:40::i;:::-;254793:14;:3;:12;:14::i;:::-;254765:24;:8;:22;:24::i;:::-;:42;254761:78;;254816:23;;;;;;;;;;;;;;254761:78;254849:48;254861:22;:5;:20;:22::i;:14::-;:20;:22::i;:::-;254885:11;254849;:48::i;:::-;254987:12;;255013:17;;;;;255032:18;;;;254973:78;;;;;16357:10:1;16394:15;;;254973:78:0;;;16376:34:1;16446:15;;16426:18;;;16419:43;-1:-1:-1;;;;;254987:12:0;;;;254973:39;;16320:18:1;;254973:78:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;255068:4:0;;253594:1485;-1:-1:-1;;;;;;;;;;;;;;253594:1485:0:o;285907:871::-;286025:18;286120:15;286138:30;:10;:28;:30::i;:::-;286120:48;;286249:25;286276:13;286293:42;286318:3;286323:11;286293:24;:42::i;:::-;286248:87;;;;286391:30;:6;:28;:30::i;:::-;286539:6;;286526:51;;;;;-1:-1:-1;;;;;286539:6:0;;;;286526:39;;:51;;286566:10;;286526:51;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;286525:52;286509:68;;286592:13;286587:185;;286626:49;286651:10;286663:11;286626:49;;;;;;;:::i;252235:1317::-;252428:16;252513:17;252533:28;:11;:26;:28::i;:::-;252513:48;;252645:31;252693:87;252720:8;252745:13;252774:4;252693:15;:87::i;:::-;252644:136;;;252837:36;:12;:34;:36::i;:::-;252934:40;252954:12;:19;;;252934;:40::i;:::-;253043:11;253057:26;:8;:26;;;:14;:26::i;:::-;253043:40;;253165:30;253200:38;253219:5;253226:11;253200:18;:38::i;:::-;253164:74;;;253286:26;:11;:24;:26::i;:::-;253322:48;253334:22;:5;254861:20;:22::i;253334:::-;253358:11;253322;:48::i;:::-;253460:12;;253486:17;;;;;253505:18;;;;253446:78;;;;;16357:10:1;16394:15;;;253446:78:0;;;16376:34:1;16446:15;;16426:18;;;16419:43;-1:-1:-1;;;;;253460:12:0;;;;253446:39;;16320:18:1;;253446:78:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;253541:4;253534:11;;;;;;252235:1317;;;;;;;:::o;279026:2138::-;279138:23;279163:18;279183:24;279280:17;279300:28;:11;:26;:28::i;:::-;279280:48;;279409:25;279436:13;279465:88;279492:8;279517:13;279546:5;279465:15;:88::i;:::-;279408:145;;;;279601:21;:6;:19;:21::i;:::-;279682:16;279701:29;279716:13;279701:14;:29::i;:::-;279682:48;;279744:6;:13;;;:18;;279761:1;279744:18;279740:1337;;279891:6;;279949:12;;;;;279875:179;;;;;-1:-1:-1;;;;;279891:6:0;;;;279875:43;;:179;;279989:8;;280028:11;;279875:179;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;279740:1337;;;280167:12;;;;;;;;;-1:-1:-1;;;;;280167:12:0;-1:-1:-1;;;;;280153:37:0;;:39;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;280291:6;;280351:12;;;;;280275:220;;;;;280140:52;;-1:-1:-1;;;;;;280291:6:0;;;;280275:44;;:220;;280391:8;;280140:52;;280469:11;;280275:220;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;280275:220:0;;;;;;;;;;;;:::i;:::-;280262:233;;280509:26;280538:18;:8;:16;:18::i;:::-;280699:11;;280747:12;;;;;280678:148;;;;;280509:47;;-1:-1:-1;;;;;;280699:11:0;;;;280678:51;;:148;;-1:-1:-1;;280761:17:0;280780:10;;280792;;280509:47;;280678:148;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1;281045:8:0;-1:-1:-1;279740:1337:0;281123:5;-1:-1:-1;;;;;281091:66:0;281108:6;:13;;;281091:66;;;281130:11;281143:13;281091:66;;;;;;;:::i;:::-;;;;;;;;279213:1951;;;;279026:2138;;;;;:::o;106296:1352::-;106356:27;106412:5;;106448:20;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;;;;;;;;;;;;;106448:20:0;;;;;;;;;;;;;;;;106434:34;;106478:19;106512:9;106507:1135;106531:6;106527:1;:10;106507:1135;;;106562:5;;106568:1;106562:8;;;;;;;:::i;:::-;;;;;;;;;;;;:::i;:::-;106554:16;;106584:20;106607:11;106619:1;106607:14;;;;;;;;:::i;:::-;;;;;;;106584:37;;106964:4;-1:-1:-1;;;;;106956:26:0;106983:5;:14;;;;;;;;:::i;:::-;106956:42;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;106935:17:0;;;106918:80;;;;;;107271:19;;107268:38;107258:301;;107435:66;107429:4;107422:80;107536:4;107530;107523:18;107258:301;-1:-1:-1;107614:3:0;;106507:1135;;284138:588;284375:11;;284279:16;;-1:-1:-1;;;;;284375:11:0;284361:10;:25;284357:60;;284395:22;;;;;;;;;;;;;;284357:60;284450:6;;284434:285;;;;;-1:-1:-1;;;;;284450:6:0;;;;284434:37;;:285;;284503:14;;;;-1:-1:-1;;284585:17:0;284626:8;;284660:10;;284697:11;;284434:285;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;284427:292;284138:588;-1:-1:-1;;;;;284138:588:0:o;248542:57::-;222498:13;:11;:13::i;:::-;248542:57::o;226274:212::-;225466:13;;185328:10;;-1:-1:-1;;;;;225466:13:0;226373:24;;226365:78;;;;;;;21479:2:1;226365:78:0;;;21461:21:1;21518:2;21498:18;;;21491:30;21557:34;21537:18;;;21530:62;21628:11;21608:18;;;21601:39;21657:19;;226365:78:0;;;;;;;;;226453:26;226472:6;226453:18;:26::i;:::-;226316:170;226274:212::o;258881:1232::-;259069:17;259159:15;259177:30;:10;:28;:30::i;:::-;259159:48;;259294:25;259321:14;259339:37;259358:3;259363:12;259339:18;:37::i;:::-;259293:83;;;;259433:30;:6;:28;:30::i;:::-;259530:17;259550:28;:11;:26;:28::i;:::-;259530:48;;259620:14;:3;:12;:14::i;:::-;259592:24;:8;:22;:24::i;:::-;:42;259588:78;;259643:23;;;;;;;;;;;;;;259588:78;259742:25;259770:43;:35;:26;:8;:26;;;:14;:26::i;:::-;231435:5;231331:118;259770:43;259848:6;;259838:44;;;;;259742:71;;-1:-1:-1;;;;;;259848:6:0;;259838:30;;:44;;259742:71;;259838:44;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;259823:59;;259897:12;259892:215;;259930:79;259958:10;259970:12;259984:10;259996:12;259930:79;;;;;;;;;:::i;:::-;;;;;;;;260037:12;;260062:13;;;;260023:73;;;;;15989:10:1;15977:23;;;260023:73:0;;;15959:42:1;-1:-1:-1;;;;;16098:15:1;;;16078:18;;;16071:43;260085:10:0;16130:18:1;;;16123:43;260037:12:0;;;;260023:38;;15932:18:1;;260023:73:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;259892:215;259088:1025;;;;;258881:1232;;;;;;:::o;261694:978::-;261833:17;261923;261943:28;:11;:26;:28::i;:::-;261923:48;;262061:25;262088:13;262117:88;262144:8;262169:13;262198:5;262117:15;:88::i;:::-;262060:145;;;;262261:30;:6;:28;:30::i;:::-;262392:6;;-1:-1:-1;;;;;262392:6:0;262382:30;262413:43;:35;:26;:8;:26;;;:14;:26::i;:43::-;262382:75;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;262367:90;;262472:12;262467:199;;262505:64;262530:10;262542:11;262555:13;262505:64;;;;;;;;:::i;:::-;;;;;;;;262597:12;;262622:13;;;;262583:72;;;;;15989:10:1;15977:23;;;262583:72:0;;;15959:42:1;-1:-1:-1;;;;;16098:15:1;;;16078:18;;;16071:43;262644:10:0;16130:18:1;;;16123:43;262597:12:0;;;;262583:38;;15932:18:1;;262583:72:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;262467:199;261856:816;;;261694:978;;;;;:::o;283125:972::-;283268:16;283356:12;283371:27;:11;:25;:27::i;:::-;283356:42;;283480:30;283515:39;283536:4;283542:11;283515:20;:39::i;:::-;283479:75;;;283600:26;:11;:24;:26::i;:::-;283704:31;283740:35;283755:4;283761:13;283740:14;:35::i;:::-;283703:72;;;283832:36;:12;:34;:36::i;:::-;283878:37;283890:11;283903;283878;:37::i;:::-;284005:12;;284031:17;;;;;284050:18;;;;283991:78;;;;;16357:10:1;16394:15;;;283991:78:0;;;16376:34:1;16446:15;;16426:18;;;16419:43;-1:-1:-1;;;;;284005:12:0;;;;283991:39;;16320:18:1;;283991:78:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;284086:4;284079:11;;;;;283125:972;;;;;;:::o;257989:850::-;258104:18;258194:12;258209:27;:11;:25;:27::i;:::-;258194:42;;258317:25;258344:13;258361:39;258382:4;258388:11;258361:20;:39::i;:::-;258316:84;;;;258456:30;:6;:28;:30::i;:::-;258601:11;;258587:54;;;;;-1:-1:-1;;;;;258601:11:0;;;;258587:41;;:54;;258629:11;;258587:54;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;258586:55;258570:71;;258656:13;258651:182;;258690:46;258711:11;258724;258690:46;;;;;;;:::i;281205:1879::-;281404:16;281486:23;;:::i;:::-;281575:12;281590:27;:11;:25;:27::i;:::-;281575:42;;281738:35;281753:4;281759:13;281738:14;:35::i;:::-;-1:-1:-1;;;;;281699:74:0;281723:11;;;281699:74;;;;281828:36;;:34;:36::i;:::-;281904:11;;-1:-1:-1;;;;;281904:11:0;281890:46;281937:19;:4;:17;:19::i;:::-;281890:67;;;;;;;;;;;;;8513:25:1;;8501:2;8486:18;;8367:177;281890:67:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;281874:83;;:13;;;:83;;;281988:1;281971:18;281967:54;;281998:23;;;;;;;;;;;;;;281967:54;282143:12;;-1:-1:-1;;;;;282143:12:0;282129:39;282169:16;:4;:14;:16::i;:::-;282129:57;;;;;;;;;;-1:-1:-1;;;;;8713:55:1;;;282129:57:0;;;8695:74:1;8668:18;;282129:57:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;282106:20;;;:80;282231:18;:4;:16;:18::i;:::-;282200:49;;:4;:20;;;:27;;;:49;;;282196:84;;282258:22;;;;;;;;;;;;;;282196:84;282365:72;282384:18;:4;:16;:18::i;:::-;282404:10;282416;282428:8;282365:18;:72::i;:::-;282497:16;282516:29;282531:13;282516:14;:29::i;:::-;282497:48;;282645:6;;;;;;;;;-1:-1:-1;;;;;282645:6:0;-1:-1:-1;;;;;282629:37:0;;282698:4;:21;;;:27;;;282755:4;:20;;;:26;;;282805:8;282837:4;:13;;;282876:10;282913:11;282629:306;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;282615:320;;282949:11;282945:133;;;282981:86;282997:4;:21;;;:28;;;283027:4;:11;;;283040;283053:13;282981:86;;;;;;;;;:::i;:::-;;;;;;;;282945:133;281422:1662;;;281205:1879;;;;;;;:::o;255121:1711::-;255388:16;255470:11;255484:26;:12;:24;:26::i;:::-;255470:40;;255592:30;255627:38;255646:5;255653:11;255627:18;:38::i;:::-;255591:74;;;255713:26;:11;:24;:26::i;:::-;255810:15;255828:30;:10;:28;:30::i;:::-;255810:48;;255929:31;255965:37;255984:3;255989:12;255965:18;:37::i;:::-;255928:74;;;256059:36;:12;:34;:36::i;:::-;256156:40;256176:12;:19;;;256156;:40::i;:::-;256546:56;256568:3;256573:10;256585:5;256592:9;256546:21;:56::i;:::-;256612:38;256624:12;256638:11;256612;:38::i;257172:775::-;257283:19;257374:12;257389:27;:11;:25;:27::i;:::-;257374:42;;257503:25;257530:14;257548:35;257563:4;257569:13;257548:14;:35::i;:::-;257502:81;;;;257640:30;:6;:28;:30::i;:::-;257711:11;;257697:54;;;;;-1:-1:-1;;;;;257711:11:0;;;;257697:41;;:54;;257739:11;;257697:54;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;257680:71;;257766:14;257761:180;;257801:42;257816:11;257829:13;257801:42;;;;;;;:::i;264147:420::-;264321:14;:21;264233:29;;;;264312:30;;264308:60;;264351:17;;;;;;;;;;;;;;264308:60;264378:32;264413:14;264428:5;264413:21;;;;;;;;:::i;:::-;;;;;;;;;;;264378:56;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;264463:12;:29;;;264444:48;;264520:17;264538:12;:21;;;264520:40;;;;;;;;:::i;:::-;;;;;;;;264502:58;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;264298:269;264147:420;;;:::o;264609:128::-;264675:12;264706:17;264724:5;264706:24;;;;;;;;:::i;:::-;;;;;;;;264699:31;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;264609:128;;;:::o;262714:910::-;262828:18;262916:11;262930:26;:12;:24;:26::i;:::-;262916:40;;263037:25;263064:13;263081:38;263100:5;263107:11;263081:18;:38::i;:::-;263036:83;;;;263175:30;:6;:28;:30::i;:::-;263393:6;;263383:44;;;;;-1:-1:-1;;;;;263393:6:0;;;;263383:30;;:44;;263414:12;;263383:44;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;263382:45;263366:61;;263442:13;263437:181;;263476:45;263495:12;263509:11;263476:45;;;;;;;:::i;260155:1497::-;260382:17;260472:15;260490:30;:10;:28;:30::i;:::-;260472:48;;260607:25;260634:14;260652:37;260671:3;260676:12;260652:18;:37::i;:::-;260606:83;;;;260746:30;:6;:28;:30::i;:::-;260840:11;260854:26;:12;:24;:26::i;:::-;260840:40;;261230:56;261252:3;261257:10;261269:5;261276:9;261230:21;:56::i;:::-;261387:6;;261377:44;;;;;-1:-1:-1;;;;;261387:6:0;;;;261377:30;;:44;;261408:12;;261377:44;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;261362:59;;261436:12;261431:215;;261469:79;261497:10;261509:12;261523:10;261535:12;261469:79;;;;;;;;;:::i;:::-;;;;;;;;261576:12;;261601:13;;;;261562:73;;;;;15989:10:1;15977:23;;;261562:73:0;;;15959:42:1;-1:-1:-1;;;;;16098:15:1;;;16078:18;;;16071:43;261624:10:0;16130:18:1;;;16123:43;261576:12:0;;;;261562:38;;15932:18:1;;261562:73:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;261431:215;260401:1251;;;;260155:1497;;;;;;;:::o;225679:178::-;222498:13;:11;:13::i;:::-;225768::::1;:24:::0;;-1:-1:-1;;;;;225768:24:0;::::1;::::0;;;::::1;::::0;::::1;::::0;;;225832:7:::1;222677:6:::0;;-1:-1:-1;;;;;222677:6:0;;222605:85;225832:7:::1;-1:-1:-1::0;;;;;225807:43:0::1;;;;;;;;;;;225679:178:::0;:::o;278445:242::-;158401:19;158424:13;;;;;;158423:14;;158469:34;;;;-1:-1:-1;158487:12:0;;158502:1;158487:12;;;;:16;158469:34;158468:108;;;-1:-1:-1;158548:4:0;98164:19;:23;;;158509:66;;-1:-1:-1;158558:12:0;;;;;:17;158509:66;158447:201;;;;;;;25228:2:1;158447:201:0;;;25210:21:1;25267:2;25247:18;;;25240:30;25306:34;25286:18;;;25279:62;25377:16;25357:18;;;25350:44;25411:19;;158447:201:0;25026:410:1;158447:201:0;158658:12;:16;;;;158673:1;158658:16;;;158684:65;;;;158718:13;:20;;;;;;;;158684:65;278595:59:::1;278617:13;278632:7;278641:12;278595:21;:59::i;:::-;278664:6;:16:::0;;;::::1;-1:-1:-1::0;;;;;278664:16:0;::::1;;::::0;;158769:99;;;;158819:5;158803:21;;;;;;158843:14;;-1:-1:-1;25593:36:1;;158843:14:0;;25581:2:1;25566:18;158843:14:0;;;;;;;158769:99;158391:483;278445:242;;;;:::o;110487:98::-;110529:6;110554:24;:13;:22;:24::i;:::-;110547:31;;110487:98;:::o;75334:187::-;75390:6;75425:16;75416:25;;;75408:76;;;;;;;25842:2:1;75408:76:0;;;25824:21:1;25881:2;25861:18;;;25854:30;25920:34;25900:18;;;25893:62;25991:8;25971:18;;;25964:36;26017:19;;75408:76:0;25640:402:1;75408:76:0;-1:-1:-1;75508:5:0;75334:187::o;190809:141::-;190881:11;190911:32;190929:13;:7;:11;:13::i;:::-;190911:17;:32::i;:::-;190904:39;190809:141;-1:-1:-1;;190809:141:0:o;268508:426::-;-1:-1:-1;;;;;;;;;;;;;;;;;;;;;;;;;268762:44:0;268776:15;:3;:13;:15::i;:::-;268793:12;268762:13;:44::i;:::-;268884:13;;;;268743:63;;-1:-1:-1;268743:63:0;-1:-1:-1;268884:18:0;;268901:1;268884:18;268880:47;;268911:16;;;;;;;;;;;;;;268880:47;268508:426;;;;;:::o;114665:223::-;114766:16;114751:11;;:31;;;;;;;;:::i;:::-;;;:69;;;;-1:-1:-1;114801:19:0;114786:11;;:34;;;;;;;;:::i;:::-;;;114751:69;114747:135;;;114843:28;;;;;;;;;;;;;;239672:132;239741:8;239768:29;239783:13;:7;:11;:13::i;:::-;239768:14;:29::i;241589:342::-;241666:5;241701:8;241666:5;34013:20;33733:2;34013;:20;:::i;:::-;241748:25;;:10;:25;:::i;:::-;241728:45;-1:-1:-1;122470:17:0;122444:43;;241787:9;:26;241783:56;;241822:17;;;;;;;;;;;;;;241783:56;241856:68;:54;241879:9;34013:20;33733:2;34013;:20;:::i;:::-;241856:7;;:54;:13;:54::i;:::-;:66;:68::i;272772:416::-;-1:-1:-1;;;;;;;;;;;;;;;;;;;;;;;;;273019:47:0;273033:19;:5;:17;:19::i;273019:47::-;273139:13;;;;273001:65;;-1:-1:-1;273001:65:0;-1:-1:-1;273139:18:0;;;273135:46;;273166:15;;;;;;;;;;;;;;114212:164;114304:16;114289:11;;:31;;;;;;;;:::i;:::-;;114285:85;;114343:16;;;;;;;;;;;;;;267371:365;267655:11;267639:27;;:12;:27;;;;:59;;;;;267685:13;267670:28;;:11;:28;;;;267639:59;267635:94;;;267707:22;;;;;;;;;;;;;;192860:149;192918:7;192944:58;192918:7;192998:2;192944:3;:12;:18;:58;:18;:58::i;243079:807::-;243144:7;243163:21;243187:23;:8;:21;:23::i;:::-;243163:47;;243220:23;243260:13;243246:28;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;243246:28:0;;243220:54;;243289:9;243284:298;243308:13;243304:1;:17;243284:298;;;243547:24;:17;:8;243562:1;243547:14;:17::i;:::-;:22;:24::i;:::-;243535:6;243542:1;243535:9;;;;;;;;:::i;:::-;;;;;;;;;;:36;243323:3;;;:::i;:::-;;;243284:298;;;-1:-1:-1;243721:58:0;243746:6;243754:24;243777:1;33271;243754:24;:::i;:::-;243721;:58::i;:::-;243870:6;243877:1;243870:9;;;;;;;;:::i;:::-;;;;;;;243863:16;;;;243079:807;;;:::o;119284:1041::-;119530:4;119524:11;;119660:34;119674:7;119689:4;119683:10;;119660:13;:34::i;:::-;-1:-1:-1;122470:17:0;122444:43;;119906:12;123302:2;123286:18;;-1:-1:-1;;123670:20:0;120202;;120224:4;120198:31;120192:4;120185:45;-1:-1:-1;120292:17:0;;119284:1041;;-1:-1:-1;119284:1041:0:o;265153:229::-;265254:16;265273:31;265288:15;265273:14;:31::i;:::-;265334:40;;;;;;;;;;;;;;;;;;265314:14;:61;;;;;;;-1:-1:-1;265314:61:0;;;;;;;;;;;;;;;;;;265254:50;;-1:-1:-1;265334:40:0;;265314:61;;;;;;;;;:::i;:::-;;;;265244:138;265153:229;;:::o;269458:424::-;-1:-1:-1;;;;;;;;;;;;;;;;;;;;;;;;;269715:45:0;269729:17;:3;:15;:17::i;273813:476::-;-1:-1:-1;;;;;;;;;;;;;;;;;;;;;;;;;274084:50:0;274098:20;:8;:18;:20::i;:::-;274120:13;274084;:50::i;:::-;274066:68;;-1:-1:-1;274066:68:0;-1:-1:-1;274223:12:0;:34;;;;-1:-1:-1;274239:13:0;;;;:18;;;274223:34;274219:63;;;274266:16;;;;;;;;;;;;;;274219:63;273813:476;;;;;;:::o;265444:179::-;265549:17;:24;;265583:33;;;;;265510:16;265583:33;;;;;;;;265606:9;265583:33;;:::i;:::-;;265444:179;;;:::o;242273:399::-;242332:26;242370:21;242394:23;:8;:21;:23::i;:::-;242370:47;;242453:13;242438:29;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;242438:29:0;;242427:40;;242482:9;242477:189;242501:13;242497:1;:17;242477:189;;;242535:12;242550:17;:8;242565:1;242550:14;:17::i;:::-;242535:32;;242595:60;242621:16;:6;:14;:16::i;:::-;242639:15;:6;:13;:15::i;:::-;153231:16;;148600:5;153177:51;;;;;;:70;;152980:275;242595:60;242581:8;242590:1;242581:11;;;;;;;;:::i;:::-;:74;;;;:11;;;;;;;;;;;:74;-1:-1:-1;242516:3:0;;;:::i;:::-;;;242477:189;;;;242360:312;242273:399;;;:::o;222763:130::-;222677:6;;-1:-1:-1;;;;;222677:6:0;185328:10;222826:23;222818:68;;;;;;;29640:2:1;222818:68:0;;;29622:21:1;;;29659:18;;;29652:30;29718:34;29698:18;;;29691:62;29770:18;;222818:68:0;29438:356:1;226041:153:0;226130:13;226123:20;;;;;;226153:34;226178:8;226153:24;:34::i;198668:129::-;198736:7;198762:28;198776:13;:7;:11;:13::i;:::-;198762;:28::i;271575:418::-;-1:-1:-1;;;;;;;;;;;;;;;;;;;;;;;;;271825:46:0;271839:18;:4;:16;:18::i;270646:418::-;-1:-1:-1;;;;;;;;;;;;;;;;;;;;;;;;;270894:46:0;270908:16;:4;:14;:16::i;201701:161::-;201763:7;201789:66;196803:2;201851;201789:7;:16;231331:118;202225:150;202284:7;202310:58;:7;196910:2;202310:29;:58::i;201185:234::-;201246:6;201344:67;196694:1;;201344:7;:16;:26;:67;:26;:67::i;201480:159::-;201541:7;201567:65;196748:1;201628:2;201567:7;:16;231331:118;287164:456;287311:9;287342:10;287311:42;;287553:7;287472:77;287493:10;287505:43;287526:11;:4;208744:18;208896:15;;;209006:2;208993:16;;;208696:329;287526:11;287539:8;287505:20;:43::i;:::-;287472:20;:77::i;:::-;:88;287468:146;;287583:20;;;;;;;;;;;;;;230289:123;230355:5;230379:26;230391:13;:7;:11;:13::i;275266:823::-;275511:20;275535:16;:5;:14;:16::i;:::-;275508:43;;;275581:12;275565:9;275575:1;275565:12;;;;;;;;:::i;:::-;;;;;;;:28;275561:65;;275602:24;;;;;;;;;;;;;;275561:65;275846:20;275869:78;275895:12;:5;:10;:12::i;:::-;275909:14;:5;:12;:14::i;:::-;275925:9;275936:10;275869:25;:78::i;:::-;275846:101;;276038:12;276020:14;:3;:12;:14::i;:::-;:30;276016:66;;276059:23;;;;;;;;;;;;;;251576:277;160496:13;;;;;;;160488:69;;;;;;;30001:2:1;160488:69:0;;;29983:21:1;30040:2;30020:18;;;30013:30;30079:34;30059:18;;;30052:62;30150:13;30130:18;;;30123:41;30181:19;;160488:69:0;29799:407:1;160488:69:0;251725:12:::1;:28:::0;;-1:-1:-1;;;;;251725:28:0;;::::1;::::0;;;::::1;;::::0;;;251763:6:::1;:16:::0;;;;::::1;::::0;;::::1;;::::0;;251789:11:::1;:26:::0;;;;::::1;::::0;;;::::1;::::0;;;::::1;::::0;;251825:21:::1;:19;:21::i;:::-;251576:277:::0;;;:::o;118177:569::-;118265:10;;118231:7;;118691:4;118682:14;;118722:17;118682:14;118265:10;118722:5;:17::i;191102:215::-;191169:11;191197:22;191211:7;191197:13;:22::i;:::-;191192:60;;191228:24;;;;;;;;;;;;;;191663:223;191722:7;191830:49;35245:35;191830:3;:12;:25;;:49::i;266763:531::-;-1:-1:-1;;;;;;;;;;;;;;;;;;;;;;;;;219481:34:0;266909:13;219468:48;;;219536:4;219529:18;;;219587:4;219571:21;;267024:38;267038:12;267052:9;267024:13;:38::i;:::-;267095:12;;267081:46;;;;;-1:-1:-1;;;;;8713:55:1;;;267081:46:0;;;8695:74:1;267016:46:0;;-1:-1:-1;267095:12:0;;;267081:39;;8668:18:1;;267081:46:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;267072:55;;267267:20;:6;:18;:20::i;:::-;266928:366;266763:531;;;;;:::o;239956:200::-;240020:8;240045:19;240056:7;240045:10;:19::i;:::-;240040:54;;240073:21;;;;;;;;;;;;;;125536:484;125621:7;125640:12;125655:13;:7;122103:3;122076:30;;121917:196;125655:13;125640:28;;125751:13;:7;:11;:13::i;:::-;125744:4;125728:13;125735:6;125728:4;:13;:::i;:::-;:20;;;;:::i;:::-;:36;125724:87;;;125787:13;;;;;;;;;;;;;;125724:87;125963:40;125983:6;125976:4;:13;125997:4;125963:5;:40::i;230550:185::-;230611:5;230633:16;230641:7;230633;:16::i;:::-;230628:48;;230658:18;;;;;;;;;;;;;;231051:214;231108:7;231211:47;35622:31;231211:5;:14;231331:118;129065:1334;129152:14;129182:6;129192:1;129182:11;129178:59;;-1:-1:-1;129224:1:0;129209:17;;129178:59;129323:2;129314:6;:11;129310:65;;;129348:16;;;;;;;;;;;;;;129310:65;122470:17;122444:43;;129454:15;129463:6;129454;:15;:::i;:::-;:31;129450:82;;;129508:13;;;;;;;;;;;;;;129450:82;129571:1;129561:11;;;129541:17;129611:13;:7;122103:3;122076:30;;121917:196;129611:13;130358:17;;;130352:24;130069:66;-1:-1:-1;;130050:17:0;;;;130046:90;;;;130348:35;;129065:1334;-1:-1:-1;;;;129065:1334:0:o;241999:195::-;242063:7;34013:20;33733:2;34013;:20;:::i;:::-;242149:38;;122470:17;122444:43;;242149:38;:::i;232181:248::-;232231:7;232251:17;232270:18;232292:16;:5;:14;:16::i;:::-;232386:35;;;;;;;30647:19:1;;;;30682:12;;;30675:28;;;;232386:35:0;;;;;;;;;30719:12:1;;;;232386:35:0;;232376:46;;;;;;232181:248;-1:-1:-1;;;;232181:248:0:o;140084:1885::-;140194:13;;140327:1;:11;;140312:27;;140308:58;;;140348:18;;;;;;;;;;;;;;140308:58;140636:9;140631:1322;140655:6;140651:1;:10;140631:1322;;;141169:17;141164:618;141204:11;141192:9;:23;141164:618;;;141255:18;141276:9;141288:1;141276:13;141255:34;;141311:17;141331:6;141338:9;141331:17;;;;;;;;:::i;:::-;;;;;;;141311:37;;141424:18;141458:11;141445:10;:24;:58;;141501:1;141445:58;;;141472:6;141479:10;141472:18;;;;;;;;:::i;:::-;;;;;;;141445:58;141424:79;;141731:32;141741:9;141752:10;141731:9;:32::i;:::-;141706:6;141726:1;141713:9;:14;;141706:22;;;;;;;;:::i;:::-;;;;;;;;;;:57;-1:-1:-1;;;141230:1:0;141217:14;141164:618;;;-1:-1:-1;141937:1:0;141917:15;;;141916:22;;;140663:3;140631:1322;;;;140162:1807;140084:1885;;:::o;133218:842::-;133557:4;133551:11;133296:7;;122470:17;122444:43;;;122103:3;122076:30;;;;133639:12;;;133635:66;;;133674:16;;;;;;;;;;;;;;133635:66;133710:8;133926:4;133918:6;133912:4;133904:6;133898:4;133891:5;133880:51;133873:58;;133955:3;133950:37;;133967:20;;;;;;;;;;;;;;133950:37;132567:3;132559:11;;;132558:20;;134004:49;133997:56;133218:842;-1:-1:-1;;;;;;;133218:842:0:o;192033:234::-;192094:7;192209:51;35326:37;192209:3;:12;231331:118;240769:236;240830:22;240947:51;35550:32;240947:8;:17;231331:118;235724:186;235777:7;235803:100;235826:76;229030:2;33733;235826:5;:14;231331:118;234457:218;234509:6;234607:60;228824:2;234664:1;234607:5;:14;231331:118;223830:187;223922:6;;;-1:-1:-1;;;;;223938:17:0;;;;;;;;;;;223970:40;;223922:6;;;223938:17;223922:6;;223970:40;;223903:16;;223970:40;223893:124;223830:187;:::o;198939:195::-;199002:7;199026:18;199036:7;199026:9;:18::i;:::-;199021:52;;199053:20;;;;;;;;;;;;;;199845:230;199906:7;200017:51;35476:33;200017:7;:16;231331:118;199492:215;199551:7;199651:49;35403:31;199651:7;:16;231331:118;131558:225;131636:7;131745:29;:7;131763:6;131771:2;130757:538;130848:7;;130890:29;:7;130904:6;130912;130890:13;:29::i;:::-;131260:2;:11;;;131276:1;131259:18;131233:45;;-1:-1:-1;;130757:538:0;;;;;:::o;138652:287::-;138733:14;138763:23;;:51;;;;-1:-1:-1;138790:24:0;;138763:51;138759:174;;;-1:-1:-1;138837:1:0;138830:8;;138759:174;138886:35;;;;;;30647:19:1;;;30682:12;;;30675:28;;;30719:12;;138886:35:0;;;;;;;;;;;;138876:46;;;;;;138869:53;;;;232774:393;232828:17;;232895:5;232970:45;:36;232895:5;228872:2;232970:14;:36::i;:::-;:43;:45::i;:::-;232958:57;-1:-1:-1;233110:50:0;:41;:7;228872:2;233110:17;:41::i;:50::-;233097:63;;232867:300;232774:393;;;:::o;244511:998::-;244662:7;245019:24;245042:1;245019:24;;;;245145:25;245127:44;;245123:74;;245180:17;;;;;;;;;;;;;;245123:74;245207:16;245226:37;245244:10;245256:6;245226:17;:37::i;:::-;245207:56;;245424:78;245445:13;245460:8;245470:9;33271:1;245424:20;:78::i;225002:100::-;160496:13;;;;;;;160488:69;;;;;;;30001:2:1;160488:69:0;;;29983:21:1;30040:2;30020:18;;;30013:30;30079:34;30059:18;;;30052:62;30150:13;30130:18;;;30123:41;30181:19;;160488:69:0;29799:407:1;160488:69:0;225069:26:::1;:24;:26::i;117297:540::-:0;117363:7;;117397:11;117404:4;117397;:11;:::i;:::-;117382:26;;117676:4;117670:11;117664:4;117661:21;117658:38;;;-1:-1:-1;117693:1:0;117658:38;117719:4;117727:1;117719:9;117715:66;;117751:19;;;;;;;;;;;;;;117715:66;132567:3;132559:11;;;132558:20;;117797:33;132234:352;191389:128;191452:4;33611:2;122470:17;122444:43;;191475:13;:35;;191389:128;-1:-1:-1;;191389:128:0:o;124763:169::-;124839:20;124901:4;124907:16;:7;:14;:16::i;:::-;124888:36;;;;;;30647:19:1;;;;30682:12;;30675:28;30719:12;;124888:36:0;;;;;;;;;;;;;124878:47;;;;;;124871:54;;124763:169;;;;:::o;215753:227::-;215831:7;215851:17;215870:18;215892:27;215903:4;215909:9;215892:10;:27::i;:::-;215850:69;;;;215929:18;215941:5;215929:11;:18::i;:::-;-1:-1:-1;215964:9:0;215753:227;-1:-1:-1;;;215753:227:0:o;115173:162::-;115264:17;115249:11;;:32;;;;;;;;:::i;:::-;;115245:84;;115304:14;;;;;;;;;;;;;;240240:389;240300:4;122470:17;122444:43;;240300:4;34013:20;33733:2;34013;:20;:::i;:::-;240513:21;;:6;:21;:::i;:::-;240489:45;-1:-1:-1;240583:6:0;34013:20;33733:2;34013;:20;:::i;:::-;240551:28;;:13;:28;:::i;:::-;:38;:71;;;;;240593:29;240608:13;240593:14;:29::i;122664:258::-;122717:12;122470:17;122444:43;;122876:13;:7;122103:3;122076:30;;121917:196;122876:13;:29;;122664:258;-1:-1:-1;;122664:258:0:o;230801:116::-;230858:4;34013:20;33733:2;34013;:20;:::i;:::-;122470:17;122444:43;;230881:13;122286:208;199202:152;199261:4;33881:3;122470:17;122444:43;;199316:13;122286:208;127152:141;127222:7;127248:38;:7;127222;127280:4;127248:13;:38::i;124208:292::-;124264:14;124290:12;124305:13;:7;122103:3;122076:30;;121917:196;124305:13;122470:17;122444:43;;;;124463:21;;;;;-1:-1:-1;;124208:292:0:o;126331:529::-;126406:7;122470:17;122444:43;;126513:13;;;126509:64;;;126549:13;;;;;;;;;;;;;;126509:64;126785:58;126814:6;126798:13;:7;122103:3;122076:30;;121917:196;126798:13;:22;126835:6;126828:4;:13;126785:5;:58::i;233231:220::-;233303:7;233428:5;233435:7;233411:32;;;;;;;;30897:19:1;;;30954:3;30950:16;30968:66;30946:89;30941:2;30932:12;;30925:111;31061:2;31052:12;;30742:328;136380:900:0;136620:12;;136515:13;;136646:17;;;136642:48;;;136672:18;;;;;;;;;;;;;;136642:48;136708:4;136700:12;;136877:9;136872:189;136896:8;136892:1;:12;136872:189;;;137010:36;137020:5;137027;137033:1;137027:8;;;;;;;;:::i;:::-;;;;;;;137037:5;137044:1;137010:9;:36::i;:::-;137002:44;-1:-1:-1;136906:3:0;;136872:189;;;-1:-1:-1;137158:8:0;137141:123;137172:6;137168:1;:10;137141:123;;;137211:38;137221:5;137236:1;137240:5;137247:1;137211:9;:38::i;:::-;137203:46;-1:-1:-1;137180:3:0;;137141:123;;;;136534:746;136380:900;;;;;;:::o;222268:111::-;160496:13;;;;;;;160488:69;;;;;;;30001:2:1;160488:69:0;;;29983:21:1;30040:2;30020:18;;;30013:30;30079:34;30059:18;;;30052:62;30150:13;30130:18;;;30123:41;30181:19;;160488:69:0;29799:407:1;160488:69:0;222340:32:::1;185328:10:::0;222340:18:::1;:32::i;214237:730::-:0;214318:7;214327:12;214355:9;:16;214375:2;214355:22;214351:610;;214691:4;214676:20;;214670:27;214740:4;214725:20;;214719:27;214797:4;214782:20;;214776:27;214393:9;214768:36;214838:25;214849:4;214768:36;214670:27;214719;214838:10;:25::i;:::-;214831:32;;;;;;;;;214351:610;-1:-1:-1;214910:1:0;;-1:-1:-1;214914:35:0;214894:56;;212662:511;212739:20;212730:5;:29;;;;;;;;:::i;:::-;;212726:441;;212662:511;:::o;212726:441::-;212835:29;212826:5;:38;;;;;;;;:::i;:::-;;212822:345;;212880:34;;;;;31277:2:1;212880:34:0;;;31259:21:1;31316:2;31296:18;;;31289:30;31355:26;31335:18;;;31328:54;31399:18;;212880:34:0;31075:348:1;212822:345:0;212944:35;212935:5;:44;;;;;;;;:::i;:::-;;212931:236;;212995:41;;;;;31630:2:1;212995:41:0;;;31612:21:1;31669:2;31649:18;;;31642:30;31708:33;31688:18;;;31681:61;31759:18;;212995:41:0;31428:355:1;212931:236:0;213066:30;213057:5;:39;;;;;;;;:::i;:::-;;213053:114;;213112:44;;;;;31990:2:1;213112:44:0;;;31972:21:1;32029:2;32009:18;;;32002:30;32068:34;32048:18;;;32041:62;32139:4;32119:18;;;32112:32;32161:19;;213112:44:0;31788:398:1;245887:302:0;245957:4;246124:18;;;;;:58;;-1:-1:-1;34178:24:0;34201:1;33271;34178:24;:::i;:::-;34172:1;:31;;246146:13;:36;;246117:65;245887:302;-1:-1:-1;;245887:302:0:o;137662:526::-;137798:14;138003:1;137976:23;;;137975:29;:34;;137971:211;;138058:24;138068:4;138074:7;138058:9;:24::i;:::-;138051:31;;;;137971:211;138147:24;138157:7;138166:4;138147:9;:24::i;217101:1456::-;217189:7;;218113:66;218100:79;;218096:161;;;-1:-1:-1;218211:1:0;;-1:-1:-1;218215:30:0;218195:51;;218096:161;218368:24;;;218351:14;218368:24;;;;;;;;;32418:25:1;;;32491:4;32479:17;;32459:18;;;32452:45;;;;32513:18;;;32506:34;;;32556:18;;;32549:34;;;218368:24:0;;32390:19:1;;218368:24:0;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;218368:24:0;;-1:-1:-1;;218368:24:0;;;-1:-1:-1;;;;;;;218406:20:0;;218402:101;;218458:1;218462:29;218442:50;;;;;;;218402:101;218521:6;-1:-1:-1;218529:20:0;;-1:-1:-1;217101:1456:0;;;;;;;;:::o;-1:-1:-1:-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;14:184:1:-;66:77;63:1;56:88;163:4;160:1;153:15;187:4;184:1;177:15;203:334;274:2;268:9;330:2;320:13;;-1:-1:-1;;316:86:1;304:99;;433:18;418:34;;454:22;;;415:62;412:88;;;480:18;;:::i;:::-;516:2;509:22;203:334;;-1:-1:-1;203:334:1:o;542:245::-;590:4;623:18;615:6;612:30;609:56;;;645:18;;:::i;:::-;-1:-1:-1;702:2:1;690:15;-1:-1:-1;;686:88:1;776:4;682:99;;542:245::o;792:462::-;834:5;887:3;880:4;872:6;868:17;864:27;854:55;;905:1;902;895:12;854:55;941:6;928:20;972:48;988:31;1016:2;988:31;:::i;:::-;972:48;:::i;:::-;1045:2;1036:7;1029:19;1091:3;1084:4;1079:2;1071:6;1067:15;1063:26;1060:35;1057:55;;;1108:1;1105;1098:12;1057:55;1173:2;1166:4;1158:6;1154:17;1147:4;1138:7;1134:18;1121:55;1221:1;1196:16;;;1214:4;1192:27;1185:38;;;;1200:7;792:462;-1:-1:-1;;;792:462:1:o;1259:539::-;1345:6;1353;1406:2;1394:9;1385:7;1381:23;1377:32;1374:52;;;1422:1;1419;1412:12;1374:52;1462:9;1449:23;1491:18;1532:2;1524:6;1521:14;1518:34;;;1548:1;1545;1538:12;1518:34;1571:49;1612:7;1603:6;1592:9;1588:22;1571:49;:::i;:::-;1561:59;;1673:2;1662:9;1658:18;1645:32;1629:48;;1702:2;1692:8;1689:16;1686:36;;;1718:1;1715;1708:12;1686:36;;1741:51;1784:7;1773:8;1762:9;1758:24;1741:51;:::i;:::-;1731:61;;;1259:539;;;;;:::o;1995:156::-;2061:20;;2121:4;2110:16;;2100:27;;2090:55;;2141:1;2138;2131:12;2090:55;1995:156;;;:::o;2156:1007::-;2285:6;2293;2301;2309;2317;2370:3;2358:9;2349:7;2345:23;2341:33;2338:53;;;2387:1;2384;2377:12;2338:53;2410:27;2427:9;2410:27;:::i;:::-;2400:37;;2488:2;2477:9;2473:18;2460:32;2511:18;2552:2;2544:6;2541:14;2538:34;;;2568:1;2565;2558:12;2538:34;2591:49;2632:7;2623:6;2612:9;2608:22;2591:49;:::i;:::-;2581:59;;2693:2;2682:9;2678:18;2665:32;2649:48;;2722:2;2712:8;2709:16;2706:36;;;2738:1;2735;2728:12;2706:36;2761:51;2804:7;2793:8;2782:9;2778:24;2761:51;:::i;:::-;2751:61;;2865:2;2854:9;2850:18;2837:32;2821:48;;2894:2;2884:8;2881:16;2878:36;;;2910:1;2907;2900:12;2878:36;2933:51;2976:7;2965:8;2954:9;2950:24;2933:51;:::i;:::-;2923:61;;3037:3;3026:9;3022:19;3009:33;2993:49;;3067:2;3057:8;3054:16;3051:36;;;3083:1;3080;3073:12;3051:36;;3106:51;3149:7;3138:8;3127:9;3123:24;3106:51;:::i;:::-;3096:61;;;2156:1007;;;;;;;;:::o;3168:808::-;3279:6;3287;3295;3303;3356:3;3344:9;3335:7;3331:23;3327:33;3324:53;;;3373:1;3370;3363:12;3324:53;3396:27;3413:9;3396:27;:::i;:::-;3386:37;;3474:2;3463:9;3459:18;3446:32;3497:18;3538:2;3530:6;3527:14;3524:34;;;3554:1;3551;3544:12;3524:34;3577:49;3618:7;3609:6;3598:9;3594:22;3577:49;:::i;:::-;3567:59;;3679:2;3668:9;3664:18;3651:32;3635:48;;3708:2;3698:8;3695:16;3692:36;;;3724:1;3721;3714:12;3692:36;3747:51;3790:7;3779:8;3768:9;3764:24;3747:51;:::i;:::-;3737:61;;3851:2;3840:9;3836:18;3823:32;3807:48;;3880:2;3870:8;3867:16;3864:36;;;3896:1;3893;3886:12;3864:36;;3919:51;3962:7;3951:8;3940:9;3936:24;3919:51;:::i;:::-;3909:61;;;3168:808;;;;;;;:::o;3981:250::-;4066:1;4076:113;4090:6;4087:1;4084:13;4076:113;;;4166:11;;;4160:18;4147:11;;;4140:39;4112:2;4105:10;4076:113;;;-1:-1:-1;;4223:1:1;4205:16;;4198:27;3981:250::o;4236:329::-;4277:3;4315:5;4309:12;4342:6;4337:3;4330:19;4358:76;4427:6;4420:4;4415:3;4411:14;4404:4;4397:5;4393:16;4358:76;:::i;:::-;4479:2;4467:15;-1:-1:-1;;4463:88:1;4454:98;;;;4554:4;4450:109;;4236:329;-1:-1:-1;;4236:329:1:o;4570:831::-;4823:2;4812:9;4805:21;4786:4;4849:44;4889:2;4878:9;4874:18;4866:6;4849:44;:::i;:::-;4912:2;4930:18;;;4923:34;;;4993:22;;;4988:2;4973:18;;4966:50;5065:13;;5087:22;;;5163:15;;;;5125;;;-1:-1:-1;5206:169:1;5220:6;5217:1;5214:13;5206:169;;;5281:13;;5269:26;;5350:15;;;;5315:12;;;;5242:1;5235:9;5206:169;;;-1:-1:-1;5392:3:1;;4570:831;-1:-1:-1;;;;;;;;4570:831:1:o;5406:219::-;5555:2;5544:9;5537:21;5518:4;5575:44;5615:2;5604:9;5600:18;5592:6;5575:44;:::i;5630:639::-;5740:6;5748;5801:2;5789:9;5780:7;5776:23;5772:32;5769:52;;;5817:1;5814;5807:12;5769:52;5857:9;5844:23;5886:18;5927:2;5919:6;5916:14;5913:34;;;5943:1;5940;5933:12;5913:34;5981:6;5970:9;5966:22;5956:32;;6026:7;6019:4;6015:2;6011:13;6007:27;5997:55;;6048:1;6045;6038:12;5997:55;6088:2;6075:16;6114:2;6106:6;6103:14;6100:34;;;6130:1;6127;6120:12;6100:34;6183:7;6178:2;6168:6;6165:1;6161:14;6157:2;6153:23;6149:32;6146:45;6143:65;;;6204:1;6201;6194:12;6143:65;6235:2;6227:11;;;;;6257:6;;-1:-1:-1;5630:639:1;;-1:-1:-1;;;;5630:639:1:o;6274:1099::-;6464:4;6493:2;6533;6522:9;6518:18;6563:2;6552:9;6545:21;6586:6;6621;6615:13;6652:6;6644;6637:22;6678:2;6668:12;;6711:2;6700:9;6696:18;6689:25;;6773:2;6763:6;6760:1;6756:14;6745:9;6741:30;6737:39;6811:2;6803:6;6799:15;6832:1;6842:502;6856:6;6853:1;6850:13;6842:502;;;6921:22;;;6945:66;6917:95;6905:108;;7036:13;;7091:9;;7084:17;7077:25;7062:41;;7142:11;;7136:18;7174:15;;;7167:27;;;7217:47;7248:15;;;7136:18;7217:47;:::i;:::-;7322:12;;;;7207:57;-1:-1:-1;;7287:15:1;;;;6878:1;6871:9;6842:502;;7378:121;7463:10;7456:5;7452:22;7445:5;7442:33;7432:61;;7489:1;7486;7479:12;7504:661;7597:6;7605;7613;7621;7674:3;7662:9;7653:7;7649:23;7645:33;7642:53;;;7691:1;7688;7681:12;7642:53;7730:9;7717:23;7749:30;7773:5;7749:30;:::i;:::-;7798:5;-1:-1:-1;7855:2:1;7840:18;;7827:32;7868;7827;7868;:::i;:::-;7919:7;-1:-1:-1;7973:2:1;7958:18;;7945:32;;-1:-1:-1;8028:2:1;8013:18;;8000:32;8055:18;8044:30;;8041:50;;;8087:1;8084;8077:12;8041:50;8110:49;8151:7;8142:6;8131:9;8127:22;8110:49;:::i;8780:609::-;8873:6;8881;8889;8942:2;8930:9;8921:7;8917:23;8913:32;8910:52;;;8958:1;8955;8948:12;8910:52;8981:27;8998:9;8981:27;:::i;:::-;8971:37;;9059:2;9048:9;9044:18;9031:32;9082:18;9123:2;9115:6;9112:14;9109:34;;;9139:1;9136;9129:12;9109:34;9162:49;9203:7;9194:6;9183:9;9179:22;9162:49;:::i;:::-;9152:59;;9264:2;9253:9;9249:18;9236:32;9220:48;;9293:2;9283:8;9280:16;9277:36;;;9309:1;9306;9299:12;9277:36;;9332:51;9375:7;9364:8;9353:9;9349:24;9332:51;:::i;:::-;9322:61;;;8780:609;;;;;:::o;9394:737::-;9498:6;9506;9514;9567:2;9555:9;9546:7;9542:23;9538:32;9535:52;;;9583:1;9580;9573:12;9535:52;9623:9;9610:23;9652:18;9693:2;9685:6;9682:14;9679:34;;;9709:1;9706;9699:12;9679:34;9732:49;9773:7;9764:6;9753:9;9749:22;9732:49;:::i;:::-;9722:59;;9834:2;9823:9;9819:18;9806:32;9790:48;;9863:2;9853:8;9850:16;9847:36;;;9879:1;9876;9869:12;10136:745;10249:6;10257;10265;10273;10281;10334:3;10322:9;10313:7;10309:23;10305:33;10302:53;;;10351:1;10348;10341:12;10302:53;10391:9;10378:23;10420:18;10461:2;10453:6;10450:14;10447:34;;;10477:1;10474;10467:12;10447:34;10500:49;10541:7;10532:6;10521:9;10517:22;10500:49;:::i;:::-;10490:59;;10602:2;10591:9;10587:18;10574:32;10558:48;;10631:2;10621:8;10618:16;10615:36;;;10647:1;10644;10637:12;10615:36;;10670:51;10713:7;10702:8;10691:9;10687:24;10670:51;:::i;:::-;10136:745;;10660:61;;-1:-1:-1;;;;10768:2:1;10753:18;;10740:32;;10819:2;10804:18;;10791:32;;10870:3;10855:19;;;10842:33;;-1:-1:-1;10136:745:1;-1:-1:-1;10136:745:1:o;10886:712::-;10940:5;10993:3;10986:4;10978:6;10974:17;10970:27;10960:55;;11011:1;11008;11001:12;10960:55;11047:6;11034:20;11073:4;11096:18;11092:2;11089:26;11086:52;;;11118:18;;:::i;:::-;11164:2;11161:1;11157:10;11187:28;11211:2;11207;11203:11;11187:28;:::i;:::-;11249:15;;;11319;;;11315:24;;;11280:12;;;;11351:15;;;11348:35;;;11379:1;11376;11369:12;11348:35;11415:2;11407:6;11403:15;11392:26;;11427:142;11443:6;11438:3;11435:15;11427:142;;;11509:17;;11497:30;;11460:12;;;;11547;;;;11427:142;;11603:1234;11766:6;11774;11782;11790;11798;11806;11859:3;11847:9;11838:7;11834:23;11830:33;11827:53;;;11876:1;11873;11866:12;11827:53;11899:27;11916:9;11899:27;:::i;:::-;11889:37;;11977:2;11966:9;11962:18;11949:32;12000:18;12041:2;12033:6;12030:14;12027:34;;;12057:1;12054;12047:12;12027:34;12080:49;12121:7;12112:6;12101:9;12097:22;12080:49;:::i;:::-;12070:59;;12182:2;12171:9;12167:18;12154:32;12138:48;;12211:2;12201:8;12198:16;12195:36;;;12227:1;12224;12217:12;12195:36;12250:51;12293:7;12282:8;12271:9;12267:24;12250:51;:::i;:::-;12240:61;;12354:2;12343:9;12339:18;12326:32;12310:48;;12383:2;12373:8;12370:16;12367:36;;;12399:1;12396;12389:12;12367:36;12422:63;12477:7;12466:8;12455:9;12451:24;12422:63;:::i;:::-;12412:73;;12538:3;12527:9;12523:19;12510:33;12494:49;;12568:2;12558:8;12555:16;12552:36;;;12584:1;12581;12574:12;12552:36;12607:51;12650:7;12639:8;12628:9;12624:24;12607:51;:::i;:::-;12597:61;;12711:3;12700:9;12696:19;12683:33;12667:49;;12741:2;12731:8;12728:16;12725:36;;;12757:1;12754;12747:12;12725:36;;12780:51;12823:7;12812:8;12801:9;12797:24;12780:51;:::i;:::-;12770:61;;;11603:1234;;;;;;;;:::o;12842:180::-;12901:6;12954:2;12942:9;12933:7;12929:23;12925:32;12922:52;;;12970:1;12967;12960:12;12922:52;-1:-1:-1;12993:23:1;;12842:180;-1:-1:-1;12842:180:1:o;13027:377::-;13220:2;13209:9;13202:21;13183:4;13246:44;13286:2;13275:9;13271:18;13263:6;13246:44;:::i;:::-;13338:9;13330:6;13326:22;13321:2;13310:9;13306:18;13299:50;13366:32;13391:6;13383;13366:32;:::i;13631:1035::-;13776:6;13784;13792;13800;13808;13861:3;13849:9;13840:7;13836:23;13832:33;13829:53;;;13878:1;13875;13868:12;13829:53;13901:27;13918:9;13901:27;:::i;:::-;13891:37;;13979:2;13968:9;13964:18;13951:32;14002:18;14043:2;14035:6;14032:14;14029:34;;;14059:1;14056;14049:12;14029:34;14082:49;14123:7;14114:6;14103:9;14099:22;14082:49;:::i;:::-;14072:59;;14184:2;14173:9;14169:18;14156:32;14140:48;;14213:2;14203:8;14200:16;14197:36;;;14229:1;14226;14219:12;14197:36;14252:63;14307:7;14296:8;14285:9;14281:24;14252:63;:::i;14671:196::-;14739:20;;-1:-1:-1;;;;;14788:54:1;;14778:65;;14768:93;;14857:1;14854;14847:12;14872:186;14931:6;14984:2;14972:9;14963:7;14959:23;14955:32;14952:52;;;15000:1;14997;14990:12;14952:52;15023:29;15042:9;15023:29;:::i;15063:409::-;15149:6;15157;15165;15173;15226:3;15214:9;15205:7;15201:23;15197:33;15194:53;;;15243:1;15240;15233:12;15194:53;15266:29;15285:9;15266:29;:::i;:::-;15256:39;;15314:38;15348:2;15337:9;15333:18;15314:38;:::i;:::-;15304:48;;15371:38;15405:2;15394:9;15390:18;15371:38;:::i;:::-;15361:48;;15428:38;15462:2;15451:9;15447:18;15428:38;:::i;:::-;15418:48;;15063:409;;;;;;;:::o;15477:277::-;15544:6;15597:2;15585:9;15576:7;15572:23;15568:32;15565:52;;;15613:1;15610;15603:12;15565:52;15645:9;15639:16;15698:5;15691:13;15684:21;15677:5;15674:32;15664:60;;15720:1;15717;15710:12;16473:374;16686:10;16678:6;16674:23;16663:9;16656:42;16734:6;16729:2;16718:9;16714:18;16707:34;16777:2;16772;16761:9;16757:18;16750:30;16637:4;16797:44;16837:2;16826:9;16822:18;16814:6;16797:44;:::i;16852:184::-;16922:6;16975:2;16963:9;16954:7;16950:23;16946:32;16943:52;;;16991:1;16988;16981:12;16943:52;-1:-1:-1;17014:16:1;;16852:184;-1:-1:-1;16852:184:1:o;17041:447::-;17282:10;17274:6;17270:23;17259:9;17252:42;17330:6;17325:2;17314:9;17310:18;17303:34;17373:6;17368:2;17357:9;17353:18;17346:34;17416:3;17411:2;17400:9;17396:18;17389:31;17233:4;17437:45;17477:3;17466:9;17462:19;17454:6;17437:45;:::i;:::-;17429:53;17041:447;-1:-1:-1;;;;;;17041:447:1:o;17493:647::-;17572:6;17625:2;17613:9;17604:7;17600:23;17596:32;17593:52;;;17641:1;17638;17631:12;17593:52;17674:9;17668:16;17707:18;17699:6;17696:30;17693:50;;;17739:1;17736;17729:12;17693:50;17762:22;;17815:4;17807:13;;17803:27;-1:-1:-1;17793:55:1;;17844:1;17841;17834:12;17793:55;17873:2;17867:9;17898:48;17914:31;17942:2;17914:31;:::i;17898:48::-;17969:2;17962:5;17955:17;18009:7;18004:2;17999;17995;17991:11;17987:20;17984:33;17981:53;;;18030:1;18027;18020:12;17981:53;18043:67;18107:2;18102;18095:5;18091:14;18086:2;18082;18078:11;18043:67;:::i;18145:1061::-;18493:10;18485:6;18481:23;18470:9;18463:42;18444:4;18524:2;18562:6;18557:2;18546:9;18542:18;18535:34;18605:3;18600:2;18589:9;18585:18;18578:31;18632:45;18672:3;18661:9;18657:19;18649:6;18632:45;:::i;:::-;18708:2;18693:18;;18686:34;;;18757:22;;;18751:3;18736:19;;18729:51;18829:13;;18851:22;;;18927:15;;;;18889;;;-1:-1:-1;18970:210:1;18984:6;18981:1;18978:13;18970:210;;;19049:13;;19064:34;19045:54;19033:67;;19155:15;;;;19120:12;;;;19006:1;18999:9;18970:210;;;-1:-1:-1;19197:3:1;;18145:1061;-1:-1:-1;;;;;;;;;;18145:1061:1:o;19211:184::-;19263:77;19260:1;19253:88;19360:4;19357:1;19350:15;19384:4;19381:1;19374:15;19400:380;19490:4;19548:11;19535:25;19638:66;19627:8;19611:14;19607:29;19603:102;19583:18;19579:127;19569:155;;19720:1;19717;19710:12;19569:155;19741:33;;;;;19400:380;-1:-1:-1;;19400:380:1:o;19785:580::-;19862:4;19868:6;19928:11;19915:25;20018:66;20007:8;19991:14;19987:29;19983:102;19963:18;19959:127;19949:155;;20100:1;20097;20090:12;19949:155;20127:33;;20179:20;;;-1:-1:-1;20222:18:1;20211:30;;20208:50;;;20254:1;20251;20244:12;20208:50;20287:4;20275:17;;-1:-1:-1;20318:14:1;20314:27;;;20304:38;;20301:58;;;20355:1;20352;20345:12;20370:271;20553:6;20545;20540:3;20527:33;20509:3;20579:16;;20604:13;;;20579:16;20370:271;-1:-1:-1;20370:271:1:o;20646:626::-;20890:4;20919:10;20968:2;20960:6;20956:15;20945:9;20938:34;21020:2;21012:6;21008:15;21003:2;20992:9;20988:18;20981:43;21060:6;21055:2;21044:9;21040:18;21033:34;21115:2;21107:6;21103:15;21098:2;21087:9;21083:18;21076:43;;21156:6;21150:3;21139:9;21135:19;21128:35;21200:3;21194;21183:9;21179:19;21172:32;21221:45;21261:3;21250:9;21246:19;21238:6;21221:45;:::i;:::-;21213:53;20646:626;-1:-1:-1;;;;;;;;20646:626:1:o;21687:617::-;21962:4;21954:6;21950:17;21939:9;21932:36;22004:3;21999:2;21988:9;21984:18;21977:31;21913:4;22031:45;22071:3;22060:9;22056:19;22048:6;22031:45;:::i;:::-;22124:9;22116:6;22112:22;22107:2;22096:9;22092:18;22085:50;22158:32;22183:6;22175;22158:32;:::i;:::-;22144:46;;22238:9;22230:6;22226:22;22221:2;22210:9;22206:18;22199:50;22266:32;22291:6;22283;22266:32;:::i;22309:455::-;22538:4;22530:6;22526:17;22515:9;22508:36;22580:2;22575;22564:9;22560:18;22553:30;22489:4;22606:44;22646:2;22635:9;22631:18;22623:6;22606:44;:::i;:::-;22698:9;22690:6;22686:22;22681:2;22670:9;22666:18;22659:50;22726:32;22751:6;22743;22726:32;:::i;22951:249::-;23020:6;23073:2;23061:9;23052:7;23048:23;23044:32;23041:52;;;23089:1;23086;23079:12;23041:52;23121:9;23115:16;23140:30;23164:5;23140:30;:::i;23205:784::-;23304:6;23357:2;23345:9;23336:7;23332:23;23328:32;23325:52;;;23373:1;23370;23363:12;23325:52;23406:2;23400:9;23448:2;23440:6;23436:15;23517:6;23505:10;23502:22;23481:18;23469:10;23466:34;23463:62;23460:88;;;23528:18;;:::i;:::-;23564:2;23557:22;23601:16;;23646:1;23636:12;;23626:40;;23662:1;23659;23652:12;23626:40;23675:21;;23741:2;23726:18;;23720:25;23754:32;23720:25;23754:32;:::i;:::-;23814:2;23802:15;;23795:32;23872:2;23857:18;;23851:25;23885:32;23851:25;23885:32;:::i;:::-;23945:2;23933:15;;23926:32;23937:6;23205:784;-1:-1:-1;;;23205:784:1:o;23994:585::-;24253:10;24245:6;24241:23;24230:9;24223:42;-1:-1:-1;;;;;24305:6:1;24301:55;24296:2;24285:9;24281:18;24274:83;24393:3;24388:2;24377:9;24373:18;24366:31;24204:4;24420:45;24460:3;24449:9;24445:19;24437:6;24420:45;:::i;:::-;24513:9;24505:6;24501:22;24496:2;24485:9;24481:18;24474:50;24541:32;24566:6;24558;24541:32;:::i;24584:437::-;24663:1;24659:12;;;;24706;;;24727:61;;24781:4;24773:6;24769:17;24759:27;;24727:61;24834:2;24826:6;24823:14;24803:18;24800:38;24797:218;;24871:77;24868:1;24861:88;24972:4;24969:1;24962:15;25000:4;24997:1;24990:15;26047:184;26099:77;26096:1;26089:88;26196:4;26193:1;26186:15;26220:4;26217:1;26210:15;26236:184;26288:77;26285:1;26278:88;26385:4;26382:1;26375:15;26409:4;26406:1;26399:15;26425:125;26490:9;;;26511:10;;;26508:36;;;26524:18;;:::i;26555:168::-;26628:9;;;26659;;26676:15;;;26670:22;;26656:37;26646:71;;26697:18;;:::i;26728:195::-;26767:3;-1:-1:-1;;26791:5:1;26788:77;26785:103;;26868:18;;:::i;:::-;-1:-1:-1;26915:1:1;26904:13;;26728:195::o;26928:128::-;26995:9;;;27016:11;;;27013:37;;;27030:18;;:::i;27186:544::-;27287:2;27282:3;27279:11;27276:448;;;27323:1;27348:5;27344:2;27337:17;27393:4;27389:2;27379:19;27463:2;27451:10;27447:19;27444:1;27440:27;27434:4;27430:38;27499:4;27487:10;27484:20;27481:47;;;-1:-1:-1;27522:4:1;27481:47;27577:2;27572:3;27568:12;27565:1;27561:20;27555:4;27551:31;27541:41;;27632:82;27650:2;27643:5;27640:13;27632:82;;;27695:17;;;27676:1;27665:13;27632:82;;27966:1467;28090:3;28084:10;28117:18;28109:6;28106:30;28103:56;;;28139:18;;:::i;:::-;28168:96;28257:6;28217:38;28249:4;28243:11;28217:38;:::i;:::-;28211:4;28168:96;:::i;:::-;28319:4;;28383:2;28372:14;;28400:1;28395:781;;;;29220:1;29237:6;29234:89;;;-1:-1:-1;29289:19:1;;;29283:26;29234:89;-1:-1:-1;;27863:1:1;27859:11;;;27855:84;27851:89;27841:100;27947:1;27943:11;;;27838:117;29336:81;;28365:1062;;28395:781;27133:1;27126:14;;;27170:4;27157:18;;-1:-1:-1;;28431:79:1;;;28607:236;28621:7;28618:1;28615:14;28607:236;;;28710:19;;;28704:26;28689:42;;28802:27;;;;28770:1;28758:14;;;;28637:19;;28607:236;;;28611:3;28871:6;28862:7;28859:19;28856:261;;;28932:19;;;28926:26;-1:-1:-1;;29015:1:1;29011:14;;;29027:3;29007:24;29003:97;28999:102;28984:118;28969:134;;28856:261;-1:-1:-1;;;;;29163:1:1;29147:14;;;29143:22;29130:36;;-1:-1:-1;27966:1467:1:o;30211:274::-;30251:1;30277;30267:189;;30312:77;30309:1;30302:88;30413:4;30410:1;30403:15;30441:4;30438:1;30431:15;30267:189;-1:-1:-1;30470:9:1;;30211:274::o","abiDefinition":[{"inputs":[{"internalType":"uint32","name":"synapseDomain_","type":"uint32"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"AgentNotActive","type":"error"},{"inputs":[],"name":"AgentNotActiveNorUnstaking","type":"error"},{"inputs":[],"name":"AgentNotGuard","type":"error"},{"inputs":[],"name":"AgentNotNotary","type":"error"},{"inputs":[],"name":"AgentUnknown","type":"error"},{"inputs":[],"name":"CallerNotDestination","type":"error"},{"inputs":[],"name":"IncorrectAgentDomain","type":"error"},{"inputs":[],"name":"IncorrectSnapshotProof","type":"error"},{"inputs":[],"name":"IncorrectSnapshotRoot","type":"error"},{"inputs":[],"name":"IncorrectTipsProof","type":"error"},{"inputs":[],"name":"IncorrectVersionLength","type":"error"},{"inputs":[],"name":"IndexOutOfRange","type":"error"},{"inputs":[],"name":"IndexedTooMuch","type":"error"},{"inputs":[],"name":"MustBeSynapseDomain","type":"error"},{"inputs":[],"name":"OccupiedMemory","type":"error"},{"inputs":[],"name":"PrecompileOutOfGas","type":"error"},{"inputs":[],"name":"TreeHeightTooLow","type":"error"},{"inputs":[],"name":"UnallocatedMemory","type":"error"},{"inputs":[],"name":"UnformattedAttestation","type":"error"},{"inputs":[],"name":"UnformattedReceipt","type":"error"},{"inputs":[],"name":"UnformattedSnapshot","type":"error"},{"inputs":[],"name":"UnformattedState","type":"error"},{"inputs":[],"name":"ViewOverrun","type":"error"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint32","name":"domain","type":"uint32"},{"indexed":false,"internalType":"address","name":"notary","type":"address"},{"indexed":false,"internalType":"bytes","name":"attPayload","type":"bytes"},{"indexed":false,"internalType":"bytes","name":"attSignature","type":"bytes"}],"name":"AttestationAccepted","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint8","name":"version","type":"uint8"}],"name":"Initialized","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"bytes","name":"attPayload","type":"bytes"},{"indexed":false,"internalType":"bytes","name":"attSignature","type":"bytes"}],"name":"InvalidAttestation","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"bytes","name":"arPayload","type":"bytes"},{"indexed":false,"internalType":"bytes","name":"arSignature","type":"bytes"}],"name":"InvalidAttestationReport","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"bytes","name":"rcptPayload","type":"bytes"},{"indexed":false,"internalType":"bytes","name":"rcptSignature","type":"bytes"}],"name":"InvalidReceipt","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"bytes","name":"rrPayload","type":"bytes"},{"indexed":false,"internalType":"bytes","name":"rrSignature","type":"bytes"}],"name":"InvalidReceiptReport","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"bytes","name":"srPayload","type":"bytes"},{"indexed":false,"internalType":"bytes","name":"srSignature","type":"bytes"}],"name":"InvalidStateReport","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint8","name":"stateIndex","type":"uint8"},{"indexed":false,"internalType":"bytes","name":"statePayload","type":"bytes"},{"indexed":false,"internalType":"bytes","name":"attPayload","type":"bytes"},{"indexed":false,"internalType":"bytes","name":"attSignature","type":"bytes"}],"name":"InvalidStateWithAttestation","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint8","name":"stateIndex","type":"uint8"},{"indexed":false,"internalType":"bytes","name":"snapPayload","type":"bytes"},{"indexed":false,"internalType":"bytes","name":"snapSignature","type":"bytes"}],"name":"InvalidStateWithSnapshot","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":"uint32","name":"domain","type":"uint32"},{"indexed":false,"internalType":"address","name":"notary","type":"address"},{"indexed":false,"internalType":"bytes","name":"rcptPayload","type":"bytes"},{"indexed":false,"internalType":"bytes","name":"rcptSignature","type":"bytes"}],"name":"ReceiptAccepted","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint32","name":"domain","type":"uint32"},{"indexed":true,"internalType":"address","name":"agent","type":"address"},{"indexed":false,"internalType":"bytes","name":"snapPayload","type":"bytes"},{"indexed":false,"internalType":"bytes","name":"snapSignature","type":"bytes"}],"name":"SnapshotAccepted","type":"event"},{"inputs":[],"name":"acceptOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"agentManager","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"destination","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"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":"address","name":"agentManager_","type":"address"},{"internalType":"address","name":"origin_","type":"address"},{"internalType":"address","name":"destination_","type":"address"},{"internalType":"address","name":"summit_","type":"address"}],"name":"initialize","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":"origin","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"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":[],"name":"pendingOwner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"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":"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":[],"name":"summit","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"synapseDomain","outputs":[{"internalType":"uint32","name":"","type":"uint32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"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"},{"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"},{"inputs":[],"name":"version","outputs":[{"internalType":"string","name":"versionString","type":"string"}],"stateMutability":"view","type":"function"}],"userDoc":{"events":{"AttestationAccepted(uint32,address,bytes,bytes)":{"notice":"Emitted when a snapshot is accepted by the Destination contract."},"InvalidAttestation(bytes,bytes)":{"notice":"Emitted when a proof of invalid attestation is submitted."},"InvalidAttestationReport(bytes,bytes)":{"notice":"Emitted when a proof of invalid attestation report is submitted."},"InvalidReceipt(bytes,bytes)":{"notice":"Emitted when a proof of invalid receipt statement is submitted."},"InvalidReceiptReport(bytes,bytes)":{"notice":"Emitted when a proof of invalid receipt report is submitted."},"InvalidStateReport(bytes,bytes)":{"notice":"Emitted when a proof of invalid state report is submitted."},"InvalidStateWithAttestation(uint8,bytes,bytes,bytes)":{"notice":"Emitted when a proof of invalid state in the signed attestation is submitted."},"InvalidStateWithSnapshot(uint8,bytes,bytes)":{"notice":"Emitted when a proof of invalid state in the signed snapshot is submitted."},"ReceiptAccepted(uint32,address,bytes,bytes)":{"notice":"Emitted when a snapshot is accepted by the Summit contract."},"SnapshotAccepted(uint32,address,bytes,bytes)":{"notice":"Emitted when a snapshot is accepted by the Summit contract."}},"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."},"initialize(address,address,address,address)":{"notice":"Initializes `Inbox` contract: - Sets `msg.sender` as the owner of the contract - Sets `agentManager`, `origin`, `destination` and `summit` addresses"},"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`."},"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."},"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"},"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."},"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."}},"notice":"`Inbox` is the child of `StatementInbox` contract, that is used on Synapse Chain. In addition to the functionality of `StatementInbox`, it also: - Accepts Guard and Notary Snapshots and passes them to `Summit` contract. - Accepts Notary-signed Receipts and passes them to `Summit` contract. - Accepts Receipt Reports to initiate a dispute between Guard and Notary. - Verifies Attestations and Attestation Reports, and slashes the signer if they are invalid.","version":1},"developerDoc":{"kind":"dev","methods":{"acceptOwnership()":{"details":"The new owner accepts the ownership transfer."},"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"}},"owner()":{"details":"Returns the address of the current owner."},"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"}},"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"},"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."}},"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)"}},"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."},"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."}},"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\":\"uint32\",\"name\":\"synapseDomain_\",\"type\":\"uint32\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[],\"name\":\"AgentNotActive\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"AgentNotActiveNorUnstaking\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"AgentNotGuard\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"AgentNotNotary\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"AgentUnknown\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"CallerNotDestination\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"IncorrectAgentDomain\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"IncorrectSnapshotProof\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"IncorrectSnapshotRoot\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"IncorrectTipsProof\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"IncorrectVersionLength\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"IndexOutOfRange\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"IndexedTooMuch\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"MustBeSynapseDomain\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OccupiedMemory\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"PrecompileOutOfGas\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"TreeHeightTooLow\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"UnallocatedMemory\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"UnformattedAttestation\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"UnformattedReceipt\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"UnformattedSnapshot\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"UnformattedState\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ViewOverrun\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint32\",\"name\":\"domain\",\"type\":\"uint32\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"notary\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"attPayload\",\"type\":\"bytes\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"attSignature\",\"type\":\"bytes\"}],\"name\":\"AttestationAccepted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint8\",\"name\":\"version\",\"type\":\"uint8\"}],\"name\":\"Initialized\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"attPayload\",\"type\":\"bytes\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"attSignature\",\"type\":\"bytes\"}],\"name\":\"InvalidAttestation\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"arPayload\",\"type\":\"bytes\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"arSignature\",\"type\":\"bytes\"}],\"name\":\"InvalidAttestationReport\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"rcptPayload\",\"type\":\"bytes\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"rcptSignature\",\"type\":\"bytes\"}],\"name\":\"InvalidReceipt\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"rrPayload\",\"type\":\"bytes\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"rrSignature\",\"type\":\"bytes\"}],\"name\":\"InvalidReceiptReport\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"srPayload\",\"type\":\"bytes\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"srSignature\",\"type\":\"bytes\"}],\"name\":\"InvalidStateReport\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint8\",\"name\":\"stateIndex\",\"type\":\"uint8\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"statePayload\",\"type\":\"bytes\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"attPayload\",\"type\":\"bytes\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"attSignature\",\"type\":\"bytes\"}],\"name\":\"InvalidStateWithAttestation\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint8\",\"name\":\"stateIndex\",\"type\":\"uint8\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"snapPayload\",\"type\":\"bytes\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"snapSignature\",\"type\":\"bytes\"}],\"name\":\"InvalidStateWithSnapshot\",\"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\":\"uint32\",\"name\":\"domain\",\"type\":\"uint32\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"notary\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"rcptPayload\",\"type\":\"bytes\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"rcptSignature\",\"type\":\"bytes\"}],\"name\":\"ReceiptAccepted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint32\",\"name\":\"domain\",\"type\":\"uint32\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"agent\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"snapPayload\",\"type\":\"bytes\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"snapSignature\",\"type\":\"bytes\"}],\"name\":\"SnapshotAccepted\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"acceptOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"agentManager\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"destination\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"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\":\"address\",\"name\":\"agentManager_\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"origin_\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"destination_\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"summit_\",\"type\":\"address\"}],\"name\":\"initialize\",\"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\":\"origin\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"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\":[],\"name\":\"pendingOwner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"renounceOwnership\",\"outputs\":[],\"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\":\"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\":[],\"name\":\"summit\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"synapseDomain\",\"outputs\":[{\"internalType\":\"uint32\",\"name\":\"\",\"type\":\"uint32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"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\"},{\"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\"},{\"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.\"},\"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\"}},\"owner()\":{\"details\":\"Returns the address of the current owner.\"},\"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\"}},\"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\"},\"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.\"}},\"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)\"}},\"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.\"},\"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.\"}},\"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\":{\"events\":{\"AttestationAccepted(uint32,address,bytes,bytes)\":{\"notice\":\"Emitted when a snapshot is accepted by the Destination contract.\"},\"InvalidAttestation(bytes,bytes)\":{\"notice\":\"Emitted when a proof of invalid attestation is submitted.\"},\"InvalidAttestationReport(bytes,bytes)\":{\"notice\":\"Emitted when a proof of invalid attestation report is submitted.\"},\"InvalidReceipt(bytes,bytes)\":{\"notice\":\"Emitted when a proof of invalid receipt statement is submitted.\"},\"InvalidReceiptReport(bytes,bytes)\":{\"notice\":\"Emitted when a proof of invalid receipt report is submitted.\"},\"InvalidStateReport(bytes,bytes)\":{\"notice\":\"Emitted when a proof of invalid state report is submitted.\"},\"InvalidStateWithAttestation(uint8,bytes,bytes,bytes)\":{\"notice\":\"Emitted when a proof of invalid state in the signed attestation is submitted.\"},\"InvalidStateWithSnapshot(uint8,bytes,bytes)\":{\"notice\":\"Emitted when a proof of invalid state in the signed snapshot is submitted.\"},\"ReceiptAccepted(uint32,address,bytes,bytes)\":{\"notice\":\"Emitted when a snapshot is accepted by the Summit contract.\"},\"SnapshotAccepted(uint32,address,bytes,bytes)\":{\"notice\":\"Emitted when a snapshot is accepted by the Summit contract.\"}},\"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.\"},\"initialize(address,address,address,address)\":{\"notice\":\"Initializes `Inbox` contract: - Sets `msg.sender` as the owner of the contract - Sets `agentManager`, `origin`, `destination` and `summit` addresses\"},\"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`.\"},\"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.\"},\"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\"},\"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.\"},\"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.\"}},\"notice\":\"`Inbox` is the child of `StatementInbox` contract, that is used on Synapse Chain. In addition to the functionality of `StatementInbox`, it also: - Accepts Guard and Notary Snapshots and passes them to `Summit` contract. - Accepts Notary-signed Receipts and passes them to `Summit` contract. - Accepts Receipt Reports to initiate a dispute between Guard and Notary. - Verifies Attestations and Attestation Reports, and slashes the signer if they are invalid.\",\"version\":1}},\"settings\":{\"compilationTarget\":{\"solidity/Inbox.sol\":\"Inbox\"},\"evmVersion\":\"london\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\"},\"optimizer\":{\"enabled\":true,\"runs\":10000},\"remappings\":[]},\"sources\":{\"solidity/Inbox.sol\":{\"keccak256\":\"0x9b516081a036814c0169e20e484d4a5499066b7a6f48fada952b5e844a1ca3e5\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://32bde393b3f24ef4307d9626d4143f337b3c0bd34e17bb969fd5a15221d96987\",\"dweb:/ipfs/QmTkt2XZRtgsbSpmsVQUM3c4ebETQoDVYbmEV9yheBghnr\"]}},\"version\":1}"},"hashes":{"acceptOwnership()":"79ba5097","agentManager()":"7622f78d","destination()":"b269681d","getGuardReport(uint256)":"c495912b","getReportsAmount()":"756ed01d","getStoredSignature(uint256)":"ddeffa66","initialize(address,address,address,address)":"f8c8765e","localDomain()":"8d3638f4","multicall((bool,bytes)[])":"60fc8466","origin()":"938b5f32","owner()":"8da5cb5b","passReceipt(uint32,uint32,uint256,bytes)":"6b47b3bc","pendingOwner()":"e30c3978","renounceOwnership()":"715018a6","submitReceipt(bytes,bytes,uint256,bytes32,bytes32)":"b2a4b455","submitReceiptReport(bytes,bytes,bytes)":"89246503","submitSnapshot(bytes,bytes)":"4bb73ea5","submitStateReportWithAttestation(uint8,bytes,bytes,bytes,bytes)":"243b9224","submitStateReportWithSnapshot(uint8,bytes,bytes,bytes)":"333138e2","submitStateReportWithSnapshotProof(uint8,bytes,bytes,bytes32[],bytes,bytes)":"be7e63da","summit()":"9fbcb9cb","synapseDomain()":"717b8638","transferOwnership(address)":"f2fde38b","verifyAttestation(bytes,bytes)":"0ca77473","verifyAttestationReport(bytes,bytes)":"31e8df5a","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","version()":"54fd4d50"}},"solidity/Inbox.sol:InboxEvents":{"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/InboxEvents.sol\n\nabstract contract InboxEvents {\n /**\n * @notice Emitted when a snapshot is accepted by the Summit contract.\n * @param domain Domain where the signed Agent is active (ZERO for Guards)\n * @param agent Agent who signed the snapshot\n * @param snapPayload Raw payload with snapshot data\n * @param snapSignature Agent signature for the snapshot\n */\n event SnapshotAccepted(uint32 indexed domain, address indexed agent, bytes snapPayload, bytes snapSignature);\n\n /**\n * @notice Emitted when a snapshot is accepted by the Summit contract.\n * @param domain Domain where the signed Notary is active\n * @param notary Notary who signed the attestation\n * @param rcptPayload Raw payload with receipt data\n * @param rcptSignature Notary signature for the receipt\n */\n event ReceiptAccepted(uint32 domain, address notary, bytes rcptPayload, bytes rcptSignature);\n\n /**\n * @notice Emitted when a proof of invalid attestation is submitted.\n * @param attPayload Raw payload with Attestation data\n * @param attSignature Notary signature for the attestation\n */\n event InvalidAttestation(bytes attPayload, bytes attSignature);\n\n /**\n * @notice Emitted when a proof of invalid attestation report is submitted.\n * @param arPayload Raw payload with report data\n * @param arSignature Guard signature for the report\n */\n event InvalidAttestationReport(bytes arPayload, bytes arSignature);\n}\n\n// contracts/events/StatementInboxEvents.sol\n\nabstract contract StatementInboxEvents {\n // ════════════════════════════════════════════ STATEMENT ACCEPTED ═════════════════════════════════════════════════\n\n /**\n * @notice Emitted when a snapshot is accepted by the Destination contract.\n * @param domain Domain where the signed Notary is active\n * @param notary Notary who signed the attestation\n * @param attPayload Raw payload with attestation data\n * @param attSignature Notary signature for the attestation\n */\n event AttestationAccepted(uint32 domain, address notary, bytes attPayload, bytes attSignature);\n\n // ═════════════════════════════════════════ INVALID STATEMENT PROVED ══════════════════════════════════════════════\n\n /**\n * @notice Emitted when a proof of invalid receipt statement is submitted.\n * @param rcptPayload Raw payload with the receipt statement\n * @param rcptSignature Notary signature for the receipt statement\n */\n event InvalidReceipt(bytes rcptPayload, bytes rcptSignature);\n\n /**\n * @notice Emitted when a proof of invalid receipt report is submitted.\n * @param rrPayload Raw payload with report data\n * @param rrSignature Guard signature for the report\n */\n event InvalidReceiptReport(bytes rrPayload, bytes rrSignature);\n\n /**\n * @notice Emitted when a proof of invalid state in the signed attestation is submitted.\n * @param stateIndex Index of invalid state in the snapshot\n * @param statePayload Raw payload with state data\n * @param attPayload Raw payload with Attestation data for snapshot\n * @param attSignature Notary signature for the attestation\n */\n event InvalidStateWithAttestation(uint8 stateIndex, bytes statePayload, bytes attPayload, bytes attSignature);\n\n /**\n * @notice Emitted when a proof of invalid state in the signed snapshot is submitted.\n * @param stateIndex Index of invalid state in the snapshot\n * @param snapPayload Raw payload with snapshot data\n * @param snapSignature Agent signature for the snapshot\n */\n event InvalidStateWithSnapshot(uint8 stateIndex, bytes snapPayload, bytes snapSignature);\n\n /**\n * @notice Emitted when a proof of invalid state report is submitted.\n * @param srPayload Raw payload with report data\n * @param srSignature Guard signature for the report\n */\n event InvalidStateReport(bytes srPayload, bytes srSignature);\n}\n\n// contracts/interfaces/ISnapshotHub.sol\n\ninterface ISnapshotHub {\n /**\n * @notice Check that a given attestation is valid: matches the historical attestation\n * derived from an accepted Notary snapshot.\n * @dev Will revert if any of these is true:\n * - Attestation payload is not properly formatted.\n * @param attPayload Raw payload with attestation data\n * @return isValid Whether the provided attestation is valid\n */\n function isValidAttestation(bytes memory attPayload) external view returns (bool isValid);\n\n /**\n * @notice Returns saved attestation with the given nonce.\n * @dev Reverts if attestation with given nonce hasn't been created yet.\n * @param attNonce Nonce for the attestation\n * @return attPayload Raw payload with formatted Attestation data\n * @return agentRoot Agent root hash used for the attestation\n * @return snapGas Snapshot gas data used for the attestation\n */\n function getAttestation(uint32 attNonce)\n external\n view\n returns (bytes memory attPayload, bytes32 agentRoot, uint256[] memory snapGas);\n\n /**\n * @notice Returns the state with the highest known nonce submitted by a given Agent.\n * @param origin Domain of origin chain\n * @param agent Agent address\n * @return statePayload Raw payload with agent's latest state for origin\n */\n function getLatestAgentState(uint32 origin, address agent) external view returns (bytes memory statePayload);\n\n /**\n * @notice Returns latest saved attestation for a Notary.\n * @param notary Notary address\n * @return attPayload Raw payload with formatted Attestation data\n * @return agentRoot Agent root hash used for the attestation\n * @return snapGas Snapshot gas data used for the attestation\n */\n function getLatestNotaryAttestation(address notary)\n external\n view\n returns (bytes memory attPayload, bytes32 agentRoot, uint256[] memory snapGas);\n\n /**\n * @notice Returns Guard snapshot from the list of all accepted Guard snapshots.\n * @dev Reverts if snapshot with given index hasn't been accepted yet.\n * @param index Snapshot index in the list of all Guard snapshots\n * @return snapPayload Raw payload with Guard snapshot\n * @return snapSignature Raw payload with Guard signature for snapshot\n */\n function getGuardSnapshot(uint256 index)\n external\n view\n returns (bytes memory snapPayload, bytes memory snapSignature);\n\n /**\n * @notice Returns Notary snapshot from the list of all accepted Guard snapshots.\n * @dev Reverts if snapshot with given index hasn't been accepted yet.\n * @param index Snapshot index in the list of all Notary snapshots\n * @return snapPayload Raw payload with Notary snapshot\n * @return snapSignature Raw payload with Notary signature for snapshot\n */\n function getNotarySnapshot(uint256 index)\n external\n view\n returns (bytes memory snapPayload, bytes memory snapSignature);\n\n /**\n * @notice Returns Notary snapshot that was used for creating a given attestation.\n * @dev Reverts if any of these is true:\n * - Attestation payload is not properly formatted.\n * - Attestation is invalid (doesn't have a matching Notary snapshot).\n * @param attPayload Raw payload with attestation data\n * @return snapPayload Raw payload with Notary snapshot\n * @return snapSignature Raw payload with Notary signature for snapshot\n */\n function getNotarySnapshot(bytes memory attPayload)\n external\n view\n returns (bytes memory snapPayload, bytes memory snapSignature);\n\n /**\n * @notice Returns proof of inclusion of (root, origin) fields of a given snapshot's state\n * into the Snapshot Merkle Tree for a given attestation.\n * @dev Reverts if any of these is true:\n * - Attestation with given nonce hasn't been created yet.\n * - State index is out of range of snapshot list.\n * @param attNonce Nonce for the attestation\n * @param stateIndex Index of state in the attestation's snapshot\n * @return snapProof The snapshot proof\n */\n function getSnapshotProof(uint32 attNonce, uint8 stateIndex) external view returns (bytes32[] memory snapProof);\n}\n\n// contracts/interfaces/IStateHub.sol\n\ninterface IStateHub {\n /**\n * @notice Check that a given state is valid: matches the historical state of Origin contract.\n * Note: any Agent including an invalid state in their snapshot will be slashed\n * upon providing the snapshot and agent signature for it to Origin contract.\n * @dev Will revert if any of these is true:\n * - State payload is not properly formatted.\n * @param statePayload Raw payload with state data\n * @return isValid Whether the provided state is valid\n */\n function isValidState(bytes memory statePayload) external view returns (bool isValid);\n\n /**\n * @notice Returns the amount of saved states so far.\n * @dev This includes the initial state of \"empty Origin Merkle Tree\".\n */\n function statesAmount() external view returns (uint256);\n\n /**\n * @notice Suggest the data (state after latest sent message) to sign for an Agent.\n * Note: signing the suggested state data will will never lead to slashing of the actor,\n * assuming they have confirmed that the block, which number is included in the data,\n * is not subject to reorganization (which is different for every observed chain).\n * @return statePayload Raw payload with the latest state data\n */\n function suggestLatestState() external view returns (bytes memory statePayload);\n\n /**\n * @notice Given the historical nonce, suggest the state data to sign for an Agent.\n * Note: signing the suggested state data will will never lead to slashing of the actor,\n * assuming they have confirmed that the block, which number is included in the data,\n * is not subject to reorganization (which is different for every observed chain).\n * @param nonce Historical nonce to form a state\n * @return statePayload Raw payload with historical state data\n */\n function suggestState(uint32 nonce) external view returns (bytes memory statePayload);\n}\n\n// contracts/interfaces/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/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// node_modules/@openzeppelin/contracts/utils/math/Math.sol\n\n// OpenZeppelin Contracts (last updated v4.9.0) (utils/math/Math.sol)\n\n/**\n * @dev Standard math utilities missing in the Solidity language.\n */\nlibrary Math {\n enum Rounding {\n Down, // Toward negative infinity\n Up, // Toward infinity\n Zero // Toward zero\n }\n\n /**\n * @dev Returns the largest of two numbers.\n */\n function max(uint256 a, uint256 b) internal pure returns (uint256) {\n return a \u003e b ? a : b;\n }\n\n /**\n * @dev Returns the smallest of two numbers.\n */\n function min(uint256 a, uint256 b) internal pure returns (uint256) {\n return a \u003c b ? a : b;\n }\n\n /**\n * @dev Returns the average of two numbers. The result is rounded towards\n * zero.\n */\n function average(uint256 a, uint256 b) internal pure returns (uint256) {\n // (a + b) / 2 can overflow.\n return (a \u0026 b) + (a ^ b) / 2;\n }\n\n /**\n * @dev Returns the ceiling of the division of two numbers.\n *\n * This differs from standard division with `/` in that it rounds up instead\n * of rounding down.\n */\n function ceilDiv(uint256 a, uint256 b) internal pure returns (uint256) {\n // (a + b - 1) / b can overflow on addition, so we distribute.\n return a == 0 ? 0 : (a - 1) / b + 1;\n }\n\n /**\n * @notice Calculates floor(x * y / denominator) with full precision. Throws if result overflows a uint256 or denominator == 0\n * @dev Original credit to Remco Bloemen under MIT license (https://xn--2-umb.com/21/muldiv)\n * with further edits by Uniswap Labs also under MIT license.\n */\n function mulDiv(uint256 x, uint256 y, uint256 denominator) internal pure returns (uint256 result) {\n unchecked {\n // 512-bit multiply [prod1 prod0] = x * y. Compute the product mod 2^256 and mod 2^256 - 1, then use\n // use the Chinese Remainder Theorem to reconstruct the 512 bit result. The result is stored in two 256\n // variables such that product = prod1 * 2^256 + prod0.\n uint256 prod0; // Least significant 256 bits of the product\n uint256 prod1; // Most significant 256 bits of the product\n assembly {\n let mm := mulmod(x, y, not(0))\n prod0 := mul(x, y)\n prod1 := sub(sub(mm, prod0), lt(mm, prod0))\n }\n\n // Handle non-overflow cases, 256 by 256 division.\n if (prod1 == 0) {\n // Solidity will revert if denominator == 0, unlike the div opcode on its own.\n // The surrounding unchecked block does not change this fact.\n // See https://docs.soliditylang.org/en/latest/control-structures.html#checked-or-unchecked-arithmetic.\n return prod0 / denominator;\n }\n\n // Make sure the result is less than 2^256. Also prevents denominator == 0.\n require(denominator \u003e prod1, \"Math: mulDiv overflow\");\n\n ///////////////////////////////////////////////\n // 512 by 256 division.\n ///////////////////////////////////////////////\n\n // Make division exact by subtracting the remainder from [prod1 prod0].\n uint256 remainder;\n assembly {\n // Compute remainder using mulmod.\n remainder := mulmod(x, y, denominator)\n\n // Subtract 256 bit number from 512 bit number.\n prod1 := sub(prod1, gt(remainder, prod0))\n prod0 := sub(prod0, remainder)\n }\n\n // Factor powers of two out of denominator and compute largest power of two divisor of denominator. Always \u003e= 1.\n // See https://cs.stackexchange.com/q/138556/92363.\n\n // Does not overflow because the denominator cannot be zero at this stage in the function.\n uint256 twos = denominator \u0026 (~denominator + 1);\n assembly {\n // Divide denominator by twos.\n denominator := div(denominator, twos)\n\n // Divide [prod1 prod0] by twos.\n prod0 := div(prod0, twos)\n\n // Flip twos such that it is 2^256 / twos. If twos is zero, then it becomes one.\n twos := add(div(sub(0, twos), twos), 1)\n }\n\n // Shift in bits from prod1 into prod0.\n prod0 |= prod1 * twos;\n\n // Invert denominator mod 2^256. Now that denominator is an odd number, it has an inverse modulo 2^256 such\n // that denominator * inv = 1 mod 2^256. Compute the inverse by starting with a seed that is correct for\n // four bits. That is, denominator * inv = 1 mod 2^4.\n uint256 inverse = (3 * denominator) ^ 2;\n\n // Use the Newton-Raphson iteration to improve the precision. Thanks to Hensel's lifting lemma, this also works\n // in modular arithmetic, doubling the correct bits in each step.\n inverse *= 2 - denominator * inverse; // inverse mod 2^8\n inverse *= 2 - denominator * inverse; // inverse mod 2^16\n inverse *= 2 - denominator * inverse; // inverse mod 2^32\n inverse *= 2 - denominator * inverse; // inverse mod 2^64\n inverse *= 2 - denominator * inverse; // inverse mod 2^128\n inverse *= 2 - denominator * inverse; // inverse mod 2^256\n\n // Because the division is now exact we can divide by multiplying with the modular inverse of denominator.\n // This will give us the correct result modulo 2^256. Since the preconditions guarantee that the outcome is\n // less than 2^256, this is the final result. We don't need to compute the high bits of the result and prod1\n // is no longer required.\n result = prod0 * inverse;\n return result;\n }\n }\n\n /**\n * @notice Calculates x * y / denominator with full precision, following the selected rounding direction.\n */\n function mulDiv(uint256 x, uint256 y, uint256 denominator, Rounding rounding) internal pure returns (uint256) {\n uint256 result = mulDiv(x, y, denominator);\n if (rounding == Rounding.Up \u0026\u0026 mulmod(x, y, denominator) \u003e 0) {\n result += 1;\n }\n return result;\n }\n\n /**\n * @dev Returns the square root of a number. If the number is not a perfect square, the value is rounded down.\n *\n * Inspired by Henry S. Warren, Jr.'s \"Hacker's Delight\" (Chapter 11).\n */\n function sqrt(uint256 a) internal pure returns (uint256) {\n if (a == 0) {\n return 0;\n }\n\n // For our first guess, we get the biggest power of 2 which is smaller than the square root of the target.\n //\n // We know that the \"msb\" (most significant bit) of our target number `a` is a power of 2 such that we have\n // `msb(a) \u003c= a \u003c 2*msb(a)`. This value can be written `msb(a)=2**k` with `k=log2(a)`.\n //\n // This can be rewritten `2**log2(a) \u003c= a \u003c 2**(log2(a) + 1)`\n // → `sqrt(2**k) \u003c= sqrt(a) \u003c sqrt(2**(k+1))`\n // → `2**(k/2) \u003c= sqrt(a) \u003c 2**((k+1)/2) \u003c= 2**(k/2 + 1)`\n //\n // Consequently, `2**(log2(a) / 2)` is a good first approximation of `sqrt(a)` with at least 1 correct bit.\n uint256 result = 1 \u003c\u003c (log2(a) \u003e\u003e 1);\n\n // At this point `result` is an estimation with one bit of precision. We know the true value is a uint128,\n // since it is the square root of a uint256. Newton's method converges quadratically (precision doubles at\n // every iteration). We thus need at most 7 iteration to turn our partial result with one bit of precision\n // into the expected uint128 result.\n unchecked {\n result = (result + a / result) \u003e\u003e 1;\n result = (result + a / result) \u003e\u003e 1;\n result = (result + a / result) \u003e\u003e 1;\n result = (result + a / result) \u003e\u003e 1;\n result = (result + a / result) \u003e\u003e 1;\n result = (result + a / result) \u003e\u003e 1;\n result = (result + a / result) \u003e\u003e 1;\n return min(result, a / result);\n }\n }\n\n /**\n * @notice Calculates sqrt(a), following the selected rounding direction.\n */\n function sqrt(uint256 a, Rounding rounding) internal pure returns (uint256) {\n unchecked {\n uint256 result = sqrt(a);\n return result + (rounding == Rounding.Up \u0026\u0026 result * result \u003c a ? 1 : 0);\n }\n }\n\n /**\n * @dev Return the log in base 2, rounded down, of a positive value.\n * Returns 0 if given 0.\n */\n function log2(uint256 value) internal pure returns (uint256) {\n uint256 result = 0;\n unchecked {\n if (value \u003e\u003e 128 \u003e 0) {\n value \u003e\u003e= 128;\n result += 128;\n }\n if (value \u003e\u003e 64 \u003e 0) {\n value \u003e\u003e= 64;\n result += 64;\n }\n if (value \u003e\u003e 32 \u003e 0) {\n value \u003e\u003e= 32;\n result += 32;\n }\n if (value \u003e\u003e 16 \u003e 0) {\n value \u003e\u003e= 16;\n result += 16;\n }\n if (value \u003e\u003e 8 \u003e 0) {\n value \u003e\u003e= 8;\n result += 8;\n }\n if (value \u003e\u003e 4 \u003e 0) {\n value \u003e\u003e= 4;\n result += 4;\n }\n if (value \u003e\u003e 2 \u003e 0) {\n value \u003e\u003e= 2;\n result += 2;\n }\n if (value \u003e\u003e 1 \u003e 0) {\n result += 1;\n }\n }\n return result;\n }\n\n /**\n * @dev Return the log in base 2, following the selected rounding direction, of a positive value.\n * Returns 0 if given 0.\n */\n function log2(uint256 value, Rounding rounding) internal pure returns (uint256) {\n unchecked {\n uint256 result = log2(value);\n return result + (rounding == Rounding.Up \u0026\u0026 1 \u003c\u003c result \u003c value ? 1 : 0);\n }\n }\n\n /**\n * @dev Return the log in base 10, rounded down, of a positive value.\n * Returns 0 if given 0.\n */\n function log10(uint256 value) internal pure returns (uint256) {\n uint256 result = 0;\n unchecked {\n if (value \u003e= 10 ** 64) {\n value /= 10 ** 64;\n result += 64;\n }\n if (value \u003e= 10 ** 32) {\n value /= 10 ** 32;\n result += 32;\n }\n if (value \u003e= 10 ** 16) {\n value /= 10 ** 16;\n result += 16;\n }\n if (value \u003e= 10 ** 8) {\n value /= 10 ** 8;\n result += 8;\n }\n if (value \u003e= 10 ** 4) {\n value /= 10 ** 4;\n result += 4;\n }\n if (value \u003e= 10 ** 2) {\n value /= 10 ** 2;\n result += 2;\n }\n if (value \u003e= 10 ** 1) {\n result += 1;\n }\n }\n return result;\n }\n\n /**\n * @dev Return the log in base 10, following the selected rounding direction, of a positive value.\n * Returns 0 if given 0.\n */\n function log10(uint256 value, Rounding rounding) internal pure returns (uint256) {\n unchecked {\n uint256 result = log10(value);\n return result + (rounding == Rounding.Up \u0026\u0026 10 ** result \u003c value ? 1 : 0);\n }\n }\n\n /**\n * @dev Return the log in base 256, rounded down, of a positive value.\n * Returns 0 if given 0.\n *\n * Adding one to the result gives the number of pairs of hex symbols needed to represent `value` as a hex string.\n */\n function log256(uint256 value) internal pure returns (uint256) {\n uint256 result = 0;\n unchecked {\n if (value \u003e\u003e 128 \u003e 0) {\n value \u003e\u003e= 128;\n result += 16;\n }\n if (value \u003e\u003e 64 \u003e 0) {\n value \u003e\u003e= 64;\n result += 8;\n }\n if (value \u003e\u003e 32 \u003e 0) {\n value \u003e\u003e= 32;\n result += 4;\n }\n if (value \u003e\u003e 16 \u003e 0) {\n value \u003e\u003e= 16;\n result += 2;\n }\n if (value \u003e\u003e 8 \u003e 0) {\n result += 1;\n }\n }\n return result;\n }\n\n /**\n * @dev Return the log in base 256, following the selected rounding direction, of a positive value.\n * Returns 0 if given 0.\n */\n function log256(uint256 value, Rounding rounding) internal pure returns (uint256) {\n unchecked {\n uint256 result = log256(value);\n return result + (rounding == Rounding.Up \u0026\u0026 1 \u003c\u003c (result \u003c\u003c 3) \u003c value ? 1 : 0);\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/utils/math/SignedMath.sol\n\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/math/SignedMath.sol)\n\n/**\n * @dev Standard signed math utilities missing in the Solidity language.\n */\nlibrary SignedMath {\n /**\n * @dev Returns the largest of two signed numbers.\n */\n function max(int256 a, int256 b) internal pure returns (int256) {\n return a \u003e b ? a : b;\n }\n\n /**\n * @dev Returns the smallest of two signed numbers.\n */\n function min(int256 a, int256 b) internal pure returns (int256) {\n return a \u003c b ? a : b;\n }\n\n /**\n * @dev Returns the average of two signed numbers without overflow.\n * The result is rounded towards zero.\n */\n function average(int256 a, int256 b) internal pure returns (int256) {\n // Formula from the book \"Hacker's Delight\"\n int256 x = (a \u0026 b) + ((a ^ b) \u003e\u003e 1);\n return x + (int256(uint256(x) \u003e\u003e 255) \u0026 (a ^ b));\n }\n\n /**\n * @dev Returns the absolute unsigned value of a signed value.\n */\n function abs(int256 n) internal pure returns (uint256) {\n unchecked {\n // must be unchecked in order to support `n = type(int256).min`\n return uint256(n \u003e= 0 ? n : -n);\n }\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// 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/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/InterfaceSummit.sol\n\ninterface InterfaceSummit {\n // ══════════════════════════════════════════ ACCEPT AGENT STATEMENTS ══════════════════════════════════════════════\n\n /**\n * @notice Accepts a receipt, which local `AgentManager` verified to have been signed by an active Notary.\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 * - Notary who signed the receipt is referenced as the \"Receipt Notary\".\n * - Notary who signed the attestation on destination chain is referenced as the \"Attestation Notary\".\n * \u003e Will revert if any of these is true:\n * \u003e - Called by anyone other than local `AgentManager`.\n * \u003e - Receipt body payload is not properly formatted.\n * \u003e - Receipt signer is in Dispute.\n * \u003e - Receipt's snapshot root is unknown.\n * @param rcptNotaryIndex Index of Receipt Notary in Agent Merkle Tree\n * @param attNotaryIndex Index of Attestation Notary in Agent Merkle Tree\n * @param sigIndex Index of stored Notary signature\n * @param attNonce Nonce of the attestation used for proving the executed message\n * @param paddedTips Padded encoded paid tips information\n * @param rcptPayload Raw payload with message execution receipt\n * @return wasAccepted Whether the receipt was accepted\n */\n function acceptReceipt(\n uint32 rcptNotaryIndex,\n uint32 attNotaryIndex,\n uint256 sigIndex,\n uint32 attNonce,\n uint256 paddedTips,\n bytes memory rcptPayload\n ) external returns (bool wasAccepted);\n\n /**\n * @notice Accepts a snapshot, which local `AgentManager` verified to have been signed by an active Guard.\n * \u003e Snapshot is a list of states for a set of Origin contracts residing on any of the chains.\n * All the states in the Guard-signed snapshot become available for Notary signing.\n * \u003e Will revert if any of these is true:\n * \u003e - Called by anyone other than local `AgentManager`.\n * \u003e - Snapshot payload is not properly formatted.\n * \u003e - Snapshot contains a state older then the Guard has previously submitted.\n * @param guardIndex Index of Guard in Agent Merkle Tree\n * @param sigIndex Index of stored Agent signature\n * @param snapPayload Raw payload with snapshot data\n */\n function acceptGuardSnapshot(uint32 guardIndex, uint256 sigIndex, bytes memory snapPayload) external;\n\n /**\n * @notice Accepts a snapshot, which local `AgentManager` verified to have been signed by an active Notary.\n * \u003e Snapshot is a list of states for a set of Origin contracts residing on any of the chains.\n * Snapshot Merkle Root is calculated and saved for valid snapshots, i.e.\n * snapshots which are only using states previously submitted by any of the Guards.\n * - Notary could use states singed by the same of different Guards 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 - Called by anyone other than local `AgentManager`.\n * \u003e - Snapshot payload is not properly formatted.\n * \u003e - Snapshot contains a state older then the Notary has previously submitted.\n * \u003e - Snapshot contains a state that no Guard has previously submitted.\n * @param notaryIndex Index of Notary in Agent Merkle Tree\n * @param sigIndex Index of stored Agent signature\n * @param agentRoot Current root of the Agent Merkle Tree\n * @param snapPayload Raw payload with snapshot data\n * @return attPayload Raw payload with data for attestation derived from Notary snapshot.\n */\n function acceptNotarySnapshot(uint32 notaryIndex, uint256 sigIndex, bytes32 agentRoot, bytes memory snapPayload)\n external\n returns (bytes memory attPayload);\n\n // ════════════════════════════════════════════════ TIPS LOGIC ═════════════════════════════════════════════════════\n\n /**\n * @notice Distributes tips using the first Receipt from the \"receipt quarantine queue\".\n * Possible scenarios:\n * - Receipt queue is empty =\u003e does nothing\n * - Receipt optimistic period is not over =\u003e does nothing\n * - Either of Notaries present in Receipt was slashed =\u003e receipt is deleted from the queue\n * - Either of Notaries present in Receipt in Dispute =\u003e receipt is moved to the end of queue\n * - None of the above =\u003e receipt tips are distributed\n * @dev Returned value makes it possible to do the following: `while (distributeTips()) {}`\n * @return queuePopped Whether the first element was popped from the queue\n */\n function distributeTips() external returns (bool queuePopped);\n\n /**\n * @notice Withdraws locked base message tips from requested domain Origin to the recipient.\n * This is done by a call to a local Origin contract, or by a manager message to the remote chain.\n * @dev This will revert, if the pending balance of origin tips (earned-claimed) is lower than requested.\n * @param origin Domain of chain to withdraw tips on\n * @param amount Amount of tips to withdraw\n */\n function withdrawTips(uint32 origin, uint256 amount) external;\n\n // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════\n\n /**\n * @notice Returns earned and claimed tips for the actor.\n * Note: Tips for address(0) belong to the Treasury.\n * @param actor Address of the actor\n * @param origin Domain where the tips were initially paid\n * @return earned Total amount of origin tips the actor has earned so far\n * @return claimed Total amount of origin tips the actor has claimed so far\n */\n function actorTips(address actor, uint32 origin) external view returns (uint128 earned, uint128 claimed);\n\n /**\n * @notice Returns the amount of receipts in the \"Receipt Quarantine Queue\".\n */\n function receiptQueueLength() external view returns (uint256);\n\n /**\n * @notice Returns the state with the highest known nonce\n * submitted by any of the currently active Guards.\n * @param origin Domain of origin chain\n * @return statePayload Raw payload with latest active Guard state for origin\n */\n function getLatestState(uint32 origin) external view returns (bytes memory statePayload);\n}\n\n// node_modules/@openzeppelin/contracts/utils/Strings.sol\n\n// OpenZeppelin Contracts (last updated v4.9.0) (utils/Strings.sol)\n\n/**\n * @dev String operations.\n */\nlibrary Strings {\n bytes16 private constant _SYMBOLS = \"0123456789abcdef\";\n uint8 private constant _ADDRESS_LENGTH = 20;\n\n /**\n * @dev Converts a `uint256` to its ASCII `string` decimal representation.\n */\n function toString(uint256 value) internal pure returns (string memory) {\n unchecked {\n uint256 length = Math.log10(value) + 1;\n string memory buffer = new string(length);\n uint256 ptr;\n /// @solidity memory-safe-assembly\n assembly {\n ptr := add(buffer, add(32, length))\n }\n while (true) {\n ptr--;\n /// @solidity memory-safe-assembly\n assembly {\n mstore8(ptr, byte(mod(value, 10), _SYMBOLS))\n }\n value /= 10;\n if (value == 0) break;\n }\n return buffer;\n }\n }\n\n /**\n * @dev Converts a `int256` to its ASCII `string` decimal representation.\n */\n function toString(int256 value) internal pure returns (string memory) {\n return string(abi.encodePacked(value \u003c 0 ? \"-\" : \"\", toString(SignedMath.abs(value))));\n }\n\n /**\n * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation.\n */\n function toHexString(uint256 value) internal pure returns (string memory) {\n unchecked {\n return toHexString(value, Math.log256(value) + 1);\n }\n }\n\n /**\n * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length.\n */\n function toHexString(uint256 value, uint256 length) internal pure returns (string memory) {\n bytes memory buffer = new bytes(2 * length + 2);\n buffer[0] = \"0\";\n buffer[1] = \"x\";\n for (uint256 i = 2 * length + 1; i \u003e 1; --i) {\n buffer[i] = _SYMBOLS[value \u0026 0xf];\n value \u003e\u003e= 4;\n }\n require(value == 0, \"Strings: hex length insufficient\");\n return string(buffer);\n }\n\n /**\n * @dev Converts an `address` with fixed length of 20 bytes to its not checksummed ASCII `string` hexadecimal representation.\n */\n function toHexString(address addr) internal pure returns (string memory) {\n return toHexString(uint256(uint160(addr)), _ADDRESS_LENGTH);\n }\n\n /**\n * @dev Returns true if the two strings are equal.\n */\n function equal(string memory a, string memory b) internal pure returns (bool) {\n return keccak256(bytes(a)) == keccak256(bytes(b));\n }\n}\n\n// node_modules/@openzeppelin/contracts-upgradeable/utils/ContextUpgradeable.sol\n\n// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)\n\n/**\n * @dev Provides information about the current execution context, including the\n * sender of the transaction and its data. While these are generally available\n * via msg.sender and msg.data, they should not be accessed in such a direct\n * manner, since when dealing with meta-transactions the account sending and\n * paying for execution may not be the actual sender (as far as an application\n * is concerned).\n *\n * This contract is only required for intermediate, library-like contracts.\n */\nabstract contract ContextUpgradeable is Initializable {\n function __Context_init() internal onlyInitializing {\n }\n\n function __Context_init_unchained() internal onlyInitializing {\n }\n function _msgSender() internal view virtual returns (address) {\n return msg.sender;\n }\n\n function _msgData() internal view virtual returns (bytes calldata) {\n return msg.data;\n }\n\n /**\n * @dev This empty reserved space is put in place to allow future versions to add new\n * variables without shifting down storage in the inheritance chain.\n * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\n */\n uint256[50] private __gap;\n}\n\n// contracts/libs/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/utils/cryptography/ECDSA.sol\n\n// OpenZeppelin Contracts (last updated v4.9.0) (utils/cryptography/ECDSA.sol)\n\n/**\n * @dev Elliptic Curve Digital Signature Algorithm (ECDSA) operations.\n *\n * These functions can be used to verify that a message was signed by the holder\n * of the private keys of a given address.\n */\nlibrary ECDSA {\n enum RecoverError {\n NoError,\n InvalidSignature,\n InvalidSignatureLength,\n InvalidSignatureS,\n InvalidSignatureV // Deprecated in v4.8\n }\n\n function _throwError(RecoverError error) private pure {\n if (error == RecoverError.NoError) {\n return; // no error: do nothing\n } else if (error == RecoverError.InvalidSignature) {\n revert(\"ECDSA: invalid signature\");\n } else if (error == RecoverError.InvalidSignatureLength) {\n revert(\"ECDSA: invalid signature length\");\n } else if (error == RecoverError.InvalidSignatureS) {\n revert(\"ECDSA: invalid signature 's' value\");\n }\n }\n\n /**\n * @dev Returns the address that signed a hashed message (`hash`) with\n * `signature` or error string. This address can then be used for verification purposes.\n *\n * The `ecrecover` EVM opcode allows for malleable (non-unique) signatures:\n * this function rejects them by requiring the `s` value to be in the lower\n * half order, and the `v` value to be either 27 or 28.\n *\n * IMPORTANT: `hash` _must_ be the result of a hash operation for the\n * verification to be secure: it is possible to craft signatures that\n * recover to arbitrary addresses for non-hashed data. A safe way to ensure\n * this is by receiving a hash of the original message (which may otherwise\n * be too long), and then calling {toEthSignedMessageHash} on it.\n *\n * Documentation for signature generation:\n * - with https://web3js.readthedocs.io/en/v1.3.4/web3-eth-accounts.html#sign[Web3.js]\n * - with https://docs.ethers.io/v5/api/signer/#Signer-signMessage[ethers]\n *\n * _Available since v4.3._\n */\n function tryRecover(bytes32 hash, bytes memory signature) internal pure returns (address, RecoverError) {\n if (signature.length == 65) {\n bytes32 r;\n bytes32 s;\n uint8 v;\n // ecrecover takes the signature parameters, and the only way to get them\n // currently is to use assembly.\n /// @solidity memory-safe-assembly\n assembly {\n r := mload(add(signature, 0x20))\n s := mload(add(signature, 0x40))\n v := byte(0, mload(add(signature, 0x60)))\n }\n return tryRecover(hash, v, r, s);\n } else {\n return (address(0), RecoverError.InvalidSignatureLength);\n }\n }\n\n /**\n * @dev Returns the address that signed a hashed message (`hash`) with\n * `signature`. This address can then be used for verification purposes.\n *\n * The `ecrecover` EVM opcode allows for malleable (non-unique) signatures:\n * this function rejects them by requiring the `s` value to be in the lower\n * half order, and the `v` value to be either 27 or 28.\n *\n * IMPORTANT: `hash` _must_ be the result of a hash operation for the\n * verification to be secure: it is possible to craft signatures that\n * recover to arbitrary addresses for non-hashed data. A safe way to ensure\n * this is by receiving a hash of the original message (which may otherwise\n * be too long), and then calling {toEthSignedMessageHash} on it.\n */\n function recover(bytes32 hash, bytes memory signature) internal pure returns (address) {\n (address recovered, RecoverError error) = tryRecover(hash, signature);\n _throwError(error);\n return recovered;\n }\n\n /**\n * @dev Overload of {ECDSA-tryRecover} that receives the `r` and `vs` short-signature fields separately.\n *\n * See https://eips.ethereum.org/EIPS/eip-2098[EIP-2098 short signatures]\n *\n * _Available since v4.3._\n */\n function tryRecover(bytes32 hash, bytes32 r, bytes32 vs) internal pure returns (address, RecoverError) {\n bytes32 s = vs \u0026 bytes32(0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff);\n uint8 v = uint8((uint256(vs) \u003e\u003e 255) + 27);\n return tryRecover(hash, v, r, s);\n }\n\n /**\n * @dev Overload of {ECDSA-recover} that receives the `r and `vs` short-signature fields separately.\n *\n * _Available since v4.2._\n */\n function recover(bytes32 hash, bytes32 r, bytes32 vs) internal pure returns (address) {\n (address recovered, RecoverError error) = tryRecover(hash, r, vs);\n _throwError(error);\n return recovered;\n }\n\n /**\n * @dev Overload of {ECDSA-tryRecover} that receives the `v`,\n * `r` and `s` signature fields separately.\n *\n * _Available since v4.3._\n */\n function tryRecover(bytes32 hash, uint8 v, bytes32 r, bytes32 s) internal pure returns (address, RecoverError) {\n // EIP-2 still allows signature malleability for ecrecover(). Remove this possibility and make the signature\n // unique. Appendix F in the Ethereum Yellow paper (https://ethereum.github.io/yellowpaper/paper.pdf), defines\n // the valid range for s in (301): 0 \u003c s \u003c secp256k1n ÷ 2 + 1, and for v in (302): v ∈ {27, 28}. Most\n // signatures from current libraries generate a unique signature with an s-value in the lower half order.\n //\n // If your library generates malleable signatures, such as s-values in the upper range, calculate a new s-value\n // with 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141 - s1 and flip v from 27 to 28 or\n // vice versa. If your library also generates signatures with 0/1 for v instead 27/28, add 27 to v to accept\n // these malleable signatures as well.\n if (uint256(s) \u003e 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0) {\n return (address(0), RecoverError.InvalidSignatureS);\n }\n\n // If the signature is valid (and not malleable), return the signer address\n address signer = ecrecover(hash, v, r, s);\n if (signer == address(0)) {\n return (address(0), RecoverError.InvalidSignature);\n }\n\n return (signer, RecoverError.NoError);\n }\n\n /**\n * @dev Overload of {ECDSA-recover} that receives the `v`,\n * `r` and `s` signature fields separately.\n */\n function recover(bytes32 hash, uint8 v, bytes32 r, bytes32 s) internal pure returns (address) {\n (address recovered, RecoverError error) = tryRecover(hash, v, r, s);\n _throwError(error);\n return recovered;\n }\n\n /**\n * @dev Returns an Ethereum Signed Message, created from a `hash`. This\n * produces hash corresponding to the one signed with the\n * https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`]\n * JSON-RPC method as part of EIP-191.\n *\n * See {recover}.\n */\n function toEthSignedMessageHash(bytes32 hash) internal pure returns (bytes32 message) {\n // 32 is the length in bytes of hash,\n // enforced by the type signature above\n /// @solidity memory-safe-assembly\n assembly {\n mstore(0x00, \"\\x19Ethereum Signed Message:\\n32\")\n mstore(0x1c, hash)\n message := keccak256(0x00, 0x3c)\n }\n }\n\n /**\n * @dev Returns an Ethereum Signed Message, created from `s`. This\n * produces hash corresponding to the one signed with the\n * https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`]\n * JSON-RPC method as part of EIP-191.\n *\n * See {recover}.\n */\n function toEthSignedMessageHash(bytes memory s) internal pure returns (bytes32) {\n return keccak256(abi.encodePacked(\"\\x19Ethereum Signed Message:\\n\", Strings.toString(s.length), s));\n }\n\n /**\n * @dev Returns an Ethereum Signed Typed Data, created from a\n * `domainSeparator` and a `structHash`. This produces hash corresponding\n * to the one signed with the\n * https://eips.ethereum.org/EIPS/eip-712[`eth_signTypedData`]\n * JSON-RPC method as part of EIP-712.\n *\n * See {recover}.\n */\n function toTypedDataHash(bytes32 domainSeparator, bytes32 structHash) internal pure returns (bytes32 data) {\n /// @solidity memory-safe-assembly\n assembly {\n let ptr := mload(0x40)\n mstore(ptr, \"\\x19\\x01\")\n mstore(add(ptr, 0x02), domainSeparator)\n mstore(add(ptr, 0x22), structHash)\n data := keccak256(ptr, 0x42)\n }\n }\n\n /**\n * @dev Returns an Ethereum Signed Data with intended validator, created from a\n * `validator` and `data` according to the version 0 of EIP-191.\n *\n * See {recover}.\n */\n function toDataWithIntendedValidatorHash(address validator, bytes memory data) internal pure returns (bytes32) {\n return keccak256(abi.encodePacked(\"\\x19\\x00\", validator, data));\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/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/inbox/StatementInbox.sol\n\n// ══════════════════════════════ LIBRARY IMPORTS ══════════════════════════════\n\n// ═════════════════════════════ INTERNAL IMPORTS ══════════════════════════════\n\n// ═════════════════════════════ EXTERNAL IMPORTS ══════════════════════════════\n\n/// @notice `StatementInbox` is the entry point for all agent-signed statements. It verifies the\n/// agent signatures, and passes the unsigned statements to the contract to consume it via `acceptX` functions. Is is\n/// also used to verify the agent-signed statements and initiate the agent slashing, should the statement be invalid.\n/// `StatementInbox` is responsible for the following:\n/// - Accepting State and Receipt Reports to initiate a dispute between Guard and Notary.\n/// - Storing all the Guard Reports with the Guard signature leading to a dispute.\n/// - Verifying State/State Reports referencing the local chain and slashing the signer if statement is invalid.\n/// - Verifying Receipt/Receipt Reports referencing the local chain and slashing the signer if statement is invalid.\nabstract contract StatementInbox is MessagingBase, StatementInboxEvents, IStatementInbox {\n using AttestationLib for bytes;\n using ReceiptLib for bytes;\n using StateLib for bytes;\n using SnapshotLib for bytes;\n\n struct StoredReport {\n uint256 sigIndex;\n bytes statementPayload;\n }\n\n // ══════════════════════════════════════════════════ STORAGE ══════════════════════════════════════════════════════\n\n address public agentManager;\n address public origin;\n address public destination;\n\n // TODO: optimize this\n bytes[] internal _storedSignatures;\n StoredReport[] internal _storedReports;\n\n /// @dev gap for upgrade safety\n uint256[45] private __GAP; // solhint-disable-line var-name-mixedcase\n\n // ════════════════════════════════════════════════ INITIALIZER ════════════════════════════════════════════════════\n\n /// @dev Initializes the contract:\n /// - Sets up `msg.sender` as the owner of the contract.\n /// - Sets up `agentManager`, `origin`, and `destination`.\n // solhint-disable-next-line func-name-mixedcase\n function __StatementInbox_init(address agentManager_, address origin_, address destination_)\n internal\n onlyInitializing\n {\n agentManager = agentManager_;\n origin = origin_;\n destination = destination_;\n __Ownable2Step_init();\n }\n\n // ══════════════════════════════════════════ SUBMIT AGENT STATEMENTS ══════════════════════════════════════════════\n\n /// @inheritdoc IStatementInbox\n // solhint-disable-next-line ordering\n function submitStateReportWithSnapshot(\n uint8 stateIndex,\n bytes memory srSignature,\n bytes memory snapPayload,\n bytes memory snapSignature\n ) external returns (bool wasAccepted) {\n // This will revert if payload is not a snapshot\n Snapshot snapshot = snapPayload.castToSnapshot();\n // This will revert if the snapshot signer is not a known Notary\n (AgentStatus memory notaryStatus,) =\n _verifySnapshot({snapshot: snapshot, snapSignature: snapSignature, verifyNotary: true});\n // Notary needs to be Active/Unstaking\n notaryStatus.verifyActiveUnstaking();\n // Check if Notary is active on this chain\n _verifyNotaryDomain(notaryStatus.domain);\n // This will revert if state index is out of range\n State state = snapshot.state(stateIndex);\n // This will revert if the report signer is not an known Guard\n (AgentStatus memory guardStatus,) = _verifyStateReport(state, srSignature);\n // Check that Guard is active\n guardStatus.verifyActive();\n _saveReport(state.unwrap().clone(), srSignature);\n // This will revert if either actor is already in dispute\n IAgentManager(agentManager).openDispute(guardStatus.index, notaryStatus.index);\n return true;\n }\n\n /// @inheritdoc IStatementInbox\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 // This will revert if payload is not a snapshot\n Snapshot snapshot = snapPayload.castToSnapshot();\n // This will revert if state index is out of range\n State state = snapshot.state(stateIndex);\n // This will revert if the report signer is not an known Guard\n (AgentStatus memory guardStatus,) = _verifyStateReport(state, srSignature);\n // Check that Guard is active\n guardStatus.verifyActive();\n // This will revert if payload is not an attestation\n Attestation att = attPayload.castToAttestation();\n // This will revert if signer is not an known Notary\n (AgentStatus memory notaryStatus,) = _verifyAttestation(att, attSignature);\n // Notary needs to be Active/Unstaking\n notaryStatus.verifyActiveUnstaking();\n // Check if Notary is active on this chain\n _verifyNotaryDomain(notaryStatus.domain);\n if (snapshot.calculateRoot() != att.snapRoot()) revert IncorrectSnapshotRoot();\n _saveReport(state.unwrap().clone(), srSignature);\n // This will revert if either actor is already in dispute\n IAgentManager(agentManager).openDispute(guardStatus.index, notaryStatus.index);\n return true;\n }\n\n /// @inheritdoc IStatementInbox\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 // This will revert if payload is not a state\n State state = statePayload.castToState();\n // This will revert if the report signer is not an known Guard\n (AgentStatus memory guardStatus,) = _verifyStateReport(state, srSignature);\n // Check that Guard is active\n guardStatus.verifyActive();\n // This will revert if payload is not an attestation\n Attestation att = attPayload.castToAttestation();\n // This will revert if signer is not a known Notary\n (AgentStatus memory notaryStatus,) = _verifyAttestation(att, attSignature);\n // Notary needs to be Active/Unstaking\n notaryStatus.verifyActiveUnstaking();\n // Check if Notary is active on this chain\n _verifyNotaryDomain(notaryStatus.domain);\n // This will revert if any of these is true:\n // - Attestation root is not equal to Merkle Root derived from State and Snapshot Proof.\n // - Snapshot Proof's first element does not match the State metadata.\n // - Snapshot Proof length exceeds Snapshot tree Height.\n // - State index is out of range.\n _verifySnapshotMerkle(att, stateIndex, state, snapProof);\n _saveReport(statePayload, srSignature);\n // This will revert if either actor is already in dispute\n IAgentManager(agentManager).openDispute(guardStatus.index, notaryStatus.index);\n return true;\n }\n\n // ══════════════════════════════════════════ VERIFY AGENT STATEMENTS ══════════════════════════════════════════════\n\n /// @inheritdoc IStatementInbox\n function verifyReceipt(bytes memory rcptPayload, bytes memory rcptSignature)\n external\n returns (bool isValidReceipt)\n {\n // This will revert if payload is not a receipt\n Receipt rcpt = rcptPayload.castToReceipt();\n // This will revert if the attestation signer is not a known Notary\n (AgentStatus memory status, address notary) = _verifyReceipt(rcpt, rcptSignature);\n // Notary needs to be Active/Unstaking\n status.verifyActiveUnstaking();\n isValidReceipt = IExecutionHub(destination).isValidReceipt(rcptPayload);\n if (!isValidReceipt) {\n emit InvalidReceipt(rcptPayload, rcptSignature);\n IAgentManager(agentManager).slashAgent(status.domain, notary, msg.sender);\n }\n }\n\n /// @inheritdoc IStatementInbox\n function verifyReceiptReport(bytes memory rcptPayload, bytes memory rrSignature)\n external\n returns (bool isValidReport)\n {\n // This will revert if payload is not a receipt\n Receipt rcpt = rcptPayload.castToReceipt();\n // This will revert if the report signer is not a known Guard\n (AgentStatus memory status, address guard) = _verifyReceiptReport(rcpt, rrSignature);\n // Guard needs to be Active/Unstaking\n status.verifyActiveUnstaking();\n // Report is valid IF AND ONLY IF the reported receipt in invalid\n isValidReport = !IExecutionHub(destination).isValidReceipt(rcptPayload);\n if (!isValidReport) {\n emit InvalidReceiptReport(rcptPayload, rrSignature);\n IAgentManager(agentManager).slashAgent(status.domain, guard, msg.sender);\n }\n }\n\n /// @inheritdoc IStatementInbox\n function verifyStateWithAttestation(\n uint8 stateIndex,\n bytes memory snapPayload,\n bytes memory attPayload,\n bytes memory attSignature\n ) external returns (bool isValidState) {\n // This will revert if payload is not an attestation\n Attestation att = attPayload.castToAttestation();\n // This will revert if the attestation signer is not a known Notary\n (AgentStatus memory status, address notary) = _verifyAttestation(att, attSignature);\n // Notary needs to be Active/Unstaking\n status.verifyActiveUnstaking();\n // This will revert if payload is not a snapshot\n Snapshot snapshot = snapPayload.castToSnapshot();\n if (snapshot.calculateRoot() != att.snapRoot()) revert IncorrectSnapshotRoot();\n // This will revert if state does not refer to this chain\n bytes memory statePayload = snapshot.state(stateIndex).unwrap().clone();\n isValidState = IStateHub(origin).isValidState(statePayload);\n if (!isValidState) {\n emit InvalidStateWithAttestation(stateIndex, statePayload, attPayload, attSignature);\n IAgentManager(agentManager).slashAgent(status.domain, notary, msg.sender);\n }\n }\n\n /// @inheritdoc IStatementInbox\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 // This will revert if payload is not an attestation\n Attestation att = attPayload.castToAttestation();\n // This will revert if the attestation signer is not a known Notary\n (AgentStatus memory status, address notary) = _verifyAttestation(att, attSignature);\n // Notary needs to be Active/Unstaking\n status.verifyActiveUnstaking();\n // This will revert if payload is not a state\n State state = statePayload.castToState();\n // This will revert if any of these is true:\n // - Attestation root is not equal to Merkle Root derived from State and Snapshot Proof.\n // - Snapshot Proof's first element does not match the State metadata.\n // - Snapshot Proof length exceeds Snapshot tree Height.\n // - State index is out of range.\n _verifySnapshotMerkle(att, stateIndex, state, snapProof);\n // This will revert if state does not refer to this chain\n isValidState = IStateHub(origin).isValidState(statePayload);\n if (!isValidState) {\n emit InvalidStateWithAttestation(stateIndex, statePayload, attPayload, attSignature);\n IAgentManager(agentManager).slashAgent(status.domain, notary, msg.sender);\n }\n }\n\n /// @inheritdoc IStatementInbox\n function verifyStateWithSnapshot(uint8 stateIndex, bytes memory snapPayload, bytes memory snapSignature)\n external\n returns (bool isValidState)\n {\n // This will revert if payload is not a snapshot\n Snapshot snapshot = snapPayload.castToSnapshot();\n // This will revert if the snapshot signer is not a known Guard/Notary\n (AgentStatus memory status, address agent) =\n _verifySnapshot({snapshot: snapshot, snapSignature: snapSignature, verifyNotary: false});\n // Agent needs to be Active/Unstaking\n status.verifyActiveUnstaking();\n // This will revert if state does not refer to this chain\n isValidState = IStateHub(origin).isValidState(snapshot.state(stateIndex).unwrap().clone());\n if (!isValidState) {\n emit InvalidStateWithSnapshot(stateIndex, snapPayload, snapSignature);\n IAgentManager(agentManager).slashAgent(status.domain, agent, msg.sender);\n }\n }\n\n /// @inheritdoc IStatementInbox\n function verifyStateReport(bytes memory statePayload, bytes memory srSignature)\n external\n returns (bool isValidReport)\n {\n // This will revert if payload is not a state\n State state = statePayload.castToState();\n // This will revert if the report signer is not a known Guard\n (AgentStatus memory status, address guard) = _verifyStateReport(state, srSignature);\n // Guard needs to be Active/Unstaking\n status.verifyActiveUnstaking();\n // Report is valid IF AND ONLY IF the reported state in invalid\n // This will revert if the reported state does not refer to this chain\n isValidReport = !IStateHub(origin).isValidState(statePayload);\n if (!isValidReport) {\n emit InvalidStateReport(statePayload, srSignature);\n IAgentManager(agentManager).slashAgent(status.domain, guard, msg.sender);\n }\n }\n\n // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════\n\n /// @inheritdoc IStatementInbox\n function getReportsAmount() external view returns (uint256) {\n return _storedReports.length;\n }\n\n /// @inheritdoc IStatementInbox\n function getGuardReport(uint256 index)\n external\n view\n returns (bytes memory statementPayload, bytes memory reportSignature)\n {\n if (index \u003e= _storedReports.length) revert IndexOutOfRange();\n StoredReport memory storedReport = _storedReports[index];\n statementPayload = storedReport.statementPayload;\n reportSignature = _storedSignatures[storedReport.sigIndex];\n }\n\n /// @inheritdoc IStatementInbox\n function getStoredSignature(uint256 index) external view returns (bytes memory) {\n return _storedSignatures[index];\n }\n\n // ══════════════════════════════════════════════ INTERNAL LOGIC ═══════════════════════════════════════════════════\n\n /// @dev Saves the statement reported by Guard as invalid and the Guard Report signature.\n function _saveReport(bytes memory statementPayload, bytes memory reportSignature) internal {\n uint256 sigIndex = _saveSignature(reportSignature);\n _storedReports.push(StoredReport(sigIndex, statementPayload));\n }\n\n /// @dev Saves the signature and returns its index.\n function _saveSignature(bytes memory signature) internal returns (uint256 sigIndex) {\n sigIndex = _storedSignatures.length;\n _storedSignatures.push(signature);\n }\n\n // ═══════════════════════════════════════════════ AGENT CHECKS ════════════════════════════════════════════════════\n\n /**\n * @dev Recovers a signer from a hashed message, and a EIP-191 signature for it.\n * Will revert, if the signer is not a known agent.\n * @dev Agent flag could be any of these: Active/Unstaking/Resting/Fraudulent/Slashed\n * Further checks need to be performed in a caller function.\n * @param hashedStatement Hash of the statement that was signed by an Agent\n * @param signature Agent signature for the hashed statement\n * @return status Struct representing agent status:\n * - flag Unknown/Active/Unstaking/Resting/Fraudulent/Slashed\n * - domain Domain where agent is/was active\n * - index Index of agent in the Agent Merkle Tree\n * @return agent Agent that signed the statement\n */\n function _recoverAgent(bytes32 hashedStatement, bytes memory signature)\n internal\n view\n returns (AgentStatus memory status, address agent)\n {\n bytes32 ethSignedMsg = ECDSA.toEthSignedMessageHash(hashedStatement);\n agent = ECDSA.recover(ethSignedMsg, signature);\n status = IAgentManager(agentManager).agentStatus(agent);\n // Discard signature of unknown agents.\n // Further flag checks are supposed to be performed in a caller function.\n status.verifyKnown();\n }\n\n /// @dev Verifies that Notary signature is active on local domain.\n function _verifyNotaryDomain(uint32 notaryDomain) internal view {\n // Notary needs to be from the local domain (if contract is not deployed on Synapse Chain).\n // Or Notary could be from any domain (if contract is deployed on Synapse Chain).\n if (notaryDomain != localDomain \u0026\u0026 localDomain != synapseDomain) revert IncorrectAgentDomain();\n }\n\n // ════════════════════════════════════════ ATTESTATION RELATED CHECKS ═════════════════════════════════════════════\n\n /**\n * @dev Internal function to verify the signed attestation payload.\n * Reverts if any of these is true:\n * - Attestation signer is not a known Notary.\n * @param att Typed memory view over attestation payload\n * @param attSignature Notary signature for the attestation\n * @return status Struct representing agent status, see {_recoverAgent}\n * @return notary Notary that signed the snapshot\n */\n function _verifyAttestation(Attestation att, bytes memory attSignature)\n internal\n view\n returns (AgentStatus memory status, address notary)\n {\n // This will revert if signer is not a known agent\n (status, notary) = _recoverAgent(att.hashValid(), attSignature);\n // Attestation signer needs to be a Notary, not a Guard\n if (status.domain == 0) revert AgentNotNotary();\n }\n\n /**\n * @dev Internal function to verify the signed attestation report payload.\n * Reverts if any of these is true:\n * - Report signer is not a known Guard.\n * @param att Typed memory view over attestation payload that Guard reports as invalid\n * @param arSignature Guard signature for the \"invalid attestation\" report\n * @return status Struct representing guard status, see {_recoverAgent}\n * @return guard Guard that signed the report\n */\n function _verifyAttestationReport(Attestation att, bytes memory arSignature)\n internal\n view\n returns (AgentStatus memory status, address guard)\n {\n // This will revert if signer is not a known agent\n (status, guard) = _recoverAgent(att.hashInvalid(), arSignature);\n // Report signer needs to be a Guard, not a Notary\n if (status.domain != 0) revert AgentNotGuard();\n }\n\n // ══════════════════════════════════════════ RECEIPT RELATED CHECKS ═══════════════════════════════════════════════\n\n /**\n * @dev Internal function to verify the signed receipt payload.\n * Reverts if any of these is true:\n * - Receipt signer is not a known Notary.\n * @param rcpt Typed memory view over receipt payload\n * @param rcptSignature Notary signature for the receipt\n * @return status Struct representing agent status, see {_recoverAgent}\n * @return notary Notary that signed the snapshot\n */\n function _verifyReceipt(Receipt rcpt, bytes memory rcptSignature)\n internal\n view\n returns (AgentStatus memory status, address notary)\n {\n // This will revert if signer is not a known agent\n (status, notary) = _recoverAgent(rcpt.hashValid(), rcptSignature);\n // Receipt signer needs to be a Notary, not a Guard\n if (status.domain == 0) revert AgentNotNotary();\n }\n\n /**\n * @dev Internal function to verify the signed receipt report payload.\n * Reverts if any of these is true:\n * - Report signer is not a known Guard.\n * @param rcpt Typed memory view over receipt payload that Guard reports as invalid\n * @param rrSignature Guard signature for the \"invalid receipt\" report\n * @return status Struct representing guard status, see {_recoverAgent}\n * @return guard Guard that signed the report\n */\n function _verifyReceiptReport(Receipt rcpt, bytes memory rrSignature)\n internal\n view\n returns (AgentStatus memory status, address guard)\n {\n // This will revert if signer is not a known agent\n (status, guard) = _recoverAgent(rcpt.hashInvalid(), rrSignature);\n // Report signer needs to be a Guard, not a Notary\n if (status.domain != 0) revert AgentNotGuard();\n }\n\n // ═══════════════════════════════════════ STATE/SNAPSHOT RELATED CHECKS ═══════════════════════════════════════════\n\n /**\n * @dev Internal function to verify the signed snapshot report payload.\n * Reverts if any of these is true:\n * - Report signer is not a known Guard.\n * @param state Typed memory view over state payload that Guard reports as invalid\n * @param srSignature Guard signature for the report\n * @return status Struct representing guard status, see {_recoverAgent}\n * @return guard Guard that signed the report\n */\n function _verifyStateReport(State state, bytes memory srSignature)\n internal\n view\n returns (AgentStatus memory status, address guard)\n {\n // This will revert if signer is not a known agent\n (status, guard) = _recoverAgent(state.hashInvalid(), srSignature);\n // Report signer needs to be a Guard, not a Notary\n if (status.domain != 0) revert AgentNotGuard();\n }\n\n /**\n * @dev Internal function to verify the signed snapshot payload.\n * Reverts if any of these is true:\n * - Snapshot signer is not a known Agent.\n * - Snapshot signer is not a Notary (if verifyNotary is true).\n * @param snapshot Typed memory view over snapshot payload\n * @param snapSignature Agent signature for the snapshot\n * @param verifyNotary If true, snapshot signer needs to be a Notary, not a Guard\n * @return status Struct representing agent status, see {_recoverAgent}\n * @return agent Agent that signed the snapshot\n */\n function _verifySnapshot(Snapshot snapshot, bytes memory snapSignature, bool verifyNotary)\n internal\n view\n returns (AgentStatus memory status, address agent)\n {\n // This will revert if signer is not a known agent\n (status, agent) = _recoverAgent(snapshot.hashValid(), snapSignature);\n // If requested, snapshot signer needs to be a Notary, not a Guard\n if (verifyNotary \u0026\u0026 status.domain == 0) revert AgentNotNotary();\n }\n\n // ═══════════════════════════════════════════ MERKLE RELATED CHECKS ═══════════════════════════════════════════════\n\n /**\n * @dev Internal function to verify that snapshot roots match.\n * Reverts if any of these is true:\n * - Attestation root is not equal to Merkle Root derived from State and Snapshot Proof.\n * - Snapshot Proof's first element does not match the State metadata.\n * - Snapshot Proof length exceeds Snapshot tree Height.\n * - State index is out of range.\n * @param att Typed memory view over Attestation\n * @param stateIndex Index of state in the snapshot\n * @param state Typed memory view over the provided state payload\n * @param snapProof Raw payload with snapshot data\n */\n function _verifySnapshotMerkle(Attestation att, uint8 stateIndex, State state, bytes32[] memory snapProof)\n internal\n pure\n {\n // Snapshot proof first element should match State metadata (aka \"right sub-leaf\")\n (, bytes32 rightSubLeaf) = state.subLeafs();\n if (snapProof[0] != rightSubLeaf) revert IncorrectSnapshotProof();\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(state.root(), state.origin(), snapProof, stateIndex);\n // Snapshot root should match the attestation root\n if (att.snapRoot() != snapshotRoot) revert IncorrectSnapshotRoot();\n }\n}\n\n// contracts/inbox/Inbox.sol\n\n// ══════════════════════════════ LIBRARY IMPORTS ══════════════════════════════\n\n// ═════════════════════════════ INTERNAL IMPORTS ══════════════════════════════\n\n/// @notice `Inbox` is the child of `StatementInbox` contract, that is used on Synapse Chain.\n/// In addition to the functionality of `StatementInbox`, it also:\n/// - Accepts Guard and Notary Snapshots and passes them to `Summit` contract.\n/// - Accepts Notary-signed Receipts and passes them to `Summit` contract.\n/// - Accepts Receipt Reports to initiate a dispute between Guard and Notary.\n/// - Verifies Attestations and Attestation Reports, and slashes the signer if they are invalid.\ncontract Inbox is StatementInbox, InboxEvents, InterfaceInbox {\n using AttestationLib for bytes;\n using ReceiptLib for bytes;\n using SnapshotLib for bytes;\n\n // Struct to get around stack too deep error. TODO: revisit this\n struct ReceiptInfo {\n AgentStatus rcptNotaryStatus;\n address notary;\n uint32 attNonce;\n AgentStatus attNotaryStatus;\n }\n\n // ══════════════════════════════════════════════════ STORAGE ══════════════════════════════════════════════════════\n\n // The address of the Summit contract.\n address public summit;\n\n // ═════════════════════════════════════════ CONSTRUCTOR \u0026 INITIALIZER ═════════════════════════════════════════════\n\n constructor(uint32 synapseDomain_) MessagingBase(\"0.0.3\", synapseDomain_) {\n if (localDomain != synapseDomain) revert MustBeSynapseDomain();\n }\n\n /// @notice Initializes `Inbox` contract:\n /// - Sets `msg.sender` as the owner of the contract\n /// - Sets `agentManager`, `origin`, `destination` and `summit` addresses\n function initialize(address agentManager_, address origin_, address destination_, address summit_)\n external\n initializer\n {\n __StatementInbox_init(agentManager_, origin_, destination_);\n summit = summit_;\n }\n\n // ══════════════════════════════════════════ SUBMIT AGENT STATEMENTS ══════════════════════════════════════════════\n\n /// @inheritdoc InterfaceInbox\n function submitSnapshot(bytes memory snapPayload, bytes memory snapSignature)\n external\n returns (bytes memory attPayload, bytes32 agentRoot_, uint256[] memory snapGas)\n {\n // This will revert if payload is not a snapshot\n Snapshot snapshot = snapPayload.castToSnapshot();\n // This will revert if the signer is not a known Guard/Notary\n (AgentStatus memory status, address agent) =\n _verifySnapshot({snapshot: snapshot, snapSignature: snapSignature, verifyNotary: false});\n // Check that Agent is active\n status.verifyActive();\n // Store Agent signature for the Snapshot\n uint256 sigIndex = _saveSignature(snapSignature);\n if (status.domain == 0) {\n // Guard that is in Dispute could still submit new snapshots, so we don't check that\n InterfaceSummit(summit).acceptGuardSnapshot({\n guardIndex: status.index,\n sigIndex: sigIndex,\n snapPayload: snapPayload\n });\n } else {\n // Get current agentRoot from AgentManager\n agentRoot_ = IAgentManager(agentManager).agentRoot();\n // This will revert if Notary is in Dispute\n attPayload = InterfaceSummit(summit).acceptNotarySnapshot({\n notaryIndex: status.index,\n sigIndex: sigIndex,\n agentRoot: agentRoot_,\n snapPayload: snapPayload\n });\n ChainGas[] memory snapGas_ = snapshot.snapGas();\n // Pass created attestation to Destination to enable executing messages coming to Synapse Chain\n InterfaceDestination(destination).acceptAttestation(\n status.index, type(uint256).max, attPayload, agentRoot_, snapGas_\n );\n // Use assembly to cast ChainGas[] to uint256[] without copying. Highest bits are left zeroed.\n // solhint-disable-next-line no-inline-assembly\n assembly {\n snapGas := snapGas_\n }\n }\n emit SnapshotAccepted(status.domain, agent, snapPayload, snapSignature);\n }\n\n /// @inheritdoc InterfaceInbox\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 // Struct to get around stack too deep error.\n ReceiptInfo memory info;\n // This will revert if payload is not a receipt\n Receipt rcpt = rcptPayload.castToReceipt();\n // This will revert if the receipt signer is not a known Notary\n (info.rcptNotaryStatus, info.notary) = _verifyReceipt(rcpt, rcptSignature);\n // Receipt Notary needs to be Active\n info.rcptNotaryStatus.verifyActive();\n info.attNonce = IExecutionHub(destination).getAttestationNonce(rcpt.snapshotRoot());\n if (info.attNonce == 0) revert IncorrectSnapshotRoot();\n // Attestation Notary domain needs to match the destination domain\n info.attNotaryStatus = IAgentManager(agentManager).agentStatus(rcpt.attNotary());\n if (info.attNotaryStatus.domain != rcpt.destination()) revert IncorrectAgentDomain();\n // Check that the correct tip values for the message were provided\n _verifyReceiptTips(rcpt.messageHash(), paddedTips, headerHash, bodyHash);\n // Store Notary signature for the Receipt\n uint256 sigIndex = _saveSignature(rcptSignature);\n // This will revert if Receipt Notary is in Dispute\n wasAccepted = InterfaceSummit(summit).acceptReceipt({\n rcptNotaryIndex: info.rcptNotaryStatus.index,\n attNotaryIndex: info.attNotaryStatus.index,\n sigIndex: sigIndex,\n attNonce: info.attNonce,\n paddedTips: paddedTips,\n rcptPayload: rcptPayload\n });\n if (wasAccepted) {\n emit ReceiptAccepted(info.rcptNotaryStatus.domain, info.notary, rcptPayload, rcptSignature);\n }\n }\n\n /// @inheritdoc InterfaceInbox\n function submitReceiptReport(bytes memory rcptPayload, bytes memory rcptSignature, bytes memory rrSignature)\n external\n returns (bool wasAccepted)\n {\n // This will revert if payload is not a receipt\n Receipt rcpt = rcptPayload.castToReceipt();\n // This will revert if the receipt signer is not a known Guard\n (AgentStatus memory guardStatus,) = _verifyReceiptReport(rcpt, rrSignature);\n // Guard needs to be Active\n guardStatus.verifyActive();\n // This will revert if report signer is not a known Notary\n (AgentStatus memory notaryStatus,) = _verifyReceipt(rcpt, rcptSignature);\n // Notary needs to be Active/Unstaking\n notaryStatus.verifyActiveUnstaking();\n _saveReport(rcptPayload, rrSignature);\n // This will revert if either actor is already in dispute\n IAgentManager(agentManager).openDispute(guardStatus.index, notaryStatus.index);\n return true;\n }\n\n /// @inheritdoc InterfaceInbox\n function passReceipt(uint32 attNotaryIndex, uint32 attNonce, uint256 paddedTips, bytes memory rcptPayload)\n external\n returns (bool wasAccepted)\n {\n // Only Destination can pass receipts\n if (msg.sender != destination) revert CallerNotDestination();\n return InterfaceSummit(summit).acceptReceipt({\n rcptNotaryIndex: attNotaryIndex,\n attNotaryIndex: attNotaryIndex,\n sigIndex: type(uint256).max,\n attNonce: attNonce,\n paddedTips: paddedTips,\n rcptPayload: rcptPayload\n });\n }\n\n // ══════════════════════════════════════════ VERIFY AGENT STATEMENTS ══════════════════════════════════════════════\n\n /// @inheritdoc InterfaceInbox\n function verifyAttestation(bytes memory attPayload, bytes memory attSignature)\n external\n returns (bool isValidAttestation)\n {\n // This will revert if payload is not an attestation\n Attestation att = attPayload.castToAttestation();\n // This will revert if the attestation signer is not a known Notary\n (AgentStatus memory status, address notary) = _verifyAttestation(att, attSignature);\n // Notary needs to be Active/Unstaking\n status.verifyActiveUnstaking();\n isValidAttestation = ISnapshotHub(summit).isValidAttestation(attPayload);\n if (!isValidAttestation) {\n emit InvalidAttestation(attPayload, attSignature);\n IAgentManager(agentManager).slashAgent(status.domain, notary, msg.sender);\n }\n }\n\n /// @inheritdoc InterfaceInbox\n function verifyAttestationReport(bytes memory attPayload, bytes memory arSignature)\n external\n returns (bool isValidReport)\n {\n // This will revert if payload is not an attestation\n Attestation att = attPayload.castToAttestation();\n // This will revert if the report signer is not a known Guard\n (AgentStatus memory status, address guard) = _verifyAttestationReport(att, arSignature);\n // Guard needs to be Active/Unstaking\n status.verifyActiveUnstaking();\n // Report is valid IF AND ONLY IF the reported attestation in invalid\n isValidReport = !ISnapshotHub(summit).isValidAttestation(attPayload);\n if (!isValidReport) {\n emit InvalidAttestationReport(attPayload, arSignature);\n IAgentManager(agentManager).slashAgent(status.domain, guard, msg.sender);\n }\n }\n\n // ══════════════════════════════════════════════ INTERNAL VIEWS ═══════════════════════════════════════════════════\n\n /// @dev Verifies that tips proof matches the message hash.\n function _verifyReceiptTips(bytes32 msgHash, uint256 paddedTips, bytes32 headerHash, bytes32 bodyHash)\n internal\n pure\n {\n Tips tips = TipsLib.wrapPadded(paddedTips);\n // full message leaf is (header, baseMessage), while base message leaf is (tips, remainingBody).\n if (MerkleMath.getParent(headerHash, MerkleMath.getParent(tips.leaf(), bodyHash)) != msgHash) {\n revert IncorrectTipsProof();\n }\n }\n}\n","language":"Solidity","languageVersion":"0.8.17","compilerVersion":"0.8.17","compilerOptions":"--combined-json bin,bin-runtime,srcmap,srcmap-runtime,abi,userdoc,devdoc,metadata,hashes --optimize --optimize-runs 10000 --allow-paths ., ./, ../","srcMap":"","srcMapRuntime":"","abiDefinition":[{"anonymous":false,"inputs":[{"indexed":false,"internalType":"bytes","name":"attPayload","type":"bytes"},{"indexed":false,"internalType":"bytes","name":"attSignature","type":"bytes"}],"name":"InvalidAttestation","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"bytes","name":"arPayload","type":"bytes"},{"indexed":false,"internalType":"bytes","name":"arSignature","type":"bytes"}],"name":"InvalidAttestationReport","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint32","name":"domain","type":"uint32"},{"indexed":false,"internalType":"address","name":"notary","type":"address"},{"indexed":false,"internalType":"bytes","name":"rcptPayload","type":"bytes"},{"indexed":false,"internalType":"bytes","name":"rcptSignature","type":"bytes"}],"name":"ReceiptAccepted","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint32","name":"domain","type":"uint32"},{"indexed":true,"internalType":"address","name":"agent","type":"address"},{"indexed":false,"internalType":"bytes","name":"snapPayload","type":"bytes"},{"indexed":false,"internalType":"bytes","name":"snapSignature","type":"bytes"}],"name":"SnapshotAccepted","type":"event"}],"userDoc":{"events":{"InvalidAttestation(bytes,bytes)":{"notice":"Emitted when a proof of invalid attestation is submitted."},"InvalidAttestationReport(bytes,bytes)":{"notice":"Emitted when a proof of invalid attestation report is submitted."},"ReceiptAccepted(uint32,address,bytes,bytes)":{"notice":"Emitted when a snapshot is accepted by the Summit contract."},"SnapshotAccepted(uint32,address,bytes,bytes)":{"notice":"Emitted when a snapshot is accepted by the Summit contract."}},"kind":"user","methods":{},"version":1},"developerDoc":{"events":{"InvalidAttestation(bytes,bytes)":{"params":{"attPayload":"Raw payload with Attestation data","attSignature":"Notary signature for the attestation"}},"InvalidAttestationReport(bytes,bytes)":{"params":{"arPayload":"Raw payload with report data","arSignature":"Guard signature for the report"}},"ReceiptAccepted(uint32,address,bytes,bytes)":{"params":{"domain":"Domain where the signed Notary is active","notary":"Notary who signed the attestation","rcptPayload":"Raw payload with receipt data","rcptSignature":"Notary signature for the receipt"}},"SnapshotAccepted(uint32,address,bytes,bytes)":{"params":{"agent":"Agent who signed the snapshot","domain":"Domain where the signed Agent is active (ZERO for Guards)","snapPayload":"Raw payload with snapshot data","snapSignature":"Agent signature for the snapshot"}}},"kind":"dev","methods":{},"version":1},"metadata":"{\"compiler\":{\"version\":\"0.8.17+commit.8df45f5f\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"attPayload\",\"type\":\"bytes\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"attSignature\",\"type\":\"bytes\"}],\"name\":\"InvalidAttestation\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"arPayload\",\"type\":\"bytes\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"arSignature\",\"type\":\"bytes\"}],\"name\":\"InvalidAttestationReport\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint32\",\"name\":\"domain\",\"type\":\"uint32\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"notary\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"rcptPayload\",\"type\":\"bytes\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"rcptSignature\",\"type\":\"bytes\"}],\"name\":\"ReceiptAccepted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint32\",\"name\":\"domain\",\"type\":\"uint32\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"agent\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"snapPayload\",\"type\":\"bytes\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"snapSignature\",\"type\":\"bytes\"}],\"name\":\"SnapshotAccepted\",\"type\":\"event\"}],\"devdoc\":{\"events\":{\"InvalidAttestation(bytes,bytes)\":{\"params\":{\"attPayload\":\"Raw payload with Attestation data\",\"attSignature\":\"Notary signature for the attestation\"}},\"InvalidAttestationReport(bytes,bytes)\":{\"params\":{\"arPayload\":\"Raw payload with report data\",\"arSignature\":\"Guard signature for the report\"}},\"ReceiptAccepted(uint32,address,bytes,bytes)\":{\"params\":{\"domain\":\"Domain where the signed Notary is active\",\"notary\":\"Notary who signed the attestation\",\"rcptPayload\":\"Raw payload with receipt data\",\"rcptSignature\":\"Notary signature for the receipt\"}},\"SnapshotAccepted(uint32,address,bytes,bytes)\":{\"params\":{\"agent\":\"Agent who signed the snapshot\",\"domain\":\"Domain where the signed Agent is active (ZERO for Guards)\",\"snapPayload\":\"Raw payload with snapshot data\",\"snapSignature\":\"Agent signature for the snapshot\"}}},\"kind\":\"dev\",\"methods\":{},\"version\":1},\"userdoc\":{\"events\":{\"InvalidAttestation(bytes,bytes)\":{\"notice\":\"Emitted when a proof of invalid attestation is submitted.\"},\"InvalidAttestationReport(bytes,bytes)\":{\"notice\":\"Emitted when a proof of invalid attestation report is submitted.\"},\"ReceiptAccepted(uint32,address,bytes,bytes)\":{\"notice\":\"Emitted when a snapshot is accepted by the Summit contract.\"},\"SnapshotAccepted(uint32,address,bytes,bytes)\":{\"notice\":\"Emitted when a snapshot is accepted by the Summit contract.\"}},\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"solidity/Inbox.sol\":\"InboxEvents\"},\"evmVersion\":\"london\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\"},\"optimizer\":{\"enabled\":true,\"runs\":10000},\"remappings\":[]},\"sources\":{\"solidity/Inbox.sol\":{\"keccak256\":\"0x9b516081a036814c0169e20e484d4a5499066b7a6f48fada952b5e844a1ca3e5\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://32bde393b3f24ef4307d9626d4143f337b3c0bd34e17bb969fd5a15221d96987\",\"dweb:/ipfs/QmTkt2XZRtgsbSpmsVQUM3c4ebETQoDVYbmEV9yheBghnr\"]}},\"version\":1}"},"hashes":{}},"solidity/Inbox.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/InboxEvents.sol\n\nabstract contract InboxEvents {\n /**\n * @notice Emitted when a snapshot is accepted by the Summit contract.\n * @param domain Domain where the signed Agent is active (ZERO for Guards)\n * @param agent Agent who signed the snapshot\n * @param snapPayload Raw payload with snapshot data\n * @param snapSignature Agent signature for the snapshot\n */\n event SnapshotAccepted(uint32 indexed domain, address indexed agent, bytes snapPayload, bytes snapSignature);\n\n /**\n * @notice Emitted when a snapshot is accepted by the Summit contract.\n * @param domain Domain where the signed Notary is active\n * @param notary Notary who signed the attestation\n * @param rcptPayload Raw payload with receipt data\n * @param rcptSignature Notary signature for the receipt\n */\n event ReceiptAccepted(uint32 domain, address notary, bytes rcptPayload, bytes rcptSignature);\n\n /**\n * @notice Emitted when a proof of invalid attestation is submitted.\n * @param attPayload Raw payload with Attestation data\n * @param attSignature Notary signature for the attestation\n */\n event InvalidAttestation(bytes attPayload, bytes attSignature);\n\n /**\n * @notice Emitted when a proof of invalid attestation report is submitted.\n * @param arPayload Raw payload with report data\n * @param arSignature Guard signature for the report\n */\n event InvalidAttestationReport(bytes arPayload, bytes arSignature);\n}\n\n// contracts/events/StatementInboxEvents.sol\n\nabstract contract StatementInboxEvents {\n // ════════════════════════════════════════════ STATEMENT ACCEPTED ═════════════════════════════════════════════════\n\n /**\n * @notice Emitted when a snapshot is accepted by the Destination contract.\n * @param domain Domain where the signed Notary is active\n * @param notary Notary who signed the attestation\n * @param attPayload Raw payload with attestation data\n * @param attSignature Notary signature for the attestation\n */\n event AttestationAccepted(uint32 domain, address notary, bytes attPayload, bytes attSignature);\n\n // ═════════════════════════════════════════ INVALID STATEMENT PROVED ══════════════════════════════════════════════\n\n /**\n * @notice Emitted when a proof of invalid receipt statement is submitted.\n * @param rcptPayload Raw payload with the receipt statement\n * @param rcptSignature Notary signature for the receipt statement\n */\n event InvalidReceipt(bytes rcptPayload, bytes rcptSignature);\n\n /**\n * @notice Emitted when a proof of invalid receipt report is submitted.\n * @param rrPayload Raw payload with report data\n * @param rrSignature Guard signature for the report\n */\n event InvalidReceiptReport(bytes rrPayload, bytes rrSignature);\n\n /**\n * @notice Emitted when a proof of invalid state in the signed attestation is submitted.\n * @param stateIndex Index of invalid state in the snapshot\n * @param statePayload Raw payload with state data\n * @param attPayload Raw payload with Attestation data for snapshot\n * @param attSignature Notary signature for the attestation\n */\n event InvalidStateWithAttestation(uint8 stateIndex, bytes statePayload, bytes attPayload, bytes attSignature);\n\n /**\n * @notice Emitted when a proof of invalid state in the signed snapshot is submitted.\n * @param stateIndex Index of invalid state in the snapshot\n * @param snapPayload Raw payload with snapshot data\n * @param snapSignature Agent signature for the snapshot\n */\n event InvalidStateWithSnapshot(uint8 stateIndex, bytes snapPayload, bytes snapSignature);\n\n /**\n * @notice Emitted when a proof of invalid state report is submitted.\n * @param srPayload Raw payload with report data\n * @param srSignature Guard signature for the report\n */\n event InvalidStateReport(bytes srPayload, bytes srSignature);\n}\n\n// contracts/interfaces/ISnapshotHub.sol\n\ninterface ISnapshotHub {\n /**\n * @notice Check that a given attestation is valid: matches the historical attestation\n * derived from an accepted Notary snapshot.\n * @dev Will revert if any of these is true:\n * - Attestation payload is not properly formatted.\n * @param attPayload Raw payload with attestation data\n * @return isValid Whether the provided attestation is valid\n */\n function isValidAttestation(bytes memory attPayload) external view returns (bool isValid);\n\n /**\n * @notice Returns saved attestation with the given nonce.\n * @dev Reverts if attestation with given nonce hasn't been created yet.\n * @param attNonce Nonce for the attestation\n * @return attPayload Raw payload with formatted Attestation data\n * @return agentRoot Agent root hash used for the attestation\n * @return snapGas Snapshot gas data used for the attestation\n */\n function getAttestation(uint32 attNonce)\n external\n view\n returns (bytes memory attPayload, bytes32 agentRoot, uint256[] memory snapGas);\n\n /**\n * @notice Returns the state with the highest known nonce submitted by a given Agent.\n * @param origin Domain of origin chain\n * @param agent Agent address\n * @return statePayload Raw payload with agent's latest state for origin\n */\n function getLatestAgentState(uint32 origin, address agent) external view returns (bytes memory statePayload);\n\n /**\n * @notice Returns latest saved attestation for a Notary.\n * @param notary Notary address\n * @return attPayload Raw payload with formatted Attestation data\n * @return agentRoot Agent root hash used for the attestation\n * @return snapGas Snapshot gas data used for the attestation\n */\n function getLatestNotaryAttestation(address notary)\n external\n view\n returns (bytes memory attPayload, bytes32 agentRoot, uint256[] memory snapGas);\n\n /**\n * @notice Returns Guard snapshot from the list of all accepted Guard snapshots.\n * @dev Reverts if snapshot with given index hasn't been accepted yet.\n * @param index Snapshot index in the list of all Guard snapshots\n * @return snapPayload Raw payload with Guard snapshot\n * @return snapSignature Raw payload with Guard signature for snapshot\n */\n function getGuardSnapshot(uint256 index)\n external\n view\n returns (bytes memory snapPayload, bytes memory snapSignature);\n\n /**\n * @notice Returns Notary snapshot from the list of all accepted Guard snapshots.\n * @dev Reverts if snapshot with given index hasn't been accepted yet.\n * @param index Snapshot index in the list of all Notary snapshots\n * @return snapPayload Raw payload with Notary snapshot\n * @return snapSignature Raw payload with Notary signature for snapshot\n */\n function getNotarySnapshot(uint256 index)\n external\n view\n returns (bytes memory snapPayload, bytes memory snapSignature);\n\n /**\n * @notice Returns Notary snapshot that was used for creating a given attestation.\n * @dev Reverts if any of these is true:\n * - Attestation payload is not properly formatted.\n * - Attestation is invalid (doesn't have a matching Notary snapshot).\n * @param attPayload Raw payload with attestation data\n * @return snapPayload Raw payload with Notary snapshot\n * @return snapSignature Raw payload with Notary signature for snapshot\n */\n function getNotarySnapshot(bytes memory attPayload)\n external\n view\n returns (bytes memory snapPayload, bytes memory snapSignature);\n\n /**\n * @notice Returns proof of inclusion of (root, origin) fields of a given snapshot's state\n * into the Snapshot Merkle Tree for a given attestation.\n * @dev Reverts if any of these is true:\n * - Attestation with given nonce hasn't been created yet.\n * - State index is out of range of snapshot list.\n * @param attNonce Nonce for the attestation\n * @param stateIndex Index of state in the attestation's snapshot\n * @return snapProof The snapshot proof\n */\n function getSnapshotProof(uint32 attNonce, uint8 stateIndex) external view returns (bytes32[] memory snapProof);\n}\n\n// contracts/interfaces/IStateHub.sol\n\ninterface IStateHub {\n /**\n * @notice Check that a given state is valid: matches the historical state of Origin contract.\n * Note: any Agent including an invalid state in their snapshot will be slashed\n * upon providing the snapshot and agent signature for it to Origin contract.\n * @dev Will revert if any of these is true:\n * - State payload is not properly formatted.\n * @param statePayload Raw payload with state data\n * @return isValid Whether the provided state is valid\n */\n function isValidState(bytes memory statePayload) external view returns (bool isValid);\n\n /**\n * @notice Returns the amount of saved states so far.\n * @dev This includes the initial state of \"empty Origin Merkle Tree\".\n */\n function statesAmount() external view returns (uint256);\n\n /**\n * @notice Suggest the data (state after latest sent message) to sign for an Agent.\n * Note: signing the suggested state data will will never lead to slashing of the actor,\n * assuming they have confirmed that the block, which number is included in the data,\n * is not subject to reorganization (which is different for every observed chain).\n * @return statePayload Raw payload with the latest state data\n */\n function suggestLatestState() external view returns (bytes memory statePayload);\n\n /**\n * @notice Given the historical nonce, suggest the state data to sign for an Agent.\n * Note: signing the suggested state data will will never lead to slashing of the actor,\n * assuming they have confirmed that the block, which number is included in the data,\n * is not subject to reorganization (which is different for every observed chain).\n * @param nonce Historical nonce to form a state\n * @return statePayload Raw payload with historical state data\n */\n function suggestState(uint32 nonce) external view returns (bytes memory statePayload);\n}\n\n// contracts/interfaces/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/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// node_modules/@openzeppelin/contracts/utils/math/Math.sol\n\n// OpenZeppelin Contracts (last updated v4.9.0) (utils/math/Math.sol)\n\n/**\n * @dev Standard math utilities missing in the Solidity language.\n */\nlibrary Math {\n enum Rounding {\n Down, // Toward negative infinity\n Up, // Toward infinity\n Zero // Toward zero\n }\n\n /**\n * @dev Returns the largest of two numbers.\n */\n function max(uint256 a, uint256 b) internal pure returns (uint256) {\n return a \u003e b ? a : b;\n }\n\n /**\n * @dev Returns the smallest of two numbers.\n */\n function min(uint256 a, uint256 b) internal pure returns (uint256) {\n return a \u003c b ? a : b;\n }\n\n /**\n * @dev Returns the average of two numbers. The result is rounded towards\n * zero.\n */\n function average(uint256 a, uint256 b) internal pure returns (uint256) {\n // (a + b) / 2 can overflow.\n return (a \u0026 b) + (a ^ b) / 2;\n }\n\n /**\n * @dev Returns the ceiling of the division of two numbers.\n *\n * This differs from standard division with `/` in that it rounds up instead\n * of rounding down.\n */\n function ceilDiv(uint256 a, uint256 b) internal pure returns (uint256) {\n // (a + b - 1) / b can overflow on addition, so we distribute.\n return a == 0 ? 0 : (a - 1) / b + 1;\n }\n\n /**\n * @notice Calculates floor(x * y / denominator) with full precision. Throws if result overflows a uint256 or denominator == 0\n * @dev Original credit to Remco Bloemen under MIT license (https://xn--2-umb.com/21/muldiv)\n * with further edits by Uniswap Labs also under MIT license.\n */\n function mulDiv(uint256 x, uint256 y, uint256 denominator) internal pure returns (uint256 result) {\n unchecked {\n // 512-bit multiply [prod1 prod0] = x * y. Compute the product mod 2^256 and mod 2^256 - 1, then use\n // use the Chinese Remainder Theorem to reconstruct the 512 bit result. The result is stored in two 256\n // variables such that product = prod1 * 2^256 + prod0.\n uint256 prod0; // Least significant 256 bits of the product\n uint256 prod1; // Most significant 256 bits of the product\n assembly {\n let mm := mulmod(x, y, not(0))\n prod0 := mul(x, y)\n prod1 := sub(sub(mm, prod0), lt(mm, prod0))\n }\n\n // Handle non-overflow cases, 256 by 256 division.\n if (prod1 == 0) {\n // Solidity will revert if denominator == 0, unlike the div opcode on its own.\n // The surrounding unchecked block does not change this fact.\n // See https://docs.soliditylang.org/en/latest/control-structures.html#checked-or-unchecked-arithmetic.\n return prod0 / denominator;\n }\n\n // Make sure the result is less than 2^256. Also prevents denominator == 0.\n require(denominator \u003e prod1, \"Math: mulDiv overflow\");\n\n ///////////////////////////////////////////////\n // 512 by 256 division.\n ///////////////////////////////////////////////\n\n // Make division exact by subtracting the remainder from [prod1 prod0].\n uint256 remainder;\n assembly {\n // Compute remainder using mulmod.\n remainder := mulmod(x, y, denominator)\n\n // Subtract 256 bit number from 512 bit number.\n prod1 := sub(prod1, gt(remainder, prod0))\n prod0 := sub(prod0, remainder)\n }\n\n // Factor powers of two out of denominator and compute largest power of two divisor of denominator. Always \u003e= 1.\n // See https://cs.stackexchange.com/q/138556/92363.\n\n // Does not overflow because the denominator cannot be zero at this stage in the function.\n uint256 twos = denominator \u0026 (~denominator + 1);\n assembly {\n // Divide denominator by twos.\n denominator := div(denominator, twos)\n\n // Divide [prod1 prod0] by twos.\n prod0 := div(prod0, twos)\n\n // Flip twos such that it is 2^256 / twos. If twos is zero, then it becomes one.\n twos := add(div(sub(0, twos), twos), 1)\n }\n\n // Shift in bits from prod1 into prod0.\n prod0 |= prod1 * twos;\n\n // Invert denominator mod 2^256. Now that denominator is an odd number, it has an inverse modulo 2^256 such\n // that denominator * inv = 1 mod 2^256. Compute the inverse by starting with a seed that is correct for\n // four bits. That is, denominator * inv = 1 mod 2^4.\n uint256 inverse = (3 * denominator) ^ 2;\n\n // Use the Newton-Raphson iteration to improve the precision. Thanks to Hensel's lifting lemma, this also works\n // in modular arithmetic, doubling the correct bits in each step.\n inverse *= 2 - denominator * inverse; // inverse mod 2^8\n inverse *= 2 - denominator * inverse; // inverse mod 2^16\n inverse *= 2 - denominator * inverse; // inverse mod 2^32\n inverse *= 2 - denominator * inverse; // inverse mod 2^64\n inverse *= 2 - denominator * inverse; // inverse mod 2^128\n inverse *= 2 - denominator * inverse; // inverse mod 2^256\n\n // Because the division is now exact we can divide by multiplying with the modular inverse of denominator.\n // This will give us the correct result modulo 2^256. Since the preconditions guarantee that the outcome is\n // less than 2^256, this is the final result. We don't need to compute the high bits of the result and prod1\n // is no longer required.\n result = prod0 * inverse;\n return result;\n }\n }\n\n /**\n * @notice Calculates x * y / denominator with full precision, following the selected rounding direction.\n */\n function mulDiv(uint256 x, uint256 y, uint256 denominator, Rounding rounding) internal pure returns (uint256) {\n uint256 result = mulDiv(x, y, denominator);\n if (rounding == Rounding.Up \u0026\u0026 mulmod(x, y, denominator) \u003e 0) {\n result += 1;\n }\n return result;\n }\n\n /**\n * @dev Returns the square root of a number. If the number is not a perfect square, the value is rounded down.\n *\n * Inspired by Henry S. Warren, Jr.'s \"Hacker's Delight\" (Chapter 11).\n */\n function sqrt(uint256 a) internal pure returns (uint256) {\n if (a == 0) {\n return 0;\n }\n\n // For our first guess, we get the biggest power of 2 which is smaller than the square root of the target.\n //\n // We know that the \"msb\" (most significant bit) of our target number `a` is a power of 2 such that we have\n // `msb(a) \u003c= a \u003c 2*msb(a)`. This value can be written `msb(a)=2**k` with `k=log2(a)`.\n //\n // This can be rewritten `2**log2(a) \u003c= a \u003c 2**(log2(a) + 1)`\n // → `sqrt(2**k) \u003c= sqrt(a) \u003c sqrt(2**(k+1))`\n // → `2**(k/2) \u003c= sqrt(a) \u003c 2**((k+1)/2) \u003c= 2**(k/2 + 1)`\n //\n // Consequently, `2**(log2(a) / 2)` is a good first approximation of `sqrt(a)` with at least 1 correct bit.\n uint256 result = 1 \u003c\u003c (log2(a) \u003e\u003e 1);\n\n // At this point `result` is an estimation with one bit of precision. We know the true value is a uint128,\n // since it is the square root of a uint256. Newton's method converges quadratically (precision doubles at\n // every iteration). We thus need at most 7 iteration to turn our partial result with one bit of precision\n // into the expected uint128 result.\n unchecked {\n result = (result + a / result) \u003e\u003e 1;\n result = (result + a / result) \u003e\u003e 1;\n result = (result + a / result) \u003e\u003e 1;\n result = (result + a / result) \u003e\u003e 1;\n result = (result + a / result) \u003e\u003e 1;\n result = (result + a / result) \u003e\u003e 1;\n result = (result + a / result) \u003e\u003e 1;\n return min(result, a / result);\n }\n }\n\n /**\n * @notice Calculates sqrt(a), following the selected rounding direction.\n */\n function sqrt(uint256 a, Rounding rounding) internal pure returns (uint256) {\n unchecked {\n uint256 result = sqrt(a);\n return result + (rounding == Rounding.Up \u0026\u0026 result * result \u003c a ? 1 : 0);\n }\n }\n\n /**\n * @dev Return the log in base 2, rounded down, of a positive value.\n * Returns 0 if given 0.\n */\n function log2(uint256 value) internal pure returns (uint256) {\n uint256 result = 0;\n unchecked {\n if (value \u003e\u003e 128 \u003e 0) {\n value \u003e\u003e= 128;\n result += 128;\n }\n if (value \u003e\u003e 64 \u003e 0) {\n value \u003e\u003e= 64;\n result += 64;\n }\n if (value \u003e\u003e 32 \u003e 0) {\n value \u003e\u003e= 32;\n result += 32;\n }\n if (value \u003e\u003e 16 \u003e 0) {\n value \u003e\u003e= 16;\n result += 16;\n }\n if (value \u003e\u003e 8 \u003e 0) {\n value \u003e\u003e= 8;\n result += 8;\n }\n if (value \u003e\u003e 4 \u003e 0) {\n value \u003e\u003e= 4;\n result += 4;\n }\n if (value \u003e\u003e 2 \u003e 0) {\n value \u003e\u003e= 2;\n result += 2;\n }\n if (value \u003e\u003e 1 \u003e 0) {\n result += 1;\n }\n }\n return result;\n }\n\n /**\n * @dev Return the log in base 2, following the selected rounding direction, of a positive value.\n * Returns 0 if given 0.\n */\n function log2(uint256 value, Rounding rounding) internal pure returns (uint256) {\n unchecked {\n uint256 result = log2(value);\n return result + (rounding == Rounding.Up \u0026\u0026 1 \u003c\u003c result \u003c value ? 1 : 0);\n }\n }\n\n /**\n * @dev Return the log in base 10, rounded down, of a positive value.\n * Returns 0 if given 0.\n */\n function log10(uint256 value) internal pure returns (uint256) {\n uint256 result = 0;\n unchecked {\n if (value \u003e= 10 ** 64) {\n value /= 10 ** 64;\n result += 64;\n }\n if (value \u003e= 10 ** 32) {\n value /= 10 ** 32;\n result += 32;\n }\n if (value \u003e= 10 ** 16) {\n value /= 10 ** 16;\n result += 16;\n }\n if (value \u003e= 10 ** 8) {\n value /= 10 ** 8;\n result += 8;\n }\n if (value \u003e= 10 ** 4) {\n value /= 10 ** 4;\n result += 4;\n }\n if (value \u003e= 10 ** 2) {\n value /= 10 ** 2;\n result += 2;\n }\n if (value \u003e= 10 ** 1) {\n result += 1;\n }\n }\n return result;\n }\n\n /**\n * @dev Return the log in base 10, following the selected rounding direction, of a positive value.\n * Returns 0 if given 0.\n */\n function log10(uint256 value, Rounding rounding) internal pure returns (uint256) {\n unchecked {\n uint256 result = log10(value);\n return result + (rounding == Rounding.Up \u0026\u0026 10 ** result \u003c value ? 1 : 0);\n }\n }\n\n /**\n * @dev Return the log in base 256, rounded down, of a positive value.\n * Returns 0 if given 0.\n *\n * Adding one to the result gives the number of pairs of hex symbols needed to represent `value` as a hex string.\n */\n function log256(uint256 value) internal pure returns (uint256) {\n uint256 result = 0;\n unchecked {\n if (value \u003e\u003e 128 \u003e 0) {\n value \u003e\u003e= 128;\n result += 16;\n }\n if (value \u003e\u003e 64 \u003e 0) {\n value \u003e\u003e= 64;\n result += 8;\n }\n if (value \u003e\u003e 32 \u003e 0) {\n value \u003e\u003e= 32;\n result += 4;\n }\n if (value \u003e\u003e 16 \u003e 0) {\n value \u003e\u003e= 16;\n result += 2;\n }\n if (value \u003e\u003e 8 \u003e 0) {\n result += 1;\n }\n }\n return result;\n }\n\n /**\n * @dev Return the log in base 256, following the selected rounding direction, of a positive value.\n * Returns 0 if given 0.\n */\n function log256(uint256 value, Rounding rounding) internal pure returns (uint256) {\n unchecked {\n uint256 result = log256(value);\n return result + (rounding == Rounding.Up \u0026\u0026 1 \u003c\u003c (result \u003c\u003c 3) \u003c value ? 1 : 0);\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/utils/math/SignedMath.sol\n\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/math/SignedMath.sol)\n\n/**\n * @dev Standard signed math utilities missing in the Solidity language.\n */\nlibrary SignedMath {\n /**\n * @dev Returns the largest of two signed numbers.\n */\n function max(int256 a, int256 b) internal pure returns (int256) {\n return a \u003e b ? a : b;\n }\n\n /**\n * @dev Returns the smallest of two signed numbers.\n */\n function min(int256 a, int256 b) internal pure returns (int256) {\n return a \u003c b ? a : b;\n }\n\n /**\n * @dev Returns the average of two signed numbers without overflow.\n * The result is rounded towards zero.\n */\n function average(int256 a, int256 b) internal pure returns (int256) {\n // Formula from the book \"Hacker's Delight\"\n int256 x = (a \u0026 b) + ((a ^ b) \u003e\u003e 1);\n return x + (int256(uint256(x) \u003e\u003e 255) \u0026 (a ^ b));\n }\n\n /**\n * @dev Returns the absolute unsigned value of a signed value.\n */\n function abs(int256 n) internal pure returns (uint256) {\n unchecked {\n // must be unchecked in order to support `n = type(int256).min`\n return uint256(n \u003e= 0 ? n : -n);\n }\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// 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/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/InterfaceSummit.sol\n\ninterface InterfaceSummit {\n // ══════════════════════════════════════════ ACCEPT AGENT STATEMENTS ══════════════════════════════════════════════\n\n /**\n * @notice Accepts a receipt, which local `AgentManager` verified to have been signed by an active Notary.\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 * - Notary who signed the receipt is referenced as the \"Receipt Notary\".\n * - Notary who signed the attestation on destination chain is referenced as the \"Attestation Notary\".\n * \u003e Will revert if any of these is true:\n * \u003e - Called by anyone other than local `AgentManager`.\n * \u003e - Receipt body payload is not properly formatted.\n * \u003e - Receipt signer is in Dispute.\n * \u003e - Receipt's snapshot root is unknown.\n * @param rcptNotaryIndex Index of Receipt Notary in Agent Merkle Tree\n * @param attNotaryIndex Index of Attestation Notary in Agent Merkle Tree\n * @param sigIndex Index of stored Notary signature\n * @param attNonce Nonce of the attestation used for proving the executed message\n * @param paddedTips Padded encoded paid tips information\n * @param rcptPayload Raw payload with message execution receipt\n * @return wasAccepted Whether the receipt was accepted\n */\n function acceptReceipt(\n uint32 rcptNotaryIndex,\n uint32 attNotaryIndex,\n uint256 sigIndex,\n uint32 attNonce,\n uint256 paddedTips,\n bytes memory rcptPayload\n ) external returns (bool wasAccepted);\n\n /**\n * @notice Accepts a snapshot, which local `AgentManager` verified to have been signed by an active Guard.\n * \u003e Snapshot is a list of states for a set of Origin contracts residing on any of the chains.\n * All the states in the Guard-signed snapshot become available for Notary signing.\n * \u003e Will revert if any of these is true:\n * \u003e - Called by anyone other than local `AgentManager`.\n * \u003e - Snapshot payload is not properly formatted.\n * \u003e - Snapshot contains a state older then the Guard has previously submitted.\n * @param guardIndex Index of Guard in Agent Merkle Tree\n * @param sigIndex Index of stored Agent signature\n * @param snapPayload Raw payload with snapshot data\n */\n function acceptGuardSnapshot(uint32 guardIndex, uint256 sigIndex, bytes memory snapPayload) external;\n\n /**\n * @notice Accepts a snapshot, which local `AgentManager` verified to have been signed by an active Notary.\n * \u003e Snapshot is a list of states for a set of Origin contracts residing on any of the chains.\n * Snapshot Merkle Root is calculated and saved for valid snapshots, i.e.\n * snapshots which are only using states previously submitted by any of the Guards.\n * - Notary could use states singed by the same of different Guards 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 - Called by anyone other than local `AgentManager`.\n * \u003e - Snapshot payload is not properly formatted.\n * \u003e - Snapshot contains a state older then the Notary has previously submitted.\n * \u003e - Snapshot contains a state that no Guard has previously submitted.\n * @param notaryIndex Index of Notary in Agent Merkle Tree\n * @param sigIndex Index of stored Agent signature\n * @param agentRoot Current root of the Agent Merkle Tree\n * @param snapPayload Raw payload with snapshot data\n * @return attPayload Raw payload with data for attestation derived from Notary snapshot.\n */\n function acceptNotarySnapshot(uint32 notaryIndex, uint256 sigIndex, bytes32 agentRoot, bytes memory snapPayload)\n external\n returns (bytes memory attPayload);\n\n // ════════════════════════════════════════════════ TIPS LOGIC ═════════════════════════════════════════════════════\n\n /**\n * @notice Distributes tips using the first Receipt from the \"receipt quarantine queue\".\n * Possible scenarios:\n * - Receipt queue is empty =\u003e does nothing\n * - Receipt optimistic period is not over =\u003e does nothing\n * - Either of Notaries present in Receipt was slashed =\u003e receipt is deleted from the queue\n * - Either of Notaries present in Receipt in Dispute =\u003e receipt is moved to the end of queue\n * - None of the above =\u003e receipt tips are distributed\n * @dev Returned value makes it possible to do the following: `while (distributeTips()) {}`\n * @return queuePopped Whether the first element was popped from the queue\n */\n function distributeTips() external returns (bool queuePopped);\n\n /**\n * @notice Withdraws locked base message tips from requested domain Origin to the recipient.\n * This is done by a call to a local Origin contract, or by a manager message to the remote chain.\n * @dev This will revert, if the pending balance of origin tips (earned-claimed) is lower than requested.\n * @param origin Domain of chain to withdraw tips on\n * @param amount Amount of tips to withdraw\n */\n function withdrawTips(uint32 origin, uint256 amount) external;\n\n // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════\n\n /**\n * @notice Returns earned and claimed tips for the actor.\n * Note: Tips for address(0) belong to the Treasury.\n * @param actor Address of the actor\n * @param origin Domain where the tips were initially paid\n * @return earned Total amount of origin tips the actor has earned so far\n * @return claimed Total amount of origin tips the actor has claimed so far\n */\n function actorTips(address actor, uint32 origin) external view returns (uint128 earned, uint128 claimed);\n\n /**\n * @notice Returns the amount of receipts in the \"Receipt Quarantine Queue\".\n */\n function receiptQueueLength() external view returns (uint256);\n\n /**\n * @notice Returns the state with the highest known nonce\n * submitted by any of the currently active Guards.\n * @param origin Domain of origin chain\n * @return statePayload Raw payload with latest active Guard state for origin\n */\n function getLatestState(uint32 origin) external view returns (bytes memory statePayload);\n}\n\n// node_modules/@openzeppelin/contracts/utils/Strings.sol\n\n// OpenZeppelin Contracts (last updated v4.9.0) (utils/Strings.sol)\n\n/**\n * @dev String operations.\n */\nlibrary Strings {\n bytes16 private constant _SYMBOLS = \"0123456789abcdef\";\n uint8 private constant _ADDRESS_LENGTH = 20;\n\n /**\n * @dev Converts a `uint256` to its ASCII `string` decimal representation.\n */\n function toString(uint256 value) internal pure returns (string memory) {\n unchecked {\n uint256 length = Math.log10(value) + 1;\n string memory buffer = new string(length);\n uint256 ptr;\n /// @solidity memory-safe-assembly\n assembly {\n ptr := add(buffer, add(32, length))\n }\n while (true) {\n ptr--;\n /// @solidity memory-safe-assembly\n assembly {\n mstore8(ptr, byte(mod(value, 10), _SYMBOLS))\n }\n value /= 10;\n if (value == 0) break;\n }\n return buffer;\n }\n }\n\n /**\n * @dev Converts a `int256` to its ASCII `string` decimal representation.\n */\n function toString(int256 value) internal pure returns (string memory) {\n return string(abi.encodePacked(value \u003c 0 ? \"-\" : \"\", toString(SignedMath.abs(value))));\n }\n\n /**\n * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation.\n */\n function toHexString(uint256 value) internal pure returns (string memory) {\n unchecked {\n return toHexString(value, Math.log256(value) + 1);\n }\n }\n\n /**\n * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length.\n */\n function toHexString(uint256 value, uint256 length) internal pure returns (string memory) {\n bytes memory buffer = new bytes(2 * length + 2);\n buffer[0] = \"0\";\n buffer[1] = \"x\";\n for (uint256 i = 2 * length + 1; i \u003e 1; --i) {\n buffer[i] = _SYMBOLS[value \u0026 0xf];\n value \u003e\u003e= 4;\n }\n require(value == 0, \"Strings: hex length insufficient\");\n return string(buffer);\n }\n\n /**\n * @dev Converts an `address` with fixed length of 20 bytes to its not checksummed ASCII `string` hexadecimal representation.\n */\n function toHexString(address addr) internal pure returns (string memory) {\n return toHexString(uint256(uint160(addr)), _ADDRESS_LENGTH);\n }\n\n /**\n * @dev Returns true if the two strings are equal.\n */\n function equal(string memory a, string memory b) internal pure returns (bool) {\n return keccak256(bytes(a)) == keccak256(bytes(b));\n }\n}\n\n// node_modules/@openzeppelin/contracts-upgradeable/utils/ContextUpgradeable.sol\n\n// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)\n\n/**\n * @dev Provides information about the current execution context, including the\n * sender of the transaction and its data. While these are generally available\n * via msg.sender and msg.data, they should not be accessed in such a direct\n * manner, since when dealing with meta-transactions the account sending and\n * paying for execution may not be the actual sender (as far as an application\n * is concerned).\n *\n * This contract is only required for intermediate, library-like contracts.\n */\nabstract contract ContextUpgradeable is Initializable {\n function __Context_init() internal onlyInitializing {\n }\n\n function __Context_init_unchained() internal onlyInitializing {\n }\n function _msgSender() internal view virtual returns (address) {\n return msg.sender;\n }\n\n function _msgData() internal view virtual returns (bytes calldata) {\n return msg.data;\n }\n\n /**\n * @dev This empty reserved space is put in place to allow future versions to add new\n * variables without shifting down storage in the inheritance chain.\n * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\n */\n uint256[50] private __gap;\n}\n\n// contracts/libs/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/utils/cryptography/ECDSA.sol\n\n// OpenZeppelin Contracts (last updated v4.9.0) (utils/cryptography/ECDSA.sol)\n\n/**\n * @dev Elliptic Curve Digital Signature Algorithm (ECDSA) operations.\n *\n * These functions can be used to verify that a message was signed by the holder\n * of the private keys of a given address.\n */\nlibrary ECDSA {\n enum RecoverError {\n NoError,\n InvalidSignature,\n InvalidSignatureLength,\n InvalidSignatureS,\n InvalidSignatureV // Deprecated in v4.8\n }\n\n function _throwError(RecoverError error) private pure {\n if (error == RecoverError.NoError) {\n return; // no error: do nothing\n } else if (error == RecoverError.InvalidSignature) {\n revert(\"ECDSA: invalid signature\");\n } else if (error == RecoverError.InvalidSignatureLength) {\n revert(\"ECDSA: invalid signature length\");\n } else if (error == RecoverError.InvalidSignatureS) {\n revert(\"ECDSA: invalid signature 's' value\");\n }\n }\n\n /**\n * @dev Returns the address that signed a hashed message (`hash`) with\n * `signature` or error string. This address can then be used for verification purposes.\n *\n * The `ecrecover` EVM opcode allows for malleable (non-unique) signatures:\n * this function rejects them by requiring the `s` value to be in the lower\n * half order, and the `v` value to be either 27 or 28.\n *\n * IMPORTANT: `hash` _must_ be the result of a hash operation for the\n * verification to be secure: it is possible to craft signatures that\n * recover to arbitrary addresses for non-hashed data. A safe way to ensure\n * this is by receiving a hash of the original message (which may otherwise\n * be too long), and then calling {toEthSignedMessageHash} on it.\n *\n * Documentation for signature generation:\n * - with https://web3js.readthedocs.io/en/v1.3.4/web3-eth-accounts.html#sign[Web3.js]\n * - with https://docs.ethers.io/v5/api/signer/#Signer-signMessage[ethers]\n *\n * _Available since v4.3._\n */\n function tryRecover(bytes32 hash, bytes memory signature) internal pure returns (address, RecoverError) {\n if (signature.length == 65) {\n bytes32 r;\n bytes32 s;\n uint8 v;\n // ecrecover takes the signature parameters, and the only way to get them\n // currently is to use assembly.\n /// @solidity memory-safe-assembly\n assembly {\n r := mload(add(signature, 0x20))\n s := mload(add(signature, 0x40))\n v := byte(0, mload(add(signature, 0x60)))\n }\n return tryRecover(hash, v, r, s);\n } else {\n return (address(0), RecoverError.InvalidSignatureLength);\n }\n }\n\n /**\n * @dev Returns the address that signed a hashed message (`hash`) with\n * `signature`. This address can then be used for verification purposes.\n *\n * The `ecrecover` EVM opcode allows for malleable (non-unique) signatures:\n * this function rejects them by requiring the `s` value to be in the lower\n * half order, and the `v` value to be either 27 or 28.\n *\n * IMPORTANT: `hash` _must_ be the result of a hash operation for the\n * verification to be secure: it is possible to craft signatures that\n * recover to arbitrary addresses for non-hashed data. A safe way to ensure\n * this is by receiving a hash of the original message (which may otherwise\n * be too long), and then calling {toEthSignedMessageHash} on it.\n */\n function recover(bytes32 hash, bytes memory signature) internal pure returns (address) {\n (address recovered, RecoverError error) = tryRecover(hash, signature);\n _throwError(error);\n return recovered;\n }\n\n /**\n * @dev Overload of {ECDSA-tryRecover} that receives the `r` and `vs` short-signature fields separately.\n *\n * See https://eips.ethereum.org/EIPS/eip-2098[EIP-2098 short signatures]\n *\n * _Available since v4.3._\n */\n function tryRecover(bytes32 hash, bytes32 r, bytes32 vs) internal pure returns (address, RecoverError) {\n bytes32 s = vs \u0026 bytes32(0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff);\n uint8 v = uint8((uint256(vs) \u003e\u003e 255) + 27);\n return tryRecover(hash, v, r, s);\n }\n\n /**\n * @dev Overload of {ECDSA-recover} that receives the `r and `vs` short-signature fields separately.\n *\n * _Available since v4.2._\n */\n function recover(bytes32 hash, bytes32 r, bytes32 vs) internal pure returns (address) {\n (address recovered, RecoverError error) = tryRecover(hash, r, vs);\n _throwError(error);\n return recovered;\n }\n\n /**\n * @dev Overload of {ECDSA-tryRecover} that receives the `v`,\n * `r` and `s` signature fields separately.\n *\n * _Available since v4.3._\n */\n function tryRecover(bytes32 hash, uint8 v, bytes32 r, bytes32 s) internal pure returns (address, RecoverError) {\n // EIP-2 still allows signature malleability for ecrecover(). Remove this possibility and make the signature\n // unique. Appendix F in the Ethereum Yellow paper (https://ethereum.github.io/yellowpaper/paper.pdf), defines\n // the valid range for s in (301): 0 \u003c s \u003c secp256k1n ÷ 2 + 1, and for v in (302): v ∈ {27, 28}. Most\n // signatures from current libraries generate a unique signature with an s-value in the lower half order.\n //\n // If your library generates malleable signatures, such as s-values in the upper range, calculate a new s-value\n // with 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141 - s1 and flip v from 27 to 28 or\n // vice versa. If your library also generates signatures with 0/1 for v instead 27/28, add 27 to v to accept\n // these malleable signatures as well.\n if (uint256(s) \u003e 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0) {\n return (address(0), RecoverError.InvalidSignatureS);\n }\n\n // If the signature is valid (and not malleable), return the signer address\n address signer = ecrecover(hash, v, r, s);\n if (signer == address(0)) {\n return (address(0), RecoverError.InvalidSignature);\n }\n\n return (signer, RecoverError.NoError);\n }\n\n /**\n * @dev Overload of {ECDSA-recover} that receives the `v`,\n * `r` and `s` signature fields separately.\n */\n function recover(bytes32 hash, uint8 v, bytes32 r, bytes32 s) internal pure returns (address) {\n (address recovered, RecoverError error) = tryRecover(hash, v, r, s);\n _throwError(error);\n return recovered;\n }\n\n /**\n * @dev Returns an Ethereum Signed Message, created from a `hash`. This\n * produces hash corresponding to the one signed with the\n * https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`]\n * JSON-RPC method as part of EIP-191.\n *\n * See {recover}.\n */\n function toEthSignedMessageHash(bytes32 hash) internal pure returns (bytes32 message) {\n // 32 is the length in bytes of hash,\n // enforced by the type signature above\n /// @solidity memory-safe-assembly\n assembly {\n mstore(0x00, \"\\x19Ethereum Signed Message:\\n32\")\n mstore(0x1c, hash)\n message := keccak256(0x00, 0x3c)\n }\n }\n\n /**\n * @dev Returns an Ethereum Signed Message, created from `s`. This\n * produces hash corresponding to the one signed with the\n * https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`]\n * JSON-RPC method as part of EIP-191.\n *\n * See {recover}.\n */\n function toEthSignedMessageHash(bytes memory s) internal pure returns (bytes32) {\n return keccak256(abi.encodePacked(\"\\x19Ethereum Signed Message:\\n\", Strings.toString(s.length), s));\n }\n\n /**\n * @dev Returns an Ethereum Signed Typed Data, created from a\n * `domainSeparator` and a `structHash`. This produces hash corresponding\n * to the one signed with the\n * https://eips.ethereum.org/EIPS/eip-712[`eth_signTypedData`]\n * JSON-RPC method as part of EIP-712.\n *\n * See {recover}.\n */\n function toTypedDataHash(bytes32 domainSeparator, bytes32 structHash) internal pure returns (bytes32 data) {\n /// @solidity memory-safe-assembly\n assembly {\n let ptr := mload(0x40)\n mstore(ptr, \"\\x19\\x01\")\n mstore(add(ptr, 0x02), domainSeparator)\n mstore(add(ptr, 0x22), structHash)\n data := keccak256(ptr, 0x42)\n }\n }\n\n /**\n * @dev Returns an Ethereum Signed Data with intended validator, created from a\n * `validator` and `data` according to the version 0 of EIP-191.\n *\n * See {recover}.\n */\n function toDataWithIntendedValidatorHash(address validator, bytes memory data) internal pure returns (bytes32) {\n return keccak256(abi.encodePacked(\"\\x19\\x00\", validator, data));\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/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/inbox/StatementInbox.sol\n\n// ══════════════════════════════ LIBRARY IMPORTS ══════════════════════════════\n\n// ═════════════════════════════ INTERNAL IMPORTS ══════════════════════════════\n\n// ═════════════════════════════ EXTERNAL IMPORTS ══════════════════════════════\n\n/// @notice `StatementInbox` is the entry point for all agent-signed statements. It verifies the\n/// agent signatures, and passes the unsigned statements to the contract to consume it via `acceptX` functions. Is is\n/// also used to verify the agent-signed statements and initiate the agent slashing, should the statement be invalid.\n/// `StatementInbox` is responsible for the following:\n/// - Accepting State and Receipt Reports to initiate a dispute between Guard and Notary.\n/// - Storing all the Guard Reports with the Guard signature leading to a dispute.\n/// - Verifying State/State Reports referencing the local chain and slashing the signer if statement is invalid.\n/// - Verifying Receipt/Receipt Reports referencing the local chain and slashing the signer if statement is invalid.\nabstract contract StatementInbox is MessagingBase, StatementInboxEvents, IStatementInbox {\n using AttestationLib for bytes;\n using ReceiptLib for bytes;\n using StateLib for bytes;\n using SnapshotLib for bytes;\n\n struct StoredReport {\n uint256 sigIndex;\n bytes statementPayload;\n }\n\n // ══════════════════════════════════════════════════ STORAGE ══════════════════════════════════════════════════════\n\n address public agentManager;\n address public origin;\n address public destination;\n\n // TODO: optimize this\n bytes[] internal _storedSignatures;\n StoredReport[] internal _storedReports;\n\n /// @dev gap for upgrade safety\n uint256[45] private __GAP; // solhint-disable-line var-name-mixedcase\n\n // ════════════════════════════════════════════════ INITIALIZER ════════════════════════════════════════════════════\n\n /// @dev Initializes the contract:\n /// - Sets up `msg.sender` as the owner of the contract.\n /// - Sets up `agentManager`, `origin`, and `destination`.\n // solhint-disable-next-line func-name-mixedcase\n function __StatementInbox_init(address agentManager_, address origin_, address destination_)\n internal\n onlyInitializing\n {\n agentManager = agentManager_;\n origin = origin_;\n destination = destination_;\n __Ownable2Step_init();\n }\n\n // ══════════════════════════════════════════ SUBMIT AGENT STATEMENTS ══════════════════════════════════════════════\n\n /// @inheritdoc IStatementInbox\n // solhint-disable-next-line ordering\n function submitStateReportWithSnapshot(\n uint8 stateIndex,\n bytes memory srSignature,\n bytes memory snapPayload,\n bytes memory snapSignature\n ) external returns (bool wasAccepted) {\n // This will revert if payload is not a snapshot\n Snapshot snapshot = snapPayload.castToSnapshot();\n // This will revert if the snapshot signer is not a known Notary\n (AgentStatus memory notaryStatus,) =\n _verifySnapshot({snapshot: snapshot, snapSignature: snapSignature, verifyNotary: true});\n // Notary needs to be Active/Unstaking\n notaryStatus.verifyActiveUnstaking();\n // Check if Notary is active on this chain\n _verifyNotaryDomain(notaryStatus.domain);\n // This will revert if state index is out of range\n State state = snapshot.state(stateIndex);\n // This will revert if the report signer is not an known Guard\n (AgentStatus memory guardStatus,) = _verifyStateReport(state, srSignature);\n // Check that Guard is active\n guardStatus.verifyActive();\n _saveReport(state.unwrap().clone(), srSignature);\n // This will revert if either actor is already in dispute\n IAgentManager(agentManager).openDispute(guardStatus.index, notaryStatus.index);\n return true;\n }\n\n /// @inheritdoc IStatementInbox\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 // This will revert if payload is not a snapshot\n Snapshot snapshot = snapPayload.castToSnapshot();\n // This will revert if state index is out of range\n State state = snapshot.state(stateIndex);\n // This will revert if the report signer is not an known Guard\n (AgentStatus memory guardStatus,) = _verifyStateReport(state, srSignature);\n // Check that Guard is active\n guardStatus.verifyActive();\n // This will revert if payload is not an attestation\n Attestation att = attPayload.castToAttestation();\n // This will revert if signer is not an known Notary\n (AgentStatus memory notaryStatus,) = _verifyAttestation(att, attSignature);\n // Notary needs to be Active/Unstaking\n notaryStatus.verifyActiveUnstaking();\n // Check if Notary is active on this chain\n _verifyNotaryDomain(notaryStatus.domain);\n if (snapshot.calculateRoot() != att.snapRoot()) revert IncorrectSnapshotRoot();\n _saveReport(state.unwrap().clone(), srSignature);\n // This will revert if either actor is already in dispute\n IAgentManager(agentManager).openDispute(guardStatus.index, notaryStatus.index);\n return true;\n }\n\n /// @inheritdoc IStatementInbox\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 // This will revert if payload is not a state\n State state = statePayload.castToState();\n // This will revert if the report signer is not an known Guard\n (AgentStatus memory guardStatus,) = _verifyStateReport(state, srSignature);\n // Check that Guard is active\n guardStatus.verifyActive();\n // This will revert if payload is not an attestation\n Attestation att = attPayload.castToAttestation();\n // This will revert if signer is not a known Notary\n (AgentStatus memory notaryStatus,) = _verifyAttestation(att, attSignature);\n // Notary needs to be Active/Unstaking\n notaryStatus.verifyActiveUnstaking();\n // Check if Notary is active on this chain\n _verifyNotaryDomain(notaryStatus.domain);\n // This will revert if any of these is true:\n // - Attestation root is not equal to Merkle Root derived from State and Snapshot Proof.\n // - Snapshot Proof's first element does not match the State metadata.\n // - Snapshot Proof length exceeds Snapshot tree Height.\n // - State index is out of range.\n _verifySnapshotMerkle(att, stateIndex, state, snapProof);\n _saveReport(statePayload, srSignature);\n // This will revert if either actor is already in dispute\n IAgentManager(agentManager).openDispute(guardStatus.index, notaryStatus.index);\n return true;\n }\n\n // ══════════════════════════════════════════ VERIFY AGENT STATEMENTS ══════════════════════════════════════════════\n\n /// @inheritdoc IStatementInbox\n function verifyReceipt(bytes memory rcptPayload, bytes memory rcptSignature)\n external\n returns (bool isValidReceipt)\n {\n // This will revert if payload is not a receipt\n Receipt rcpt = rcptPayload.castToReceipt();\n // This will revert if the attestation signer is not a known Notary\n (AgentStatus memory status, address notary) = _verifyReceipt(rcpt, rcptSignature);\n // Notary needs to be Active/Unstaking\n status.verifyActiveUnstaking();\n isValidReceipt = IExecutionHub(destination).isValidReceipt(rcptPayload);\n if (!isValidReceipt) {\n emit InvalidReceipt(rcptPayload, rcptSignature);\n IAgentManager(agentManager).slashAgent(status.domain, notary, msg.sender);\n }\n }\n\n /// @inheritdoc IStatementInbox\n function verifyReceiptReport(bytes memory rcptPayload, bytes memory rrSignature)\n external\n returns (bool isValidReport)\n {\n // This will revert if payload is not a receipt\n Receipt rcpt = rcptPayload.castToReceipt();\n // This will revert if the report signer is not a known Guard\n (AgentStatus memory status, address guard) = _verifyReceiptReport(rcpt, rrSignature);\n // Guard needs to be Active/Unstaking\n status.verifyActiveUnstaking();\n // Report is valid IF AND ONLY IF the reported receipt in invalid\n isValidReport = !IExecutionHub(destination).isValidReceipt(rcptPayload);\n if (!isValidReport) {\n emit InvalidReceiptReport(rcptPayload, rrSignature);\n IAgentManager(agentManager).slashAgent(status.domain, guard, msg.sender);\n }\n }\n\n /// @inheritdoc IStatementInbox\n function verifyStateWithAttestation(\n uint8 stateIndex,\n bytes memory snapPayload,\n bytes memory attPayload,\n bytes memory attSignature\n ) external returns (bool isValidState) {\n // This will revert if payload is not an attestation\n Attestation att = attPayload.castToAttestation();\n // This will revert if the attestation signer is not a known Notary\n (AgentStatus memory status, address notary) = _verifyAttestation(att, attSignature);\n // Notary needs to be Active/Unstaking\n status.verifyActiveUnstaking();\n // This will revert if payload is not a snapshot\n Snapshot snapshot = snapPayload.castToSnapshot();\n if (snapshot.calculateRoot() != att.snapRoot()) revert IncorrectSnapshotRoot();\n // This will revert if state does not refer to this chain\n bytes memory statePayload = snapshot.state(stateIndex).unwrap().clone();\n isValidState = IStateHub(origin).isValidState(statePayload);\n if (!isValidState) {\n emit InvalidStateWithAttestation(stateIndex, statePayload, attPayload, attSignature);\n IAgentManager(agentManager).slashAgent(status.domain, notary, msg.sender);\n }\n }\n\n /// @inheritdoc IStatementInbox\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 // This will revert if payload is not an attestation\n Attestation att = attPayload.castToAttestation();\n // This will revert if the attestation signer is not a known Notary\n (AgentStatus memory status, address notary) = _verifyAttestation(att, attSignature);\n // Notary needs to be Active/Unstaking\n status.verifyActiveUnstaking();\n // This will revert if payload is not a state\n State state = statePayload.castToState();\n // This will revert if any of these is true:\n // - Attestation root is not equal to Merkle Root derived from State and Snapshot Proof.\n // - Snapshot Proof's first element does not match the State metadata.\n // - Snapshot Proof length exceeds Snapshot tree Height.\n // - State index is out of range.\n _verifySnapshotMerkle(att, stateIndex, state, snapProof);\n // This will revert if state does not refer to this chain\n isValidState = IStateHub(origin).isValidState(statePayload);\n if (!isValidState) {\n emit InvalidStateWithAttestation(stateIndex, statePayload, attPayload, attSignature);\n IAgentManager(agentManager).slashAgent(status.domain, notary, msg.sender);\n }\n }\n\n /// @inheritdoc IStatementInbox\n function verifyStateWithSnapshot(uint8 stateIndex, bytes memory snapPayload, bytes memory snapSignature)\n external\n returns (bool isValidState)\n {\n // This will revert if payload is not a snapshot\n Snapshot snapshot = snapPayload.castToSnapshot();\n // This will revert if the snapshot signer is not a known Guard/Notary\n (AgentStatus memory status, address agent) =\n _verifySnapshot({snapshot: snapshot, snapSignature: snapSignature, verifyNotary: false});\n // Agent needs to be Active/Unstaking\n status.verifyActiveUnstaking();\n // This will revert if state does not refer to this chain\n isValidState = IStateHub(origin).isValidState(snapshot.state(stateIndex).unwrap().clone());\n if (!isValidState) {\n emit InvalidStateWithSnapshot(stateIndex, snapPayload, snapSignature);\n IAgentManager(agentManager).slashAgent(status.domain, agent, msg.sender);\n }\n }\n\n /// @inheritdoc IStatementInbox\n function verifyStateReport(bytes memory statePayload, bytes memory srSignature)\n external\n returns (bool isValidReport)\n {\n // This will revert if payload is not a state\n State state = statePayload.castToState();\n // This will revert if the report signer is not a known Guard\n (AgentStatus memory status, address guard) = _verifyStateReport(state, srSignature);\n // Guard needs to be Active/Unstaking\n status.verifyActiveUnstaking();\n // Report is valid IF AND ONLY IF the reported state in invalid\n // This will revert if the reported state does not refer to this chain\n isValidReport = !IStateHub(origin).isValidState(statePayload);\n if (!isValidReport) {\n emit InvalidStateReport(statePayload, srSignature);\n IAgentManager(agentManager).slashAgent(status.domain, guard, msg.sender);\n }\n }\n\n // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════\n\n /// @inheritdoc IStatementInbox\n function getReportsAmount() external view returns (uint256) {\n return _storedReports.length;\n }\n\n /// @inheritdoc IStatementInbox\n function getGuardReport(uint256 index)\n external\n view\n returns (bytes memory statementPayload, bytes memory reportSignature)\n {\n if (index \u003e= _storedReports.length) revert IndexOutOfRange();\n StoredReport memory storedReport = _storedReports[index];\n statementPayload = storedReport.statementPayload;\n reportSignature = _storedSignatures[storedReport.sigIndex];\n }\n\n /// @inheritdoc IStatementInbox\n function getStoredSignature(uint256 index) external view returns (bytes memory) {\n return _storedSignatures[index];\n }\n\n // ══════════════════════════════════════════════ INTERNAL LOGIC ═══════════════════════════════════════════════════\n\n /// @dev Saves the statement reported by Guard as invalid and the Guard Report signature.\n function _saveReport(bytes memory statementPayload, bytes memory reportSignature) internal {\n uint256 sigIndex = _saveSignature(reportSignature);\n _storedReports.push(StoredReport(sigIndex, statementPayload));\n }\n\n /// @dev Saves the signature and returns its index.\n function _saveSignature(bytes memory signature) internal returns (uint256 sigIndex) {\n sigIndex = _storedSignatures.length;\n _storedSignatures.push(signature);\n }\n\n // ═══════════════════════════════════════════════ AGENT CHECKS ════════════════════════════════════════════════════\n\n /**\n * @dev Recovers a signer from a hashed message, and a EIP-191 signature for it.\n * Will revert, if the signer is not a known agent.\n * @dev Agent flag could be any of these: Active/Unstaking/Resting/Fraudulent/Slashed\n * Further checks need to be performed in a caller function.\n * @param hashedStatement Hash of the statement that was signed by an Agent\n * @param signature Agent signature for the hashed statement\n * @return status Struct representing agent status:\n * - flag Unknown/Active/Unstaking/Resting/Fraudulent/Slashed\n * - domain Domain where agent is/was active\n * - index Index of agent in the Agent Merkle Tree\n * @return agent Agent that signed the statement\n */\n function _recoverAgent(bytes32 hashedStatement, bytes memory signature)\n internal\n view\n returns (AgentStatus memory status, address agent)\n {\n bytes32 ethSignedMsg = ECDSA.toEthSignedMessageHash(hashedStatement);\n agent = ECDSA.recover(ethSignedMsg, signature);\n status = IAgentManager(agentManager).agentStatus(agent);\n // Discard signature of unknown agents.\n // Further flag checks are supposed to be performed in a caller function.\n status.verifyKnown();\n }\n\n /// @dev Verifies that Notary signature is active on local domain.\n function _verifyNotaryDomain(uint32 notaryDomain) internal view {\n // Notary needs to be from the local domain (if contract is not deployed on Synapse Chain).\n // Or Notary could be from any domain (if contract is deployed on Synapse Chain).\n if (notaryDomain != localDomain \u0026\u0026 localDomain != synapseDomain) revert IncorrectAgentDomain();\n }\n\n // ════════════════════════════════════════ ATTESTATION RELATED CHECKS ═════════════════════════════════════════════\n\n /**\n * @dev Internal function to verify the signed attestation payload.\n * Reverts if any of these is true:\n * - Attestation signer is not a known Notary.\n * @param att Typed memory view over attestation payload\n * @param attSignature Notary signature for the attestation\n * @return status Struct representing agent status, see {_recoverAgent}\n * @return notary Notary that signed the snapshot\n */\n function _verifyAttestation(Attestation att, bytes memory attSignature)\n internal\n view\n returns (AgentStatus memory status, address notary)\n {\n // This will revert if signer is not a known agent\n (status, notary) = _recoverAgent(att.hashValid(), attSignature);\n // Attestation signer needs to be a Notary, not a Guard\n if (status.domain == 0) revert AgentNotNotary();\n }\n\n /**\n * @dev Internal function to verify the signed attestation report payload.\n * Reverts if any of these is true:\n * - Report signer is not a known Guard.\n * @param att Typed memory view over attestation payload that Guard reports as invalid\n * @param arSignature Guard signature for the \"invalid attestation\" report\n * @return status Struct representing guard status, see {_recoverAgent}\n * @return guard Guard that signed the report\n */\n function _verifyAttestationReport(Attestation att, bytes memory arSignature)\n internal\n view\n returns (AgentStatus memory status, address guard)\n {\n // This will revert if signer is not a known agent\n (status, guard) = _recoverAgent(att.hashInvalid(), arSignature);\n // Report signer needs to be a Guard, not a Notary\n if (status.domain != 0) revert AgentNotGuard();\n }\n\n // ══════════════════════════════════════════ RECEIPT RELATED CHECKS ═══════════════════════════════════════════════\n\n /**\n * @dev Internal function to verify the signed receipt payload.\n * Reverts if any of these is true:\n * - Receipt signer is not a known Notary.\n * @param rcpt Typed memory view over receipt payload\n * @param rcptSignature Notary signature for the receipt\n * @return status Struct representing agent status, see {_recoverAgent}\n * @return notary Notary that signed the snapshot\n */\n function _verifyReceipt(Receipt rcpt, bytes memory rcptSignature)\n internal\n view\n returns (AgentStatus memory status, address notary)\n {\n // This will revert if signer is not a known agent\n (status, notary) = _recoverAgent(rcpt.hashValid(), rcptSignature);\n // Receipt signer needs to be a Notary, not a Guard\n if (status.domain == 0) revert AgentNotNotary();\n }\n\n /**\n * @dev Internal function to verify the signed receipt report payload.\n * Reverts if any of these is true:\n * - Report signer is not a known Guard.\n * @param rcpt Typed memory view over receipt payload that Guard reports as invalid\n * @param rrSignature Guard signature for the \"invalid receipt\" report\n * @return status Struct representing guard status, see {_recoverAgent}\n * @return guard Guard that signed the report\n */\n function _verifyReceiptReport(Receipt rcpt, bytes memory rrSignature)\n internal\n view\n returns (AgentStatus memory status, address guard)\n {\n // This will revert if signer is not a known agent\n (status, guard) = _recoverAgent(rcpt.hashInvalid(), rrSignature);\n // Report signer needs to be a Guard, not a Notary\n if (status.domain != 0) revert AgentNotGuard();\n }\n\n // ═══════════════════════════════════════ STATE/SNAPSHOT RELATED CHECKS ═══════════════════════════════════════════\n\n /**\n * @dev Internal function to verify the signed snapshot report payload.\n * Reverts if any of these is true:\n * - Report signer is not a known Guard.\n * @param state Typed memory view over state payload that Guard reports as invalid\n * @param srSignature Guard signature for the report\n * @return status Struct representing guard status, see {_recoverAgent}\n * @return guard Guard that signed the report\n */\n function _verifyStateReport(State state, bytes memory srSignature)\n internal\n view\n returns (AgentStatus memory status, address guard)\n {\n // This will revert if signer is not a known agent\n (status, guard) = _recoverAgent(state.hashInvalid(), srSignature);\n // Report signer needs to be a Guard, not a Notary\n if (status.domain != 0) revert AgentNotGuard();\n }\n\n /**\n * @dev Internal function to verify the signed snapshot payload.\n * Reverts if any of these is true:\n * - Snapshot signer is not a known Agent.\n * - Snapshot signer is not a Notary (if verifyNotary is true).\n * @param snapshot Typed memory view over snapshot payload\n * @param snapSignature Agent signature for the snapshot\n * @param verifyNotary If true, snapshot signer needs to be a Notary, not a Guard\n * @return status Struct representing agent status, see {_recoverAgent}\n * @return agent Agent that signed the snapshot\n */\n function _verifySnapshot(Snapshot snapshot, bytes memory snapSignature, bool verifyNotary)\n internal\n view\n returns (AgentStatus memory status, address agent)\n {\n // This will revert if signer is not a known agent\n (status, agent) = _recoverAgent(snapshot.hashValid(), snapSignature);\n // If requested, snapshot signer needs to be a Notary, not a Guard\n if (verifyNotary \u0026\u0026 status.domain == 0) revert AgentNotNotary();\n }\n\n // ═══════════════════════════════════════════ MERKLE RELATED CHECKS ═══════════════════════════════════════════════\n\n /**\n * @dev Internal function to verify that snapshot roots match.\n * Reverts if any of these is true:\n * - Attestation root is not equal to Merkle Root derived from State and Snapshot Proof.\n * - Snapshot Proof's first element does not match the State metadata.\n * - Snapshot Proof length exceeds Snapshot tree Height.\n * - State index is out of range.\n * @param att Typed memory view over Attestation\n * @param stateIndex Index of state in the snapshot\n * @param state Typed memory view over the provided state payload\n * @param snapProof Raw payload with snapshot data\n */\n function _verifySnapshotMerkle(Attestation att, uint8 stateIndex, State state, bytes32[] memory snapProof)\n internal\n pure\n {\n // Snapshot proof first element should match State metadata (aka \"right sub-leaf\")\n (, bytes32 rightSubLeaf) = state.subLeafs();\n if (snapProof[0] != rightSubLeaf) revert IncorrectSnapshotProof();\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(state.root(), state.origin(), snapProof, stateIndex);\n // Snapshot root should match the attestation root\n if (att.snapRoot() != snapshotRoot) revert IncorrectSnapshotRoot();\n }\n}\n\n// contracts/inbox/Inbox.sol\n\n// ══════════════════════════════ LIBRARY IMPORTS ══════════════════════════════\n\n// ═════════════════════════════ INTERNAL IMPORTS ══════════════════════════════\n\n/// @notice `Inbox` is the child of `StatementInbox` contract, that is used on Synapse Chain.\n/// In addition to the functionality of `StatementInbox`, it also:\n/// - Accepts Guard and Notary Snapshots and passes them to `Summit` contract.\n/// - Accepts Notary-signed Receipts and passes them to `Summit` contract.\n/// - Accepts Receipt Reports to initiate a dispute between Guard and Notary.\n/// - Verifies Attestations and Attestation Reports, and slashes the signer if they are invalid.\ncontract Inbox is StatementInbox, InboxEvents, InterfaceInbox {\n using AttestationLib for bytes;\n using ReceiptLib for bytes;\n using SnapshotLib for bytes;\n\n // Struct to get around stack too deep error. TODO: revisit this\n struct ReceiptInfo {\n AgentStatus rcptNotaryStatus;\n address notary;\n uint32 attNonce;\n AgentStatus attNotaryStatus;\n }\n\n // ══════════════════════════════════════════════════ STORAGE ══════════════════════════════════════════════════════\n\n // The address of the Summit contract.\n address public summit;\n\n // ═════════════════════════════════════════ CONSTRUCTOR \u0026 INITIALIZER ═════════════════════════════════════════════\n\n constructor(uint32 synapseDomain_) MessagingBase(\"0.0.3\", synapseDomain_) {\n if (localDomain != synapseDomain) revert MustBeSynapseDomain();\n }\n\n /// @notice Initializes `Inbox` contract:\n /// - Sets `msg.sender` as the owner of the contract\n /// - Sets `agentManager`, `origin`, `destination` and `summit` addresses\n function initialize(address agentManager_, address origin_, address destination_, address summit_)\n external\n initializer\n {\n __StatementInbox_init(agentManager_, origin_, destination_);\n summit = summit_;\n }\n\n // ══════════════════════════════════════════ SUBMIT AGENT STATEMENTS ══════════════════════════════════════════════\n\n /// @inheritdoc InterfaceInbox\n function submitSnapshot(bytes memory snapPayload, bytes memory snapSignature)\n external\n returns (bytes memory attPayload, bytes32 agentRoot_, uint256[] memory snapGas)\n {\n // This will revert if payload is not a snapshot\n Snapshot snapshot = snapPayload.castToSnapshot();\n // This will revert if the signer is not a known Guard/Notary\n (AgentStatus memory status, address agent) =\n _verifySnapshot({snapshot: snapshot, snapSignature: snapSignature, verifyNotary: false});\n // Check that Agent is active\n status.verifyActive();\n // Store Agent signature for the Snapshot\n uint256 sigIndex = _saveSignature(snapSignature);\n if (status.domain == 0) {\n // Guard that is in Dispute could still submit new snapshots, so we don't check that\n InterfaceSummit(summit).acceptGuardSnapshot({\n guardIndex: status.index,\n sigIndex: sigIndex,\n snapPayload: snapPayload\n });\n } else {\n // Get current agentRoot from AgentManager\n agentRoot_ = IAgentManager(agentManager).agentRoot();\n // This will revert if Notary is in Dispute\n attPayload = InterfaceSummit(summit).acceptNotarySnapshot({\n notaryIndex: status.index,\n sigIndex: sigIndex,\n agentRoot: agentRoot_,\n snapPayload: snapPayload\n });\n ChainGas[] memory snapGas_ = snapshot.snapGas();\n // Pass created attestation to Destination to enable executing messages coming to Synapse Chain\n InterfaceDestination(destination).acceptAttestation(\n status.index, type(uint256).max, attPayload, agentRoot_, snapGas_\n );\n // Use assembly to cast ChainGas[] to uint256[] without copying. Highest bits are left zeroed.\n // solhint-disable-next-line no-inline-assembly\n assembly {\n snapGas := snapGas_\n }\n }\n emit SnapshotAccepted(status.domain, agent, snapPayload, snapSignature);\n }\n\n /// @inheritdoc InterfaceInbox\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 // Struct to get around stack too deep error.\n ReceiptInfo memory info;\n // This will revert if payload is not a receipt\n Receipt rcpt = rcptPayload.castToReceipt();\n // This will revert if the receipt signer is not a known Notary\n (info.rcptNotaryStatus, info.notary) = _verifyReceipt(rcpt, rcptSignature);\n // Receipt Notary needs to be Active\n info.rcptNotaryStatus.verifyActive();\n info.attNonce = IExecutionHub(destination).getAttestationNonce(rcpt.snapshotRoot());\n if (info.attNonce == 0) revert IncorrectSnapshotRoot();\n // Attestation Notary domain needs to match the destination domain\n info.attNotaryStatus = IAgentManager(agentManager).agentStatus(rcpt.attNotary());\n if (info.attNotaryStatus.domain != rcpt.destination()) revert IncorrectAgentDomain();\n // Check that the correct tip values for the message were provided\n _verifyReceiptTips(rcpt.messageHash(), paddedTips, headerHash, bodyHash);\n // Store Notary signature for the Receipt\n uint256 sigIndex = _saveSignature(rcptSignature);\n // This will revert if Receipt Notary is in Dispute\n wasAccepted = InterfaceSummit(summit).acceptReceipt({\n rcptNotaryIndex: info.rcptNotaryStatus.index,\n attNotaryIndex: info.attNotaryStatus.index,\n sigIndex: sigIndex,\n attNonce: info.attNonce,\n paddedTips: paddedTips,\n rcptPayload: rcptPayload\n });\n if (wasAccepted) {\n emit ReceiptAccepted(info.rcptNotaryStatus.domain, info.notary, rcptPayload, rcptSignature);\n }\n }\n\n /// @inheritdoc InterfaceInbox\n function submitReceiptReport(bytes memory rcptPayload, bytes memory rcptSignature, bytes memory rrSignature)\n external\n returns (bool wasAccepted)\n {\n // This will revert if payload is not a receipt\n Receipt rcpt = rcptPayload.castToReceipt();\n // This will revert if the receipt signer is not a known Guard\n (AgentStatus memory guardStatus,) = _verifyReceiptReport(rcpt, rrSignature);\n // Guard needs to be Active\n guardStatus.verifyActive();\n // This will revert if report signer is not a known Notary\n (AgentStatus memory notaryStatus,) = _verifyReceipt(rcpt, rcptSignature);\n // Notary needs to be Active/Unstaking\n notaryStatus.verifyActiveUnstaking();\n _saveReport(rcptPayload, rrSignature);\n // This will revert if either actor is already in dispute\n IAgentManager(agentManager).openDispute(guardStatus.index, notaryStatus.index);\n return true;\n }\n\n /// @inheritdoc InterfaceInbox\n function passReceipt(uint32 attNotaryIndex, uint32 attNonce, uint256 paddedTips, bytes memory rcptPayload)\n external\n returns (bool wasAccepted)\n {\n // Only Destination can pass receipts\n if (msg.sender != destination) revert CallerNotDestination();\n return InterfaceSummit(summit).acceptReceipt({\n rcptNotaryIndex: attNotaryIndex,\n attNotaryIndex: attNotaryIndex,\n sigIndex: type(uint256).max,\n attNonce: attNonce,\n paddedTips: paddedTips,\n rcptPayload: rcptPayload\n });\n }\n\n // ══════════════════════════════════════════ VERIFY AGENT STATEMENTS ══════════════════════════════════════════════\n\n /// @inheritdoc InterfaceInbox\n function verifyAttestation(bytes memory attPayload, bytes memory attSignature)\n external\n returns (bool isValidAttestation)\n {\n // This will revert if payload is not an attestation\n Attestation att = attPayload.castToAttestation();\n // This will revert if the attestation signer is not a known Notary\n (AgentStatus memory status, address notary) = _verifyAttestation(att, attSignature);\n // Notary needs to be Active/Unstaking\n status.verifyActiveUnstaking();\n isValidAttestation = ISnapshotHub(summit).isValidAttestation(attPayload);\n if (!isValidAttestation) {\n emit InvalidAttestation(attPayload, attSignature);\n IAgentManager(agentManager).slashAgent(status.domain, notary, msg.sender);\n }\n }\n\n /// @inheritdoc InterfaceInbox\n function verifyAttestationReport(bytes memory attPayload, bytes memory arSignature)\n external\n returns (bool isValidReport)\n {\n // This will revert if payload is not an attestation\n Attestation att = attPayload.castToAttestation();\n // This will revert if the report signer is not a known Guard\n (AgentStatus memory status, address guard) = _verifyAttestationReport(att, arSignature);\n // Guard needs to be Active/Unstaking\n status.verifyActiveUnstaking();\n // Report is valid IF AND ONLY IF the reported attestation in invalid\n isValidReport = !ISnapshotHub(summit).isValidAttestation(attPayload);\n if (!isValidReport) {\n emit InvalidAttestationReport(attPayload, arSignature);\n IAgentManager(agentManager).slashAgent(status.domain, guard, msg.sender);\n }\n }\n\n // ══════════════════════════════════════════════ INTERNAL VIEWS ═══════════════════════════════════════════════════\n\n /// @dev Verifies that tips proof matches the message hash.\n function _verifyReceiptTips(bytes32 msgHash, uint256 paddedTips, bytes32 headerHash, bytes32 bodyHash)\n internal\n pure\n {\n Tips tips = TipsLib.wrapPadded(paddedTips);\n // full message leaf is (header, baseMessage), while base message leaf is (tips, remainingBody).\n if (MerkleMath.getParent(headerHash, MerkleMath.getParent(tips.leaf(), bodyHash)) != msgHash) {\n revert IncorrectTipsProof();\n }\n }\n}\n","language":"Solidity","languageVersion":"0.8.17","compilerVersion":"0.8.17","compilerOptions":"--combined-json bin,bin-runtime,srcmap,srcmap-runtime,abi,userdoc,devdoc,metadata,hashes --optimize --optimize-runs 10000 --allow-paths ., ./, ../","srcMap":"","srcMapRuntime":"","abiDefinition":[{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint8","name":"version","type":"uint8"}],"name":"Initialized","type":"event"}],"userDoc":{"kind":"user","methods":{},"version":1},"developerDoc":{"custom:oz-upgrades-unsafe-allow":"constructor constructor() { _disableInitializers(); } ``` ====","details":"This is a base contract to aid in writing upgradeable contracts, or any kind of contract that will be deployed behind a proxy. Since proxied contracts do not make use of a constructor, it's common to move constructor logic to an external initializer function, usually called `initialize`. It then becomes necessary to protect this initializer function so it can only be called once. The {initializer} modifier provided by this contract will have this effect. The initialization functions use a version number. Once a version number is used, it is consumed and cannot be reused. This mechanism prevents re-execution of each \"step\" but allows the creation of new initialization steps in case an upgrade adds a module that needs to be initialized. For example: [.hljs-theme-light.nopadding] ```solidity contract MyToken is ERC20Upgradeable { function initialize() initializer public { __ERC20_init(\"MyToken\", \"MTK\"); } } contract MyTokenV2 is MyToken, ERC20PermitUpgradeable { function initializeV2() reinitializer(2) public { __ERC20Permit_init(\"MyToken\"); } } ``` TIP: To avoid leaving the proxy in an uninitialized state, the initializer function should be called as early as possible by providing the encoded function call as the `_data` argument to {ERC1967Proxy-constructor}. CAUTION: When used with inheritance, manual care must be taken to not invoke a parent initializer twice, or to ensure that all initializers are idempotent. This is not verified automatically as constructors are by Solidity. [CAUTION] ==== Avoid leaving a contract uninitialized. An uninitialized contract can be taken over by an attacker. This applies to both a proxy and its implementation contract, which may impact the proxy. To prevent the implementation contract from being used, you should invoke the {_disableInitializers} function in the constructor to automatically lock it when it is deployed: [.hljs-theme-light.nopadding] ```","events":{"Initialized(uint8)":{"details":"Triggered when the contract has been initialized or reinitialized."}},"kind":"dev","methods":{},"stateVariables":{"_initialized":{"custom:oz-retyped-from":"bool","details":"Indicates that the contract has been initialized."},"_initializing":{"details":"Indicates that the contract is in the process of being initialized."}},"version":1},"metadata":"{\"compiler\":{\"version\":\"0.8.17+commit.8df45f5f\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint8\",\"name\":\"version\",\"type\":\"uint8\"}],\"name\":\"Initialized\",\"type\":\"event\"}],\"devdoc\":{\"custom:oz-upgrades-unsafe-allow\":\"constructor constructor() { _disableInitializers(); } ``` ====\",\"details\":\"This is a base contract to aid in writing upgradeable contracts, or any kind of contract that will be deployed behind a proxy. Since proxied contracts do not make use of a constructor, it's common to move constructor logic to an external initializer function, usually called `initialize`. It then becomes necessary to protect this initializer function so it can only be called once. The {initializer} modifier provided by this contract will have this effect. The initialization functions use a version number. Once a version number is used, it is consumed and cannot be reused. This mechanism prevents re-execution of each \\\"step\\\" but allows the creation of new initialization steps in case an upgrade adds a module that needs to be initialized. For example: [.hljs-theme-light.nopadding] ```solidity contract MyToken is ERC20Upgradeable { function initialize() initializer public { __ERC20_init(\\\"MyToken\\\", \\\"MTK\\\"); } } contract MyTokenV2 is MyToken, ERC20PermitUpgradeable { function initializeV2() reinitializer(2) public { __ERC20Permit_init(\\\"MyToken\\\"); } } ``` TIP: To avoid leaving the proxy in an uninitialized state, the initializer function should be called as early as possible by providing the encoded function call as the `_data` argument to {ERC1967Proxy-constructor}. CAUTION: When used with inheritance, manual care must be taken to not invoke a parent initializer twice, or to ensure that all initializers are idempotent. This is not verified automatically as constructors are by Solidity. [CAUTION] ==== Avoid leaving a contract uninitialized. An uninitialized contract can be taken over by an attacker. This applies to both a proxy and its implementation contract, which may impact the proxy. To prevent the implementation contract from being used, you should invoke the {_disableInitializers} function in the constructor to automatically lock it when it is deployed: [.hljs-theme-light.nopadding] ```\",\"events\":{\"Initialized(uint8)\":{\"details\":\"Triggered when the contract has been initialized or reinitialized.\"}},\"kind\":\"dev\",\"methods\":{},\"stateVariables\":{\"_initialized\":{\"custom:oz-retyped-from\":\"bool\",\"details\":\"Indicates that the contract has been initialized.\"},\"_initializing\":{\"details\":\"Indicates that the contract is in the process of being initialized.\"}},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"solidity/Inbox.sol\":\"Initializable\"},\"evmVersion\":\"london\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\"},\"optimizer\":{\"enabled\":true,\"runs\":10000},\"remappings\":[]},\"sources\":{\"solidity/Inbox.sol\":{\"keccak256\":\"0x9b516081a036814c0169e20e484d4a5499066b7a6f48fada952b5e844a1ca3e5\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://32bde393b3f24ef4307d9626d4143f337b3c0bd34e17bb969fd5a15221d96987\",\"dweb:/ipfs/QmTkt2XZRtgsbSpmsVQUM3c4ebETQoDVYbmEV9yheBghnr\"]}},\"version\":1}"},"hashes":{}},"solidity/Inbox.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/InboxEvents.sol\n\nabstract contract InboxEvents {\n /**\n * @notice Emitted when a snapshot is accepted by the Summit contract.\n * @param domain Domain where the signed Agent is active (ZERO for Guards)\n * @param agent Agent who signed the snapshot\n * @param snapPayload Raw payload with snapshot data\n * @param snapSignature Agent signature for the snapshot\n */\n event SnapshotAccepted(uint32 indexed domain, address indexed agent, bytes snapPayload, bytes snapSignature);\n\n /**\n * @notice Emitted when a snapshot is accepted by the Summit contract.\n * @param domain Domain where the signed Notary is active\n * @param notary Notary who signed the attestation\n * @param rcptPayload Raw payload with receipt data\n * @param rcptSignature Notary signature for the receipt\n */\n event ReceiptAccepted(uint32 domain, address notary, bytes rcptPayload, bytes rcptSignature);\n\n /**\n * @notice Emitted when a proof of invalid attestation is submitted.\n * @param attPayload Raw payload with Attestation data\n * @param attSignature Notary signature for the attestation\n */\n event InvalidAttestation(bytes attPayload, bytes attSignature);\n\n /**\n * @notice Emitted when a proof of invalid attestation report is submitted.\n * @param arPayload Raw payload with report data\n * @param arSignature Guard signature for the report\n */\n event InvalidAttestationReport(bytes arPayload, bytes arSignature);\n}\n\n// contracts/events/StatementInboxEvents.sol\n\nabstract contract StatementInboxEvents {\n // ════════════════════════════════════════════ STATEMENT ACCEPTED ═════════════════════════════════════════════════\n\n /**\n * @notice Emitted when a snapshot is accepted by the Destination contract.\n * @param domain Domain where the signed Notary is active\n * @param notary Notary who signed the attestation\n * @param attPayload Raw payload with attestation data\n * @param attSignature Notary signature for the attestation\n */\n event AttestationAccepted(uint32 domain, address notary, bytes attPayload, bytes attSignature);\n\n // ═════════════════════════════════════════ INVALID STATEMENT PROVED ══════════════════════════════════════════════\n\n /**\n * @notice Emitted when a proof of invalid receipt statement is submitted.\n * @param rcptPayload Raw payload with the receipt statement\n * @param rcptSignature Notary signature for the receipt statement\n */\n event InvalidReceipt(bytes rcptPayload, bytes rcptSignature);\n\n /**\n * @notice Emitted when a proof of invalid receipt report is submitted.\n * @param rrPayload Raw payload with report data\n * @param rrSignature Guard signature for the report\n */\n event InvalidReceiptReport(bytes rrPayload, bytes rrSignature);\n\n /**\n * @notice Emitted when a proof of invalid state in the signed attestation is submitted.\n * @param stateIndex Index of invalid state in the snapshot\n * @param statePayload Raw payload with state data\n * @param attPayload Raw payload with Attestation data for snapshot\n * @param attSignature Notary signature for the attestation\n */\n event InvalidStateWithAttestation(uint8 stateIndex, bytes statePayload, bytes attPayload, bytes attSignature);\n\n /**\n * @notice Emitted when a proof of invalid state in the signed snapshot is submitted.\n * @param stateIndex Index of invalid state in the snapshot\n * @param snapPayload Raw payload with snapshot data\n * @param snapSignature Agent signature for the snapshot\n */\n event InvalidStateWithSnapshot(uint8 stateIndex, bytes snapPayload, bytes snapSignature);\n\n /**\n * @notice Emitted when a proof of invalid state report is submitted.\n * @param srPayload Raw payload with report data\n * @param srSignature Guard signature for the report\n */\n event InvalidStateReport(bytes srPayload, bytes srSignature);\n}\n\n// contracts/interfaces/ISnapshotHub.sol\n\ninterface ISnapshotHub {\n /**\n * @notice Check that a given attestation is valid: matches the historical attestation\n * derived from an accepted Notary snapshot.\n * @dev Will revert if any of these is true:\n * - Attestation payload is not properly formatted.\n * @param attPayload Raw payload with attestation data\n * @return isValid Whether the provided attestation is valid\n */\n function isValidAttestation(bytes memory attPayload) external view returns (bool isValid);\n\n /**\n * @notice Returns saved attestation with the given nonce.\n * @dev Reverts if attestation with given nonce hasn't been created yet.\n * @param attNonce Nonce for the attestation\n * @return attPayload Raw payload with formatted Attestation data\n * @return agentRoot Agent root hash used for the attestation\n * @return snapGas Snapshot gas data used for the attestation\n */\n function getAttestation(uint32 attNonce)\n external\n view\n returns (bytes memory attPayload, bytes32 agentRoot, uint256[] memory snapGas);\n\n /**\n * @notice Returns the state with the highest known nonce submitted by a given Agent.\n * @param origin Domain of origin chain\n * @param agent Agent address\n * @return statePayload Raw payload with agent's latest state for origin\n */\n function getLatestAgentState(uint32 origin, address agent) external view returns (bytes memory statePayload);\n\n /**\n * @notice Returns latest saved attestation for a Notary.\n * @param notary Notary address\n * @return attPayload Raw payload with formatted Attestation data\n * @return agentRoot Agent root hash used for the attestation\n * @return snapGas Snapshot gas data used for the attestation\n */\n function getLatestNotaryAttestation(address notary)\n external\n view\n returns (bytes memory attPayload, bytes32 agentRoot, uint256[] memory snapGas);\n\n /**\n * @notice Returns Guard snapshot from the list of all accepted Guard snapshots.\n * @dev Reverts if snapshot with given index hasn't been accepted yet.\n * @param index Snapshot index in the list of all Guard snapshots\n * @return snapPayload Raw payload with Guard snapshot\n * @return snapSignature Raw payload with Guard signature for snapshot\n */\n function getGuardSnapshot(uint256 index)\n external\n view\n returns (bytes memory snapPayload, bytes memory snapSignature);\n\n /**\n * @notice Returns Notary snapshot from the list of all accepted Guard snapshots.\n * @dev Reverts if snapshot with given index hasn't been accepted yet.\n * @param index Snapshot index in the list of all Notary snapshots\n * @return snapPayload Raw payload with Notary snapshot\n * @return snapSignature Raw payload with Notary signature for snapshot\n */\n function getNotarySnapshot(uint256 index)\n external\n view\n returns (bytes memory snapPayload, bytes memory snapSignature);\n\n /**\n * @notice Returns Notary snapshot that was used for creating a given attestation.\n * @dev Reverts if any of these is true:\n * - Attestation payload is not properly formatted.\n * - Attestation is invalid (doesn't have a matching Notary snapshot).\n * @param attPayload Raw payload with attestation data\n * @return snapPayload Raw payload with Notary snapshot\n * @return snapSignature Raw payload with Notary signature for snapshot\n */\n function getNotarySnapshot(bytes memory attPayload)\n external\n view\n returns (bytes memory snapPayload, bytes memory snapSignature);\n\n /**\n * @notice Returns proof of inclusion of (root, origin) fields of a given snapshot's state\n * into the Snapshot Merkle Tree for a given attestation.\n * @dev Reverts if any of these is true:\n * - Attestation with given nonce hasn't been created yet.\n * - State index is out of range of snapshot list.\n * @param attNonce Nonce for the attestation\n * @param stateIndex Index of state in the attestation's snapshot\n * @return snapProof The snapshot proof\n */\n function getSnapshotProof(uint32 attNonce, uint8 stateIndex) external view returns (bytes32[] memory snapProof);\n}\n\n// contracts/interfaces/IStateHub.sol\n\ninterface IStateHub {\n /**\n * @notice Check that a given state is valid: matches the historical state of Origin contract.\n * Note: any Agent including an invalid state in their snapshot will be slashed\n * upon providing the snapshot and agent signature for it to Origin contract.\n * @dev Will revert if any of these is true:\n * - State payload is not properly formatted.\n * @param statePayload Raw payload with state data\n * @return isValid Whether the provided state is valid\n */\n function isValidState(bytes memory statePayload) external view returns (bool isValid);\n\n /**\n * @notice Returns the amount of saved states so far.\n * @dev This includes the initial state of \"empty Origin Merkle Tree\".\n */\n function statesAmount() external view returns (uint256);\n\n /**\n * @notice Suggest the data (state after latest sent message) to sign for an Agent.\n * Note: signing the suggested state data will will never lead to slashing of the actor,\n * assuming they have confirmed that the block, which number is included in the data,\n * is not subject to reorganization (which is different for every observed chain).\n * @return statePayload Raw payload with the latest state data\n */\n function suggestLatestState() external view returns (bytes memory statePayload);\n\n /**\n * @notice Given the historical nonce, suggest the state data to sign for an Agent.\n * Note: signing the suggested state data will will never lead to slashing of the actor,\n * assuming they have confirmed that the block, which number is included in the data,\n * is not subject to reorganization (which is different for every observed chain).\n * @param nonce Historical nonce to form a state\n * @return statePayload Raw payload with historical state data\n */\n function suggestState(uint32 nonce) external view returns (bytes memory statePayload);\n}\n\n// contracts/interfaces/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/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// node_modules/@openzeppelin/contracts/utils/math/Math.sol\n\n// OpenZeppelin Contracts (last updated v4.9.0) (utils/math/Math.sol)\n\n/**\n * @dev Standard math utilities missing in the Solidity language.\n */\nlibrary Math {\n enum Rounding {\n Down, // Toward negative infinity\n Up, // Toward infinity\n Zero // Toward zero\n }\n\n /**\n * @dev Returns the largest of two numbers.\n */\n function max(uint256 a, uint256 b) internal pure returns (uint256) {\n return a \u003e b ? a : b;\n }\n\n /**\n * @dev Returns the smallest of two numbers.\n */\n function min(uint256 a, uint256 b) internal pure returns (uint256) {\n return a \u003c b ? a : b;\n }\n\n /**\n * @dev Returns the average of two numbers. The result is rounded towards\n * zero.\n */\n function average(uint256 a, uint256 b) internal pure returns (uint256) {\n // (a + b) / 2 can overflow.\n return (a \u0026 b) + (a ^ b) / 2;\n }\n\n /**\n * @dev Returns the ceiling of the division of two numbers.\n *\n * This differs from standard division with `/` in that it rounds up instead\n * of rounding down.\n */\n function ceilDiv(uint256 a, uint256 b) internal pure returns (uint256) {\n // (a + b - 1) / b can overflow on addition, so we distribute.\n return a == 0 ? 0 : (a - 1) / b + 1;\n }\n\n /**\n * @notice Calculates floor(x * y / denominator) with full precision. Throws if result overflows a uint256 or denominator == 0\n * @dev Original credit to Remco Bloemen under MIT license (https://xn--2-umb.com/21/muldiv)\n * with further edits by Uniswap Labs also under MIT license.\n */\n function mulDiv(uint256 x, uint256 y, uint256 denominator) internal pure returns (uint256 result) {\n unchecked {\n // 512-bit multiply [prod1 prod0] = x * y. Compute the product mod 2^256 and mod 2^256 - 1, then use\n // use the Chinese Remainder Theorem to reconstruct the 512 bit result. The result is stored in two 256\n // variables such that product = prod1 * 2^256 + prod0.\n uint256 prod0; // Least significant 256 bits of the product\n uint256 prod1; // Most significant 256 bits of the product\n assembly {\n let mm := mulmod(x, y, not(0))\n prod0 := mul(x, y)\n prod1 := sub(sub(mm, prod0), lt(mm, prod0))\n }\n\n // Handle non-overflow cases, 256 by 256 division.\n if (prod1 == 0) {\n // Solidity will revert if denominator == 0, unlike the div opcode on its own.\n // The surrounding unchecked block does not change this fact.\n // See https://docs.soliditylang.org/en/latest/control-structures.html#checked-or-unchecked-arithmetic.\n return prod0 / denominator;\n }\n\n // Make sure the result is less than 2^256. Also prevents denominator == 0.\n require(denominator \u003e prod1, \"Math: mulDiv overflow\");\n\n ///////////////////////////////////////////////\n // 512 by 256 division.\n ///////////////////////////////////////////////\n\n // Make division exact by subtracting the remainder from [prod1 prod0].\n uint256 remainder;\n assembly {\n // Compute remainder using mulmod.\n remainder := mulmod(x, y, denominator)\n\n // Subtract 256 bit number from 512 bit number.\n prod1 := sub(prod1, gt(remainder, prod0))\n prod0 := sub(prod0, remainder)\n }\n\n // Factor powers of two out of denominator and compute largest power of two divisor of denominator. Always \u003e= 1.\n // See https://cs.stackexchange.com/q/138556/92363.\n\n // Does not overflow because the denominator cannot be zero at this stage in the function.\n uint256 twos = denominator \u0026 (~denominator + 1);\n assembly {\n // Divide denominator by twos.\n denominator := div(denominator, twos)\n\n // Divide [prod1 prod0] by twos.\n prod0 := div(prod0, twos)\n\n // Flip twos such that it is 2^256 / twos. If twos is zero, then it becomes one.\n twos := add(div(sub(0, twos), twos), 1)\n }\n\n // Shift in bits from prod1 into prod0.\n prod0 |= prod1 * twos;\n\n // Invert denominator mod 2^256. Now that denominator is an odd number, it has an inverse modulo 2^256 such\n // that denominator * inv = 1 mod 2^256. Compute the inverse by starting with a seed that is correct for\n // four bits. That is, denominator * inv = 1 mod 2^4.\n uint256 inverse = (3 * denominator) ^ 2;\n\n // Use the Newton-Raphson iteration to improve the precision. Thanks to Hensel's lifting lemma, this also works\n // in modular arithmetic, doubling the correct bits in each step.\n inverse *= 2 - denominator * inverse; // inverse mod 2^8\n inverse *= 2 - denominator * inverse; // inverse mod 2^16\n inverse *= 2 - denominator * inverse; // inverse mod 2^32\n inverse *= 2 - denominator * inverse; // inverse mod 2^64\n inverse *= 2 - denominator * inverse; // inverse mod 2^128\n inverse *= 2 - denominator * inverse; // inverse mod 2^256\n\n // Because the division is now exact we can divide by multiplying with the modular inverse of denominator.\n // This will give us the correct result modulo 2^256. Since the preconditions guarantee that the outcome is\n // less than 2^256, this is the final result. We don't need to compute the high bits of the result and prod1\n // is no longer required.\n result = prod0 * inverse;\n return result;\n }\n }\n\n /**\n * @notice Calculates x * y / denominator with full precision, following the selected rounding direction.\n */\n function mulDiv(uint256 x, uint256 y, uint256 denominator, Rounding rounding) internal pure returns (uint256) {\n uint256 result = mulDiv(x, y, denominator);\n if (rounding == Rounding.Up \u0026\u0026 mulmod(x, y, denominator) \u003e 0) {\n result += 1;\n }\n return result;\n }\n\n /**\n * @dev Returns the square root of a number. If the number is not a perfect square, the value is rounded down.\n *\n * Inspired by Henry S. Warren, Jr.'s \"Hacker's Delight\" (Chapter 11).\n */\n function sqrt(uint256 a) internal pure returns (uint256) {\n if (a == 0) {\n return 0;\n }\n\n // For our first guess, we get the biggest power of 2 which is smaller than the square root of the target.\n //\n // We know that the \"msb\" (most significant bit) of our target number `a` is a power of 2 such that we have\n // `msb(a) \u003c= a \u003c 2*msb(a)`. This value can be written `msb(a)=2**k` with `k=log2(a)`.\n //\n // This can be rewritten `2**log2(a) \u003c= a \u003c 2**(log2(a) + 1)`\n // → `sqrt(2**k) \u003c= sqrt(a) \u003c sqrt(2**(k+1))`\n // → `2**(k/2) \u003c= sqrt(a) \u003c 2**((k+1)/2) \u003c= 2**(k/2 + 1)`\n //\n // Consequently, `2**(log2(a) / 2)` is a good first approximation of `sqrt(a)` with at least 1 correct bit.\n uint256 result = 1 \u003c\u003c (log2(a) \u003e\u003e 1);\n\n // At this point `result` is an estimation with one bit of precision. We know the true value is a uint128,\n // since it is the square root of a uint256. Newton's method converges quadratically (precision doubles at\n // every iteration). We thus need at most 7 iteration to turn our partial result with one bit of precision\n // into the expected uint128 result.\n unchecked {\n result = (result + a / result) \u003e\u003e 1;\n result = (result + a / result) \u003e\u003e 1;\n result = (result + a / result) \u003e\u003e 1;\n result = (result + a / result) \u003e\u003e 1;\n result = (result + a / result) \u003e\u003e 1;\n result = (result + a / result) \u003e\u003e 1;\n result = (result + a / result) \u003e\u003e 1;\n return min(result, a / result);\n }\n }\n\n /**\n * @notice Calculates sqrt(a), following the selected rounding direction.\n */\n function sqrt(uint256 a, Rounding rounding) internal pure returns (uint256) {\n unchecked {\n uint256 result = sqrt(a);\n return result + (rounding == Rounding.Up \u0026\u0026 result * result \u003c a ? 1 : 0);\n }\n }\n\n /**\n * @dev Return the log in base 2, rounded down, of a positive value.\n * Returns 0 if given 0.\n */\n function log2(uint256 value) internal pure returns (uint256) {\n uint256 result = 0;\n unchecked {\n if (value \u003e\u003e 128 \u003e 0) {\n value \u003e\u003e= 128;\n result += 128;\n }\n if (value \u003e\u003e 64 \u003e 0) {\n value \u003e\u003e= 64;\n result += 64;\n }\n if (value \u003e\u003e 32 \u003e 0) {\n value \u003e\u003e= 32;\n result += 32;\n }\n if (value \u003e\u003e 16 \u003e 0) {\n value \u003e\u003e= 16;\n result += 16;\n }\n if (value \u003e\u003e 8 \u003e 0) {\n value \u003e\u003e= 8;\n result += 8;\n }\n if (value \u003e\u003e 4 \u003e 0) {\n value \u003e\u003e= 4;\n result += 4;\n }\n if (value \u003e\u003e 2 \u003e 0) {\n value \u003e\u003e= 2;\n result += 2;\n }\n if (value \u003e\u003e 1 \u003e 0) {\n result += 1;\n }\n }\n return result;\n }\n\n /**\n * @dev Return the log in base 2, following the selected rounding direction, of a positive value.\n * Returns 0 if given 0.\n */\n function log2(uint256 value, Rounding rounding) internal pure returns (uint256) {\n unchecked {\n uint256 result = log2(value);\n return result + (rounding == Rounding.Up \u0026\u0026 1 \u003c\u003c result \u003c value ? 1 : 0);\n }\n }\n\n /**\n * @dev Return the log in base 10, rounded down, of a positive value.\n * Returns 0 if given 0.\n */\n function log10(uint256 value) internal pure returns (uint256) {\n uint256 result = 0;\n unchecked {\n if (value \u003e= 10 ** 64) {\n value /= 10 ** 64;\n result += 64;\n }\n if (value \u003e= 10 ** 32) {\n value /= 10 ** 32;\n result += 32;\n }\n if (value \u003e= 10 ** 16) {\n value /= 10 ** 16;\n result += 16;\n }\n if (value \u003e= 10 ** 8) {\n value /= 10 ** 8;\n result += 8;\n }\n if (value \u003e= 10 ** 4) {\n value /= 10 ** 4;\n result += 4;\n }\n if (value \u003e= 10 ** 2) {\n value /= 10 ** 2;\n result += 2;\n }\n if (value \u003e= 10 ** 1) {\n result += 1;\n }\n }\n return result;\n }\n\n /**\n * @dev Return the log in base 10, following the selected rounding direction, of a positive value.\n * Returns 0 if given 0.\n */\n function log10(uint256 value, Rounding rounding) internal pure returns (uint256) {\n unchecked {\n uint256 result = log10(value);\n return result + (rounding == Rounding.Up \u0026\u0026 10 ** result \u003c value ? 1 : 0);\n }\n }\n\n /**\n * @dev Return the log in base 256, rounded down, of a positive value.\n * Returns 0 if given 0.\n *\n * Adding one to the result gives the number of pairs of hex symbols needed to represent `value` as a hex string.\n */\n function log256(uint256 value) internal pure returns (uint256) {\n uint256 result = 0;\n unchecked {\n if (value \u003e\u003e 128 \u003e 0) {\n value \u003e\u003e= 128;\n result += 16;\n }\n if (value \u003e\u003e 64 \u003e 0) {\n value \u003e\u003e= 64;\n result += 8;\n }\n if (value \u003e\u003e 32 \u003e 0) {\n value \u003e\u003e= 32;\n result += 4;\n }\n if (value \u003e\u003e 16 \u003e 0) {\n value \u003e\u003e= 16;\n result += 2;\n }\n if (value \u003e\u003e 8 \u003e 0) {\n result += 1;\n }\n }\n return result;\n }\n\n /**\n * @dev Return the log in base 256, following the selected rounding direction, of a positive value.\n * Returns 0 if given 0.\n */\n function log256(uint256 value, Rounding rounding) internal pure returns (uint256) {\n unchecked {\n uint256 result = log256(value);\n return result + (rounding == Rounding.Up \u0026\u0026 1 \u003c\u003c (result \u003c\u003c 3) \u003c value ? 1 : 0);\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/utils/math/SignedMath.sol\n\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/math/SignedMath.sol)\n\n/**\n * @dev Standard signed math utilities missing in the Solidity language.\n */\nlibrary SignedMath {\n /**\n * @dev Returns the largest of two signed numbers.\n */\n function max(int256 a, int256 b) internal pure returns (int256) {\n return a \u003e b ? a : b;\n }\n\n /**\n * @dev Returns the smallest of two signed numbers.\n */\n function min(int256 a, int256 b) internal pure returns (int256) {\n return a \u003c b ? a : b;\n }\n\n /**\n * @dev Returns the average of two signed numbers without overflow.\n * The result is rounded towards zero.\n */\n function average(int256 a, int256 b) internal pure returns (int256) {\n // Formula from the book \"Hacker's Delight\"\n int256 x = (a \u0026 b) + ((a ^ b) \u003e\u003e 1);\n return x + (int256(uint256(x) \u003e\u003e 255) \u0026 (a ^ b));\n }\n\n /**\n * @dev Returns the absolute unsigned value of a signed value.\n */\n function abs(int256 n) internal pure returns (uint256) {\n unchecked {\n // must be unchecked in order to support `n = type(int256).min`\n return uint256(n \u003e= 0 ? n : -n);\n }\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// 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/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/InterfaceSummit.sol\n\ninterface InterfaceSummit {\n // ══════════════════════════════════════════ ACCEPT AGENT STATEMENTS ══════════════════════════════════════════════\n\n /**\n * @notice Accepts a receipt, which local `AgentManager` verified to have been signed by an active Notary.\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 * - Notary who signed the receipt is referenced as the \"Receipt Notary\".\n * - Notary who signed the attestation on destination chain is referenced as the \"Attestation Notary\".\n * \u003e Will revert if any of these is true:\n * \u003e - Called by anyone other than local `AgentManager`.\n * \u003e - Receipt body payload is not properly formatted.\n * \u003e - Receipt signer is in Dispute.\n * \u003e - Receipt's snapshot root is unknown.\n * @param rcptNotaryIndex Index of Receipt Notary in Agent Merkle Tree\n * @param attNotaryIndex Index of Attestation Notary in Agent Merkle Tree\n * @param sigIndex Index of stored Notary signature\n * @param attNonce Nonce of the attestation used for proving the executed message\n * @param paddedTips Padded encoded paid tips information\n * @param rcptPayload Raw payload with message execution receipt\n * @return wasAccepted Whether the receipt was accepted\n */\n function acceptReceipt(\n uint32 rcptNotaryIndex,\n uint32 attNotaryIndex,\n uint256 sigIndex,\n uint32 attNonce,\n uint256 paddedTips,\n bytes memory rcptPayload\n ) external returns (bool wasAccepted);\n\n /**\n * @notice Accepts a snapshot, which local `AgentManager` verified to have been signed by an active Guard.\n * \u003e Snapshot is a list of states for a set of Origin contracts residing on any of the chains.\n * All the states in the Guard-signed snapshot become available for Notary signing.\n * \u003e Will revert if any of these is true:\n * \u003e - Called by anyone other than local `AgentManager`.\n * \u003e - Snapshot payload is not properly formatted.\n * \u003e - Snapshot contains a state older then the Guard has previously submitted.\n * @param guardIndex Index of Guard in Agent Merkle Tree\n * @param sigIndex Index of stored Agent signature\n * @param snapPayload Raw payload with snapshot data\n */\n function acceptGuardSnapshot(uint32 guardIndex, uint256 sigIndex, bytes memory snapPayload) external;\n\n /**\n * @notice Accepts a snapshot, which local `AgentManager` verified to have been signed by an active Notary.\n * \u003e Snapshot is a list of states for a set of Origin contracts residing on any of the chains.\n * Snapshot Merkle Root is calculated and saved for valid snapshots, i.e.\n * snapshots which are only using states previously submitted by any of the Guards.\n * - Notary could use states singed by the same of different Guards 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 - Called by anyone other than local `AgentManager`.\n * \u003e - Snapshot payload is not properly formatted.\n * \u003e - Snapshot contains a state older then the Notary has previously submitted.\n * \u003e - Snapshot contains a state that no Guard has previously submitted.\n * @param notaryIndex Index of Notary in Agent Merkle Tree\n * @param sigIndex Index of stored Agent signature\n * @param agentRoot Current root of the Agent Merkle Tree\n * @param snapPayload Raw payload with snapshot data\n * @return attPayload Raw payload with data for attestation derived from Notary snapshot.\n */\n function acceptNotarySnapshot(uint32 notaryIndex, uint256 sigIndex, bytes32 agentRoot, bytes memory snapPayload)\n external\n returns (bytes memory attPayload);\n\n // ════════════════════════════════════════════════ TIPS LOGIC ═════════════════════════════════════════════════════\n\n /**\n * @notice Distributes tips using the first Receipt from the \"receipt quarantine queue\".\n * Possible scenarios:\n * - Receipt queue is empty =\u003e does nothing\n * - Receipt optimistic period is not over =\u003e does nothing\n * - Either of Notaries present in Receipt was slashed =\u003e receipt is deleted from the queue\n * - Either of Notaries present in Receipt in Dispute =\u003e receipt is moved to the end of queue\n * - None of the above =\u003e receipt tips are distributed\n * @dev Returned value makes it possible to do the following: `while (distributeTips()) {}`\n * @return queuePopped Whether the first element was popped from the queue\n */\n function distributeTips() external returns (bool queuePopped);\n\n /**\n * @notice Withdraws locked base message tips from requested domain Origin to the recipient.\n * This is done by a call to a local Origin contract, or by a manager message to the remote chain.\n * @dev This will revert, if the pending balance of origin tips (earned-claimed) is lower than requested.\n * @param origin Domain of chain to withdraw tips on\n * @param amount Amount of tips to withdraw\n */\n function withdrawTips(uint32 origin, uint256 amount) external;\n\n // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════\n\n /**\n * @notice Returns earned and claimed tips for the actor.\n * Note: Tips for address(0) belong to the Treasury.\n * @param actor Address of the actor\n * @param origin Domain where the tips were initially paid\n * @return earned Total amount of origin tips the actor has earned so far\n * @return claimed Total amount of origin tips the actor has claimed so far\n */\n function actorTips(address actor, uint32 origin) external view returns (uint128 earned, uint128 claimed);\n\n /**\n * @notice Returns the amount of receipts in the \"Receipt Quarantine Queue\".\n */\n function receiptQueueLength() external view returns (uint256);\n\n /**\n * @notice Returns the state with the highest known nonce\n * submitted by any of the currently active Guards.\n * @param origin Domain of origin chain\n * @return statePayload Raw payload with latest active Guard state for origin\n */\n function getLatestState(uint32 origin) external view returns (bytes memory statePayload);\n}\n\n// node_modules/@openzeppelin/contracts/utils/Strings.sol\n\n// OpenZeppelin Contracts (last updated v4.9.0) (utils/Strings.sol)\n\n/**\n * @dev String operations.\n */\nlibrary Strings {\n bytes16 private constant _SYMBOLS = \"0123456789abcdef\";\n uint8 private constant _ADDRESS_LENGTH = 20;\n\n /**\n * @dev Converts a `uint256` to its ASCII `string` decimal representation.\n */\n function toString(uint256 value) internal pure returns (string memory) {\n unchecked {\n uint256 length = Math.log10(value) + 1;\n string memory buffer = new string(length);\n uint256 ptr;\n /// @solidity memory-safe-assembly\n assembly {\n ptr := add(buffer, add(32, length))\n }\n while (true) {\n ptr--;\n /// @solidity memory-safe-assembly\n assembly {\n mstore8(ptr, byte(mod(value, 10), _SYMBOLS))\n }\n value /= 10;\n if (value == 0) break;\n }\n return buffer;\n }\n }\n\n /**\n * @dev Converts a `int256` to its ASCII `string` decimal representation.\n */\n function toString(int256 value) internal pure returns (string memory) {\n return string(abi.encodePacked(value \u003c 0 ? \"-\" : \"\", toString(SignedMath.abs(value))));\n }\n\n /**\n * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation.\n */\n function toHexString(uint256 value) internal pure returns (string memory) {\n unchecked {\n return toHexString(value, Math.log256(value) + 1);\n }\n }\n\n /**\n * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length.\n */\n function toHexString(uint256 value, uint256 length) internal pure returns (string memory) {\n bytes memory buffer = new bytes(2 * length + 2);\n buffer[0] = \"0\";\n buffer[1] = \"x\";\n for (uint256 i = 2 * length + 1; i \u003e 1; --i) {\n buffer[i] = _SYMBOLS[value \u0026 0xf];\n value \u003e\u003e= 4;\n }\n require(value == 0, \"Strings: hex length insufficient\");\n return string(buffer);\n }\n\n /**\n * @dev Converts an `address` with fixed length of 20 bytes to its not checksummed ASCII `string` hexadecimal representation.\n */\n function toHexString(address addr) internal pure returns (string memory) {\n return toHexString(uint256(uint160(addr)), _ADDRESS_LENGTH);\n }\n\n /**\n * @dev Returns true if the two strings are equal.\n */\n function equal(string memory a, string memory b) internal pure returns (bool) {\n return keccak256(bytes(a)) == keccak256(bytes(b));\n }\n}\n\n// node_modules/@openzeppelin/contracts-upgradeable/utils/ContextUpgradeable.sol\n\n// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)\n\n/**\n * @dev Provides information about the current execution context, including the\n * sender of the transaction and its data. While these are generally available\n * via msg.sender and msg.data, they should not be accessed in such a direct\n * manner, since when dealing with meta-transactions the account sending and\n * paying for execution may not be the actual sender (as far as an application\n * is concerned).\n *\n * This contract is only required for intermediate, library-like contracts.\n */\nabstract contract ContextUpgradeable is Initializable {\n function __Context_init() internal onlyInitializing {\n }\n\n function __Context_init_unchained() internal onlyInitializing {\n }\n function _msgSender() internal view virtual returns (address) {\n return msg.sender;\n }\n\n function _msgData() internal view virtual returns (bytes calldata) {\n return msg.data;\n }\n\n /**\n * @dev This empty reserved space is put in place to allow future versions to add new\n * variables without shifting down storage in the inheritance chain.\n * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\n */\n uint256[50] private __gap;\n}\n\n// contracts/libs/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/utils/cryptography/ECDSA.sol\n\n// OpenZeppelin Contracts (last updated v4.9.0) (utils/cryptography/ECDSA.sol)\n\n/**\n * @dev Elliptic Curve Digital Signature Algorithm (ECDSA) operations.\n *\n * These functions can be used to verify that a message was signed by the holder\n * of the private keys of a given address.\n */\nlibrary ECDSA {\n enum RecoverError {\n NoError,\n InvalidSignature,\n InvalidSignatureLength,\n InvalidSignatureS,\n InvalidSignatureV // Deprecated in v4.8\n }\n\n function _throwError(RecoverError error) private pure {\n if (error == RecoverError.NoError) {\n return; // no error: do nothing\n } else if (error == RecoverError.InvalidSignature) {\n revert(\"ECDSA: invalid signature\");\n } else if (error == RecoverError.InvalidSignatureLength) {\n revert(\"ECDSA: invalid signature length\");\n } else if (error == RecoverError.InvalidSignatureS) {\n revert(\"ECDSA: invalid signature 's' value\");\n }\n }\n\n /**\n * @dev Returns the address that signed a hashed message (`hash`) with\n * `signature` or error string. This address can then be used for verification purposes.\n *\n * The `ecrecover` EVM opcode allows for malleable (non-unique) signatures:\n * this function rejects them by requiring the `s` value to be in the lower\n * half order, and the `v` value to be either 27 or 28.\n *\n * IMPORTANT: `hash` _must_ be the result of a hash operation for the\n * verification to be secure: it is possible to craft signatures that\n * recover to arbitrary addresses for non-hashed data. A safe way to ensure\n * this is by receiving a hash of the original message (which may otherwise\n * be too long), and then calling {toEthSignedMessageHash} on it.\n *\n * Documentation for signature generation:\n * - with https://web3js.readthedocs.io/en/v1.3.4/web3-eth-accounts.html#sign[Web3.js]\n * - with https://docs.ethers.io/v5/api/signer/#Signer-signMessage[ethers]\n *\n * _Available since v4.3._\n */\n function tryRecover(bytes32 hash, bytes memory signature) internal pure returns (address, RecoverError) {\n if (signature.length == 65) {\n bytes32 r;\n bytes32 s;\n uint8 v;\n // ecrecover takes the signature parameters, and the only way to get them\n // currently is to use assembly.\n /// @solidity memory-safe-assembly\n assembly {\n r := mload(add(signature, 0x20))\n s := mload(add(signature, 0x40))\n v := byte(0, mload(add(signature, 0x60)))\n }\n return tryRecover(hash, v, r, s);\n } else {\n return (address(0), RecoverError.InvalidSignatureLength);\n }\n }\n\n /**\n * @dev Returns the address that signed a hashed message (`hash`) with\n * `signature`. This address can then be used for verification purposes.\n *\n * The `ecrecover` EVM opcode allows for malleable (non-unique) signatures:\n * this function rejects them by requiring the `s` value to be in the lower\n * half order, and the `v` value to be either 27 or 28.\n *\n * IMPORTANT: `hash` _must_ be the result of a hash operation for the\n * verification to be secure: it is possible to craft signatures that\n * recover to arbitrary addresses for non-hashed data. A safe way to ensure\n * this is by receiving a hash of the original message (which may otherwise\n * be too long), and then calling {toEthSignedMessageHash} on it.\n */\n function recover(bytes32 hash, bytes memory signature) internal pure returns (address) {\n (address recovered, RecoverError error) = tryRecover(hash, signature);\n _throwError(error);\n return recovered;\n }\n\n /**\n * @dev Overload of {ECDSA-tryRecover} that receives the `r` and `vs` short-signature fields separately.\n *\n * See https://eips.ethereum.org/EIPS/eip-2098[EIP-2098 short signatures]\n *\n * _Available since v4.3._\n */\n function tryRecover(bytes32 hash, bytes32 r, bytes32 vs) internal pure returns (address, RecoverError) {\n bytes32 s = vs \u0026 bytes32(0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff);\n uint8 v = uint8((uint256(vs) \u003e\u003e 255) + 27);\n return tryRecover(hash, v, r, s);\n }\n\n /**\n * @dev Overload of {ECDSA-recover} that receives the `r and `vs` short-signature fields separately.\n *\n * _Available since v4.2._\n */\n function recover(bytes32 hash, bytes32 r, bytes32 vs) internal pure returns (address) {\n (address recovered, RecoverError error) = tryRecover(hash, r, vs);\n _throwError(error);\n return recovered;\n }\n\n /**\n * @dev Overload of {ECDSA-tryRecover} that receives the `v`,\n * `r` and `s` signature fields separately.\n *\n * _Available since v4.3._\n */\n function tryRecover(bytes32 hash, uint8 v, bytes32 r, bytes32 s) internal pure returns (address, RecoverError) {\n // EIP-2 still allows signature malleability for ecrecover(). Remove this possibility and make the signature\n // unique. Appendix F in the Ethereum Yellow paper (https://ethereum.github.io/yellowpaper/paper.pdf), defines\n // the valid range for s in (301): 0 \u003c s \u003c secp256k1n ÷ 2 + 1, and for v in (302): v ∈ {27, 28}. Most\n // signatures from current libraries generate a unique signature with an s-value in the lower half order.\n //\n // If your library generates malleable signatures, such as s-values in the upper range, calculate a new s-value\n // with 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141 - s1 and flip v from 27 to 28 or\n // vice versa. If your library also generates signatures with 0/1 for v instead 27/28, add 27 to v to accept\n // these malleable signatures as well.\n if (uint256(s) \u003e 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0) {\n return (address(0), RecoverError.InvalidSignatureS);\n }\n\n // If the signature is valid (and not malleable), return the signer address\n address signer = ecrecover(hash, v, r, s);\n if (signer == address(0)) {\n return (address(0), RecoverError.InvalidSignature);\n }\n\n return (signer, RecoverError.NoError);\n }\n\n /**\n * @dev Overload of {ECDSA-recover} that receives the `v`,\n * `r` and `s` signature fields separately.\n */\n function recover(bytes32 hash, uint8 v, bytes32 r, bytes32 s) internal pure returns (address) {\n (address recovered, RecoverError error) = tryRecover(hash, v, r, s);\n _throwError(error);\n return recovered;\n }\n\n /**\n * @dev Returns an Ethereum Signed Message, created from a `hash`. This\n * produces hash corresponding to the one signed with the\n * https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`]\n * JSON-RPC method as part of EIP-191.\n *\n * See {recover}.\n */\n function toEthSignedMessageHash(bytes32 hash) internal pure returns (bytes32 message) {\n // 32 is the length in bytes of hash,\n // enforced by the type signature above\n /// @solidity memory-safe-assembly\n assembly {\n mstore(0x00, \"\\x19Ethereum Signed Message:\\n32\")\n mstore(0x1c, hash)\n message := keccak256(0x00, 0x3c)\n }\n }\n\n /**\n * @dev Returns an Ethereum Signed Message, created from `s`. This\n * produces hash corresponding to the one signed with the\n * https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`]\n * JSON-RPC method as part of EIP-191.\n *\n * See {recover}.\n */\n function toEthSignedMessageHash(bytes memory s) internal pure returns (bytes32) {\n return keccak256(abi.encodePacked(\"\\x19Ethereum Signed Message:\\n\", Strings.toString(s.length), s));\n }\n\n /**\n * @dev Returns an Ethereum Signed Typed Data, created from a\n * `domainSeparator` and a `structHash`. This produces hash corresponding\n * to the one signed with the\n * https://eips.ethereum.org/EIPS/eip-712[`eth_signTypedData`]\n * JSON-RPC method as part of EIP-712.\n *\n * See {recover}.\n */\n function toTypedDataHash(bytes32 domainSeparator, bytes32 structHash) internal pure returns (bytes32 data) {\n /// @solidity memory-safe-assembly\n assembly {\n let ptr := mload(0x40)\n mstore(ptr, \"\\x19\\x01\")\n mstore(add(ptr, 0x02), domainSeparator)\n mstore(add(ptr, 0x22), structHash)\n data := keccak256(ptr, 0x42)\n }\n }\n\n /**\n * @dev Returns an Ethereum Signed Data with intended validator, created from a\n * `validator` and `data` according to the version 0 of EIP-191.\n *\n * See {recover}.\n */\n function toDataWithIntendedValidatorHash(address validator, bytes memory data) internal pure returns (bytes32) {\n return keccak256(abi.encodePacked(\"\\x19\\x00\", validator, data));\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/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/inbox/StatementInbox.sol\n\n// ══════════════════════════════ LIBRARY IMPORTS ══════════════════════════════\n\n// ═════════════════════════════ INTERNAL IMPORTS ══════════════════════════════\n\n// ═════════════════════════════ EXTERNAL IMPORTS ══════════════════════════════\n\n/// @notice `StatementInbox` is the entry point for all agent-signed statements. It verifies the\n/// agent signatures, and passes the unsigned statements to the contract to consume it via `acceptX` functions. Is is\n/// also used to verify the agent-signed statements and initiate the agent slashing, should the statement be invalid.\n/// `StatementInbox` is responsible for the following:\n/// - Accepting State and Receipt Reports to initiate a dispute between Guard and Notary.\n/// - Storing all the Guard Reports with the Guard signature leading to a dispute.\n/// - Verifying State/State Reports referencing the local chain and slashing the signer if statement is invalid.\n/// - Verifying Receipt/Receipt Reports referencing the local chain and slashing the signer if statement is invalid.\nabstract contract StatementInbox is MessagingBase, StatementInboxEvents, IStatementInbox {\n using AttestationLib for bytes;\n using ReceiptLib for bytes;\n using StateLib for bytes;\n using SnapshotLib for bytes;\n\n struct StoredReport {\n uint256 sigIndex;\n bytes statementPayload;\n }\n\n // ══════════════════════════════════════════════════ STORAGE ══════════════════════════════════════════════════════\n\n address public agentManager;\n address public origin;\n address public destination;\n\n // TODO: optimize this\n bytes[] internal _storedSignatures;\n StoredReport[] internal _storedReports;\n\n /// @dev gap for upgrade safety\n uint256[45] private __GAP; // solhint-disable-line var-name-mixedcase\n\n // ════════════════════════════════════════════════ INITIALIZER ════════════════════════════════════════════════════\n\n /// @dev Initializes the contract:\n /// - Sets up `msg.sender` as the owner of the contract.\n /// - Sets up `agentManager`, `origin`, and `destination`.\n // solhint-disable-next-line func-name-mixedcase\n function __StatementInbox_init(address agentManager_, address origin_, address destination_)\n internal\n onlyInitializing\n {\n agentManager = agentManager_;\n origin = origin_;\n destination = destination_;\n __Ownable2Step_init();\n }\n\n // ══════════════════════════════════════════ SUBMIT AGENT STATEMENTS ══════════════════════════════════════════════\n\n /// @inheritdoc IStatementInbox\n // solhint-disable-next-line ordering\n function submitStateReportWithSnapshot(\n uint8 stateIndex,\n bytes memory srSignature,\n bytes memory snapPayload,\n bytes memory snapSignature\n ) external returns (bool wasAccepted) {\n // This will revert if payload is not a snapshot\n Snapshot snapshot = snapPayload.castToSnapshot();\n // This will revert if the snapshot signer is not a known Notary\n (AgentStatus memory notaryStatus,) =\n _verifySnapshot({snapshot: snapshot, snapSignature: snapSignature, verifyNotary: true});\n // Notary needs to be Active/Unstaking\n notaryStatus.verifyActiveUnstaking();\n // Check if Notary is active on this chain\n _verifyNotaryDomain(notaryStatus.domain);\n // This will revert if state index is out of range\n State state = snapshot.state(stateIndex);\n // This will revert if the report signer is not an known Guard\n (AgentStatus memory guardStatus,) = _verifyStateReport(state, srSignature);\n // Check that Guard is active\n guardStatus.verifyActive();\n _saveReport(state.unwrap().clone(), srSignature);\n // This will revert if either actor is already in dispute\n IAgentManager(agentManager).openDispute(guardStatus.index, notaryStatus.index);\n return true;\n }\n\n /// @inheritdoc IStatementInbox\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 // This will revert if payload is not a snapshot\n Snapshot snapshot = snapPayload.castToSnapshot();\n // This will revert if state index is out of range\n State state = snapshot.state(stateIndex);\n // This will revert if the report signer is not an known Guard\n (AgentStatus memory guardStatus,) = _verifyStateReport(state, srSignature);\n // Check that Guard is active\n guardStatus.verifyActive();\n // This will revert if payload is not an attestation\n Attestation att = attPayload.castToAttestation();\n // This will revert if signer is not an known Notary\n (AgentStatus memory notaryStatus,) = _verifyAttestation(att, attSignature);\n // Notary needs to be Active/Unstaking\n notaryStatus.verifyActiveUnstaking();\n // Check if Notary is active on this chain\n _verifyNotaryDomain(notaryStatus.domain);\n if (snapshot.calculateRoot() != att.snapRoot()) revert IncorrectSnapshotRoot();\n _saveReport(state.unwrap().clone(), srSignature);\n // This will revert if either actor is already in dispute\n IAgentManager(agentManager).openDispute(guardStatus.index, notaryStatus.index);\n return true;\n }\n\n /// @inheritdoc IStatementInbox\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 // This will revert if payload is not a state\n State state = statePayload.castToState();\n // This will revert if the report signer is not an known Guard\n (AgentStatus memory guardStatus,) = _verifyStateReport(state, srSignature);\n // Check that Guard is active\n guardStatus.verifyActive();\n // This will revert if payload is not an attestation\n Attestation att = attPayload.castToAttestation();\n // This will revert if signer is not a known Notary\n (AgentStatus memory notaryStatus,) = _verifyAttestation(att, attSignature);\n // Notary needs to be Active/Unstaking\n notaryStatus.verifyActiveUnstaking();\n // Check if Notary is active on this chain\n _verifyNotaryDomain(notaryStatus.domain);\n // This will revert if any of these is true:\n // - Attestation root is not equal to Merkle Root derived from State and Snapshot Proof.\n // - Snapshot Proof's first element does not match the State metadata.\n // - Snapshot Proof length exceeds Snapshot tree Height.\n // - State index is out of range.\n _verifySnapshotMerkle(att, stateIndex, state, snapProof);\n _saveReport(statePayload, srSignature);\n // This will revert if either actor is already in dispute\n IAgentManager(agentManager).openDispute(guardStatus.index, notaryStatus.index);\n return true;\n }\n\n // ══════════════════════════════════════════ VERIFY AGENT STATEMENTS ══════════════════════════════════════════════\n\n /// @inheritdoc IStatementInbox\n function verifyReceipt(bytes memory rcptPayload, bytes memory rcptSignature)\n external\n returns (bool isValidReceipt)\n {\n // This will revert if payload is not a receipt\n Receipt rcpt = rcptPayload.castToReceipt();\n // This will revert if the attestation signer is not a known Notary\n (AgentStatus memory status, address notary) = _verifyReceipt(rcpt, rcptSignature);\n // Notary needs to be Active/Unstaking\n status.verifyActiveUnstaking();\n isValidReceipt = IExecutionHub(destination).isValidReceipt(rcptPayload);\n if (!isValidReceipt) {\n emit InvalidReceipt(rcptPayload, rcptSignature);\n IAgentManager(agentManager).slashAgent(status.domain, notary, msg.sender);\n }\n }\n\n /// @inheritdoc IStatementInbox\n function verifyReceiptReport(bytes memory rcptPayload, bytes memory rrSignature)\n external\n returns (bool isValidReport)\n {\n // This will revert if payload is not a receipt\n Receipt rcpt = rcptPayload.castToReceipt();\n // This will revert if the report signer is not a known Guard\n (AgentStatus memory status, address guard) = _verifyReceiptReport(rcpt, rrSignature);\n // Guard needs to be Active/Unstaking\n status.verifyActiveUnstaking();\n // Report is valid IF AND ONLY IF the reported receipt in invalid\n isValidReport = !IExecutionHub(destination).isValidReceipt(rcptPayload);\n if (!isValidReport) {\n emit InvalidReceiptReport(rcptPayload, rrSignature);\n IAgentManager(agentManager).slashAgent(status.domain, guard, msg.sender);\n }\n }\n\n /// @inheritdoc IStatementInbox\n function verifyStateWithAttestation(\n uint8 stateIndex,\n bytes memory snapPayload,\n bytes memory attPayload,\n bytes memory attSignature\n ) external returns (bool isValidState) {\n // This will revert if payload is not an attestation\n Attestation att = attPayload.castToAttestation();\n // This will revert if the attestation signer is not a known Notary\n (AgentStatus memory status, address notary) = _verifyAttestation(att, attSignature);\n // Notary needs to be Active/Unstaking\n status.verifyActiveUnstaking();\n // This will revert if payload is not a snapshot\n Snapshot snapshot = snapPayload.castToSnapshot();\n if (snapshot.calculateRoot() != att.snapRoot()) revert IncorrectSnapshotRoot();\n // This will revert if state does not refer to this chain\n bytes memory statePayload = snapshot.state(stateIndex).unwrap().clone();\n isValidState = IStateHub(origin).isValidState(statePayload);\n if (!isValidState) {\n emit InvalidStateWithAttestation(stateIndex, statePayload, attPayload, attSignature);\n IAgentManager(agentManager).slashAgent(status.domain, notary, msg.sender);\n }\n }\n\n /// @inheritdoc IStatementInbox\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 // This will revert if payload is not an attestation\n Attestation att = attPayload.castToAttestation();\n // This will revert if the attestation signer is not a known Notary\n (AgentStatus memory status, address notary) = _verifyAttestation(att, attSignature);\n // Notary needs to be Active/Unstaking\n status.verifyActiveUnstaking();\n // This will revert if payload is not a state\n State state = statePayload.castToState();\n // This will revert if any of these is true:\n // - Attestation root is not equal to Merkle Root derived from State and Snapshot Proof.\n // - Snapshot Proof's first element does not match the State metadata.\n // - Snapshot Proof length exceeds Snapshot tree Height.\n // - State index is out of range.\n _verifySnapshotMerkle(att, stateIndex, state, snapProof);\n // This will revert if state does not refer to this chain\n isValidState = IStateHub(origin).isValidState(statePayload);\n if (!isValidState) {\n emit InvalidStateWithAttestation(stateIndex, statePayload, attPayload, attSignature);\n IAgentManager(agentManager).slashAgent(status.domain, notary, msg.sender);\n }\n }\n\n /// @inheritdoc IStatementInbox\n function verifyStateWithSnapshot(uint8 stateIndex, bytes memory snapPayload, bytes memory snapSignature)\n external\n returns (bool isValidState)\n {\n // This will revert if payload is not a snapshot\n Snapshot snapshot = snapPayload.castToSnapshot();\n // This will revert if the snapshot signer is not a known Guard/Notary\n (AgentStatus memory status, address agent) =\n _verifySnapshot({snapshot: snapshot, snapSignature: snapSignature, verifyNotary: false});\n // Agent needs to be Active/Unstaking\n status.verifyActiveUnstaking();\n // This will revert if state does not refer to this chain\n isValidState = IStateHub(origin).isValidState(snapshot.state(stateIndex).unwrap().clone());\n if (!isValidState) {\n emit InvalidStateWithSnapshot(stateIndex, snapPayload, snapSignature);\n IAgentManager(agentManager).slashAgent(status.domain, agent, msg.sender);\n }\n }\n\n /// @inheritdoc IStatementInbox\n function verifyStateReport(bytes memory statePayload, bytes memory srSignature)\n external\n returns (bool isValidReport)\n {\n // This will revert if payload is not a state\n State state = statePayload.castToState();\n // This will revert if the report signer is not a known Guard\n (AgentStatus memory status, address guard) = _verifyStateReport(state, srSignature);\n // Guard needs to be Active/Unstaking\n status.verifyActiveUnstaking();\n // Report is valid IF AND ONLY IF the reported state in invalid\n // This will revert if the reported state does not refer to this chain\n isValidReport = !IStateHub(origin).isValidState(statePayload);\n if (!isValidReport) {\n emit InvalidStateReport(statePayload, srSignature);\n IAgentManager(agentManager).slashAgent(status.domain, guard, msg.sender);\n }\n }\n\n // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════\n\n /// @inheritdoc IStatementInbox\n function getReportsAmount() external view returns (uint256) {\n return _storedReports.length;\n }\n\n /// @inheritdoc IStatementInbox\n function getGuardReport(uint256 index)\n external\n view\n returns (bytes memory statementPayload, bytes memory reportSignature)\n {\n if (index \u003e= _storedReports.length) revert IndexOutOfRange();\n StoredReport memory storedReport = _storedReports[index];\n statementPayload = storedReport.statementPayload;\n reportSignature = _storedSignatures[storedReport.sigIndex];\n }\n\n /// @inheritdoc IStatementInbox\n function getStoredSignature(uint256 index) external view returns (bytes memory) {\n return _storedSignatures[index];\n }\n\n // ══════════════════════════════════════════════ INTERNAL LOGIC ═══════════════════════════════════════════════════\n\n /// @dev Saves the statement reported by Guard as invalid and the Guard Report signature.\n function _saveReport(bytes memory statementPayload, bytes memory reportSignature) internal {\n uint256 sigIndex = _saveSignature(reportSignature);\n _storedReports.push(StoredReport(sigIndex, statementPayload));\n }\n\n /// @dev Saves the signature and returns its index.\n function _saveSignature(bytes memory signature) internal returns (uint256 sigIndex) {\n sigIndex = _storedSignatures.length;\n _storedSignatures.push(signature);\n }\n\n // ═══════════════════════════════════════════════ AGENT CHECKS ════════════════════════════════════════════════════\n\n /**\n * @dev Recovers a signer from a hashed message, and a EIP-191 signature for it.\n * Will revert, if the signer is not a known agent.\n * @dev Agent flag could be any of these: Active/Unstaking/Resting/Fraudulent/Slashed\n * Further checks need to be performed in a caller function.\n * @param hashedStatement Hash of the statement that was signed by an Agent\n * @param signature Agent signature for the hashed statement\n * @return status Struct representing agent status:\n * - flag Unknown/Active/Unstaking/Resting/Fraudulent/Slashed\n * - domain Domain where agent is/was active\n * - index Index of agent in the Agent Merkle Tree\n * @return agent Agent that signed the statement\n */\n function _recoverAgent(bytes32 hashedStatement, bytes memory signature)\n internal\n view\n returns (AgentStatus memory status, address agent)\n {\n bytes32 ethSignedMsg = ECDSA.toEthSignedMessageHash(hashedStatement);\n agent = ECDSA.recover(ethSignedMsg, signature);\n status = IAgentManager(agentManager).agentStatus(agent);\n // Discard signature of unknown agents.\n // Further flag checks are supposed to be performed in a caller function.\n status.verifyKnown();\n }\n\n /// @dev Verifies that Notary signature is active on local domain.\n function _verifyNotaryDomain(uint32 notaryDomain) internal view {\n // Notary needs to be from the local domain (if contract is not deployed on Synapse Chain).\n // Or Notary could be from any domain (if contract is deployed on Synapse Chain).\n if (notaryDomain != localDomain \u0026\u0026 localDomain != synapseDomain) revert IncorrectAgentDomain();\n }\n\n // ════════════════════════════════════════ ATTESTATION RELATED CHECKS ═════════════════════════════════════════════\n\n /**\n * @dev Internal function to verify the signed attestation payload.\n * Reverts if any of these is true:\n * - Attestation signer is not a known Notary.\n * @param att Typed memory view over attestation payload\n * @param attSignature Notary signature for the attestation\n * @return status Struct representing agent status, see {_recoverAgent}\n * @return notary Notary that signed the snapshot\n */\n function _verifyAttestation(Attestation att, bytes memory attSignature)\n internal\n view\n returns (AgentStatus memory status, address notary)\n {\n // This will revert if signer is not a known agent\n (status, notary) = _recoverAgent(att.hashValid(), attSignature);\n // Attestation signer needs to be a Notary, not a Guard\n if (status.domain == 0) revert AgentNotNotary();\n }\n\n /**\n * @dev Internal function to verify the signed attestation report payload.\n * Reverts if any of these is true:\n * - Report signer is not a known Guard.\n * @param att Typed memory view over attestation payload that Guard reports as invalid\n * @param arSignature Guard signature for the \"invalid attestation\" report\n * @return status Struct representing guard status, see {_recoverAgent}\n * @return guard Guard that signed the report\n */\n function _verifyAttestationReport(Attestation att, bytes memory arSignature)\n internal\n view\n returns (AgentStatus memory status, address guard)\n {\n // This will revert if signer is not a known agent\n (status, guard) = _recoverAgent(att.hashInvalid(), arSignature);\n // Report signer needs to be a Guard, not a Notary\n if (status.domain != 0) revert AgentNotGuard();\n }\n\n // ══════════════════════════════════════════ RECEIPT RELATED CHECKS ═══════════════════════════════════════════════\n\n /**\n * @dev Internal function to verify the signed receipt payload.\n * Reverts if any of these is true:\n * - Receipt signer is not a known Notary.\n * @param rcpt Typed memory view over receipt payload\n * @param rcptSignature Notary signature for the receipt\n * @return status Struct representing agent status, see {_recoverAgent}\n * @return notary Notary that signed the snapshot\n */\n function _verifyReceipt(Receipt rcpt, bytes memory rcptSignature)\n internal\n view\n returns (AgentStatus memory status, address notary)\n {\n // This will revert if signer is not a known agent\n (status, notary) = _recoverAgent(rcpt.hashValid(), rcptSignature);\n // Receipt signer needs to be a Notary, not a Guard\n if (status.domain == 0) revert AgentNotNotary();\n }\n\n /**\n * @dev Internal function to verify the signed receipt report payload.\n * Reverts if any of these is true:\n * - Report signer is not a known Guard.\n * @param rcpt Typed memory view over receipt payload that Guard reports as invalid\n * @param rrSignature Guard signature for the \"invalid receipt\" report\n * @return status Struct representing guard status, see {_recoverAgent}\n * @return guard Guard that signed the report\n */\n function _verifyReceiptReport(Receipt rcpt, bytes memory rrSignature)\n internal\n view\n returns (AgentStatus memory status, address guard)\n {\n // This will revert if signer is not a known agent\n (status, guard) = _recoverAgent(rcpt.hashInvalid(), rrSignature);\n // Report signer needs to be a Guard, not a Notary\n if (status.domain != 0) revert AgentNotGuard();\n }\n\n // ═══════════════════════════════════════ STATE/SNAPSHOT RELATED CHECKS ═══════════════════════════════════════════\n\n /**\n * @dev Internal function to verify the signed snapshot report payload.\n * Reverts if any of these is true:\n * - Report signer is not a known Guard.\n * @param state Typed memory view over state payload that Guard reports as invalid\n * @param srSignature Guard signature for the report\n * @return status Struct representing guard status, see {_recoverAgent}\n * @return guard Guard that signed the report\n */\n function _verifyStateReport(State state, bytes memory srSignature)\n internal\n view\n returns (AgentStatus memory status, address guard)\n {\n // This will revert if signer is not a known agent\n (status, guard) = _recoverAgent(state.hashInvalid(), srSignature);\n // Report signer needs to be a Guard, not a Notary\n if (status.domain != 0) revert AgentNotGuard();\n }\n\n /**\n * @dev Internal function to verify the signed snapshot payload.\n * Reverts if any of these is true:\n * - Snapshot signer is not a known Agent.\n * - Snapshot signer is not a Notary (if verifyNotary is true).\n * @param snapshot Typed memory view over snapshot payload\n * @param snapSignature Agent signature for the snapshot\n * @param verifyNotary If true, snapshot signer needs to be a Notary, not a Guard\n * @return status Struct representing agent status, see {_recoverAgent}\n * @return agent Agent that signed the snapshot\n */\n function _verifySnapshot(Snapshot snapshot, bytes memory snapSignature, bool verifyNotary)\n internal\n view\n returns (AgentStatus memory status, address agent)\n {\n // This will revert if signer is not a known agent\n (status, agent) = _recoverAgent(snapshot.hashValid(), snapSignature);\n // If requested, snapshot signer needs to be a Notary, not a Guard\n if (verifyNotary \u0026\u0026 status.domain == 0) revert AgentNotNotary();\n }\n\n // ═══════════════════════════════════════════ MERKLE RELATED CHECKS ═══════════════════════════════════════════════\n\n /**\n * @dev Internal function to verify that snapshot roots match.\n * Reverts if any of these is true:\n * - Attestation root is not equal to Merkle Root derived from State and Snapshot Proof.\n * - Snapshot Proof's first element does not match the State metadata.\n * - Snapshot Proof length exceeds Snapshot tree Height.\n * - State index is out of range.\n * @param att Typed memory view over Attestation\n * @param stateIndex Index of state in the snapshot\n * @param state Typed memory view over the provided state payload\n * @param snapProof Raw payload with snapshot data\n */\n function _verifySnapshotMerkle(Attestation att, uint8 stateIndex, State state, bytes32[] memory snapProof)\n internal\n pure\n {\n // Snapshot proof first element should match State metadata (aka \"right sub-leaf\")\n (, bytes32 rightSubLeaf) = state.subLeafs();\n if (snapProof[0] != rightSubLeaf) revert IncorrectSnapshotProof();\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(state.root(), state.origin(), snapProof, stateIndex);\n // Snapshot root should match the attestation root\n if (att.snapRoot() != snapshotRoot) revert IncorrectSnapshotRoot();\n }\n}\n\n// contracts/inbox/Inbox.sol\n\n// ══════════════════════════════ LIBRARY IMPORTS ══════════════════════════════\n\n// ═════════════════════════════ INTERNAL IMPORTS ══════════════════════════════\n\n/// @notice `Inbox` is the child of `StatementInbox` contract, that is used on Synapse Chain.\n/// In addition to the functionality of `StatementInbox`, it also:\n/// - Accepts Guard and Notary Snapshots and passes them to `Summit` contract.\n/// - Accepts Notary-signed Receipts and passes them to `Summit` contract.\n/// - Accepts Receipt Reports to initiate a dispute between Guard and Notary.\n/// - Verifies Attestations and Attestation Reports, and slashes the signer if they are invalid.\ncontract Inbox is StatementInbox, InboxEvents, InterfaceInbox {\n using AttestationLib for bytes;\n using ReceiptLib for bytes;\n using SnapshotLib for bytes;\n\n // Struct to get around stack too deep error. TODO: revisit this\n struct ReceiptInfo {\n AgentStatus rcptNotaryStatus;\n address notary;\n uint32 attNonce;\n AgentStatus attNotaryStatus;\n }\n\n // ══════════════════════════════════════════════════ STORAGE ══════════════════════════════════════════════════════\n\n // The address of the Summit contract.\n address public summit;\n\n // ═════════════════════════════════════════ CONSTRUCTOR \u0026 INITIALIZER ═════════════════════════════════════════════\n\n constructor(uint32 synapseDomain_) MessagingBase(\"0.0.3\", synapseDomain_) {\n if (localDomain != synapseDomain) revert MustBeSynapseDomain();\n }\n\n /// @notice Initializes `Inbox` contract:\n /// - Sets `msg.sender` as the owner of the contract\n /// - Sets `agentManager`, `origin`, `destination` and `summit` addresses\n function initialize(address agentManager_, address origin_, address destination_, address summit_)\n external\n initializer\n {\n __StatementInbox_init(agentManager_, origin_, destination_);\n summit = summit_;\n }\n\n // ══════════════════════════════════════════ SUBMIT AGENT STATEMENTS ══════════════════════════════════════════════\n\n /// @inheritdoc InterfaceInbox\n function submitSnapshot(bytes memory snapPayload, bytes memory snapSignature)\n external\n returns (bytes memory attPayload, bytes32 agentRoot_, uint256[] memory snapGas)\n {\n // This will revert if payload is not a snapshot\n Snapshot snapshot = snapPayload.castToSnapshot();\n // This will revert if the signer is not a known Guard/Notary\n (AgentStatus memory status, address agent) =\n _verifySnapshot({snapshot: snapshot, snapSignature: snapSignature, verifyNotary: false});\n // Check that Agent is active\n status.verifyActive();\n // Store Agent signature for the Snapshot\n uint256 sigIndex = _saveSignature(snapSignature);\n if (status.domain == 0) {\n // Guard that is in Dispute could still submit new snapshots, so we don't check that\n InterfaceSummit(summit).acceptGuardSnapshot({\n guardIndex: status.index,\n sigIndex: sigIndex,\n snapPayload: snapPayload\n });\n } else {\n // Get current agentRoot from AgentManager\n agentRoot_ = IAgentManager(agentManager).agentRoot();\n // This will revert if Notary is in Dispute\n attPayload = InterfaceSummit(summit).acceptNotarySnapshot({\n notaryIndex: status.index,\n sigIndex: sigIndex,\n agentRoot: agentRoot_,\n snapPayload: snapPayload\n });\n ChainGas[] memory snapGas_ = snapshot.snapGas();\n // Pass created attestation to Destination to enable executing messages coming to Synapse Chain\n InterfaceDestination(destination).acceptAttestation(\n status.index, type(uint256).max, attPayload, agentRoot_, snapGas_\n );\n // Use assembly to cast ChainGas[] to uint256[] without copying. Highest bits are left zeroed.\n // solhint-disable-next-line no-inline-assembly\n assembly {\n snapGas := snapGas_\n }\n }\n emit SnapshotAccepted(status.domain, agent, snapPayload, snapSignature);\n }\n\n /// @inheritdoc InterfaceInbox\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 // Struct to get around stack too deep error.\n ReceiptInfo memory info;\n // This will revert if payload is not a receipt\n Receipt rcpt = rcptPayload.castToReceipt();\n // This will revert if the receipt signer is not a known Notary\n (info.rcptNotaryStatus, info.notary) = _verifyReceipt(rcpt, rcptSignature);\n // Receipt Notary needs to be Active\n info.rcptNotaryStatus.verifyActive();\n info.attNonce = IExecutionHub(destination).getAttestationNonce(rcpt.snapshotRoot());\n if (info.attNonce == 0) revert IncorrectSnapshotRoot();\n // Attestation Notary domain needs to match the destination domain\n info.attNotaryStatus = IAgentManager(agentManager).agentStatus(rcpt.attNotary());\n if (info.attNotaryStatus.domain != rcpt.destination()) revert IncorrectAgentDomain();\n // Check that the correct tip values for the message were provided\n _verifyReceiptTips(rcpt.messageHash(), paddedTips, headerHash, bodyHash);\n // Store Notary signature for the Receipt\n uint256 sigIndex = _saveSignature(rcptSignature);\n // This will revert if Receipt Notary is in Dispute\n wasAccepted = InterfaceSummit(summit).acceptReceipt({\n rcptNotaryIndex: info.rcptNotaryStatus.index,\n attNotaryIndex: info.attNotaryStatus.index,\n sigIndex: sigIndex,\n attNonce: info.attNonce,\n paddedTips: paddedTips,\n rcptPayload: rcptPayload\n });\n if (wasAccepted) {\n emit ReceiptAccepted(info.rcptNotaryStatus.domain, info.notary, rcptPayload, rcptSignature);\n }\n }\n\n /// @inheritdoc InterfaceInbox\n function submitReceiptReport(bytes memory rcptPayload, bytes memory rcptSignature, bytes memory rrSignature)\n external\n returns (bool wasAccepted)\n {\n // This will revert if payload is not a receipt\n Receipt rcpt = rcptPayload.castToReceipt();\n // This will revert if the receipt signer is not a known Guard\n (AgentStatus memory guardStatus,) = _verifyReceiptReport(rcpt, rrSignature);\n // Guard needs to be Active\n guardStatus.verifyActive();\n // This will revert if report signer is not a known Notary\n (AgentStatus memory notaryStatus,) = _verifyReceipt(rcpt, rcptSignature);\n // Notary needs to be Active/Unstaking\n notaryStatus.verifyActiveUnstaking();\n _saveReport(rcptPayload, rrSignature);\n // This will revert if either actor is already in dispute\n IAgentManager(agentManager).openDispute(guardStatus.index, notaryStatus.index);\n return true;\n }\n\n /// @inheritdoc InterfaceInbox\n function passReceipt(uint32 attNotaryIndex, uint32 attNonce, uint256 paddedTips, bytes memory rcptPayload)\n external\n returns (bool wasAccepted)\n {\n // Only Destination can pass receipts\n if (msg.sender != destination) revert CallerNotDestination();\n return InterfaceSummit(summit).acceptReceipt({\n rcptNotaryIndex: attNotaryIndex,\n attNotaryIndex: attNotaryIndex,\n sigIndex: type(uint256).max,\n attNonce: attNonce,\n paddedTips: paddedTips,\n rcptPayload: rcptPayload\n });\n }\n\n // ══════════════════════════════════════════ VERIFY AGENT STATEMENTS ══════════════════════════════════════════════\n\n /// @inheritdoc InterfaceInbox\n function verifyAttestation(bytes memory attPayload, bytes memory attSignature)\n external\n returns (bool isValidAttestation)\n {\n // This will revert if payload is not an attestation\n Attestation att = attPayload.castToAttestation();\n // This will revert if the attestation signer is not a known Notary\n (AgentStatus memory status, address notary) = _verifyAttestation(att, attSignature);\n // Notary needs to be Active/Unstaking\n status.verifyActiveUnstaking();\n isValidAttestation = ISnapshotHub(summit).isValidAttestation(attPayload);\n if (!isValidAttestation) {\n emit InvalidAttestation(attPayload, attSignature);\n IAgentManager(agentManager).slashAgent(status.domain, notary, msg.sender);\n }\n }\n\n /// @inheritdoc InterfaceInbox\n function verifyAttestationReport(bytes memory attPayload, bytes memory arSignature)\n external\n returns (bool isValidReport)\n {\n // This will revert if payload is not an attestation\n Attestation att = attPayload.castToAttestation();\n // This will revert if the report signer is not a known Guard\n (AgentStatus memory status, address guard) = _verifyAttestationReport(att, arSignature);\n // Guard needs to be Active/Unstaking\n status.verifyActiveUnstaking();\n // Report is valid IF AND ONLY IF the reported attestation in invalid\n isValidReport = !ISnapshotHub(summit).isValidAttestation(attPayload);\n if (!isValidReport) {\n emit InvalidAttestationReport(attPayload, arSignature);\n IAgentManager(agentManager).slashAgent(status.domain, guard, msg.sender);\n }\n }\n\n // ══════════════════════════════════════════════ INTERNAL VIEWS ═══════════════════════════════════════════════════\n\n /// @dev Verifies that tips proof matches the message hash.\n function _verifyReceiptTips(bytes32 msgHash, uint256 paddedTips, bytes32 headerHash, bytes32 bodyHash)\n internal\n pure\n {\n Tips tips = TipsLib.wrapPadded(paddedTips);\n // full message leaf is (header, baseMessage), while base message leaf is (tips, remainingBody).\n if (MerkleMath.getParent(headerHash, MerkleMath.getParent(tips.leaf(), bodyHash)) != msgHash) {\n revert IncorrectTipsProof();\n }\n }\n}\n","language":"Solidity","languageVersion":"0.8.17","compilerVersion":"0.8.17","compilerOptions":"--combined-json bin,bin-runtime,srcmap,srcmap-runtime,abi,userdoc,devdoc,metadata,hashes --optimize --optimize-runs 10000 --allow-paths ., ./, ../","srcMap":"","srcMapRuntime":"","abiDefinition":[{"inputs":[{"internalType":"uint32","name":"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/Inbox.sol\":\"InterfaceDestination\"},\"evmVersion\":\"london\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\"},\"optimizer\":{\"enabled\":true,\"runs\":10000},\"remappings\":[]},\"sources\":{\"solidity/Inbox.sol\":{\"keccak256\":\"0x9b516081a036814c0169e20e484d4a5499066b7a6f48fada952b5e844a1ca3e5\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://32bde393b3f24ef4307d9626d4143f337b3c0bd34e17bb969fd5a15221d96987\",\"dweb:/ipfs/QmTkt2XZRtgsbSpmsVQUM3c4ebETQoDVYbmEV9yheBghnr\"]}},\"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/Inbox.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/InboxEvents.sol\n\nabstract contract InboxEvents {\n /**\n * @notice Emitted when a snapshot is accepted by the Summit contract.\n * @param domain Domain where the signed Agent is active (ZERO for Guards)\n * @param agent Agent who signed the snapshot\n * @param snapPayload Raw payload with snapshot data\n * @param snapSignature Agent signature for the snapshot\n */\n event SnapshotAccepted(uint32 indexed domain, address indexed agent, bytes snapPayload, bytes snapSignature);\n\n /**\n * @notice Emitted when a snapshot is accepted by the Summit contract.\n * @param domain Domain where the signed Notary is active\n * @param notary Notary who signed the attestation\n * @param rcptPayload Raw payload with receipt data\n * @param rcptSignature Notary signature for the receipt\n */\n event ReceiptAccepted(uint32 domain, address notary, bytes rcptPayload, bytes rcptSignature);\n\n /**\n * @notice Emitted when a proof of invalid attestation is submitted.\n * @param attPayload Raw payload with Attestation data\n * @param attSignature Notary signature for the attestation\n */\n event InvalidAttestation(bytes attPayload, bytes attSignature);\n\n /**\n * @notice Emitted when a proof of invalid attestation report is submitted.\n * @param arPayload Raw payload with report data\n * @param arSignature Guard signature for the report\n */\n event InvalidAttestationReport(bytes arPayload, bytes arSignature);\n}\n\n// contracts/events/StatementInboxEvents.sol\n\nabstract contract StatementInboxEvents {\n // ════════════════════════════════════════════ STATEMENT ACCEPTED ═════════════════════════════════════════════════\n\n /**\n * @notice Emitted when a snapshot is accepted by the Destination contract.\n * @param domain Domain where the signed Notary is active\n * @param notary Notary who signed the attestation\n * @param attPayload Raw payload with attestation data\n * @param attSignature Notary signature for the attestation\n */\n event AttestationAccepted(uint32 domain, address notary, bytes attPayload, bytes attSignature);\n\n // ═════════════════════════════════════════ INVALID STATEMENT PROVED ══════════════════════════════════════════════\n\n /**\n * @notice Emitted when a proof of invalid receipt statement is submitted.\n * @param rcptPayload Raw payload with the receipt statement\n * @param rcptSignature Notary signature for the receipt statement\n */\n event InvalidReceipt(bytes rcptPayload, bytes rcptSignature);\n\n /**\n * @notice Emitted when a proof of invalid receipt report is submitted.\n * @param rrPayload Raw payload with report data\n * @param rrSignature Guard signature for the report\n */\n event InvalidReceiptReport(bytes rrPayload, bytes rrSignature);\n\n /**\n * @notice Emitted when a proof of invalid state in the signed attestation is submitted.\n * @param stateIndex Index of invalid state in the snapshot\n * @param statePayload Raw payload with state data\n * @param attPayload Raw payload with Attestation data for snapshot\n * @param attSignature Notary signature for the attestation\n */\n event InvalidStateWithAttestation(uint8 stateIndex, bytes statePayload, bytes attPayload, bytes attSignature);\n\n /**\n * @notice Emitted when a proof of invalid state in the signed snapshot is submitted.\n * @param stateIndex Index of invalid state in the snapshot\n * @param snapPayload Raw payload with snapshot data\n * @param snapSignature Agent signature for the snapshot\n */\n event InvalidStateWithSnapshot(uint8 stateIndex, bytes snapPayload, bytes snapSignature);\n\n /**\n * @notice Emitted when a proof of invalid state report is submitted.\n * @param srPayload Raw payload with report data\n * @param srSignature Guard signature for the report\n */\n event InvalidStateReport(bytes srPayload, bytes srSignature);\n}\n\n// contracts/interfaces/ISnapshotHub.sol\n\ninterface ISnapshotHub {\n /**\n * @notice Check that a given attestation is valid: matches the historical attestation\n * derived from an accepted Notary snapshot.\n * @dev Will revert if any of these is true:\n * - Attestation payload is not properly formatted.\n * @param attPayload Raw payload with attestation data\n * @return isValid Whether the provided attestation is valid\n */\n function isValidAttestation(bytes memory attPayload) external view returns (bool isValid);\n\n /**\n * @notice Returns saved attestation with the given nonce.\n * @dev Reverts if attestation with given nonce hasn't been created yet.\n * @param attNonce Nonce for the attestation\n * @return attPayload Raw payload with formatted Attestation data\n * @return agentRoot Agent root hash used for the attestation\n * @return snapGas Snapshot gas data used for the attestation\n */\n function getAttestation(uint32 attNonce)\n external\n view\n returns (bytes memory attPayload, bytes32 agentRoot, uint256[] memory snapGas);\n\n /**\n * @notice Returns the state with the highest known nonce submitted by a given Agent.\n * @param origin Domain of origin chain\n * @param agent Agent address\n * @return statePayload Raw payload with agent's latest state for origin\n */\n function getLatestAgentState(uint32 origin, address agent) external view returns (bytes memory statePayload);\n\n /**\n * @notice Returns latest saved attestation for a Notary.\n * @param notary Notary address\n * @return attPayload Raw payload with formatted Attestation data\n * @return agentRoot Agent root hash used for the attestation\n * @return snapGas Snapshot gas data used for the attestation\n */\n function getLatestNotaryAttestation(address notary)\n external\n view\n returns (bytes memory attPayload, bytes32 agentRoot, uint256[] memory snapGas);\n\n /**\n * @notice Returns Guard snapshot from the list of all accepted Guard snapshots.\n * @dev Reverts if snapshot with given index hasn't been accepted yet.\n * @param index Snapshot index in the list of all Guard snapshots\n * @return snapPayload Raw payload with Guard snapshot\n * @return snapSignature Raw payload with Guard signature for snapshot\n */\n function getGuardSnapshot(uint256 index)\n external\n view\n returns (bytes memory snapPayload, bytes memory snapSignature);\n\n /**\n * @notice Returns Notary snapshot from the list of all accepted Guard snapshots.\n * @dev Reverts if snapshot with given index hasn't been accepted yet.\n * @param index Snapshot index in the list of all Notary snapshots\n * @return snapPayload Raw payload with Notary snapshot\n * @return snapSignature Raw payload with Notary signature for snapshot\n */\n function getNotarySnapshot(uint256 index)\n external\n view\n returns (bytes memory snapPayload, bytes memory snapSignature);\n\n /**\n * @notice Returns Notary snapshot that was used for creating a given attestation.\n * @dev Reverts if any of these is true:\n * - Attestation payload is not properly formatted.\n * - Attestation is invalid (doesn't have a matching Notary snapshot).\n * @param attPayload Raw payload with attestation data\n * @return snapPayload Raw payload with Notary snapshot\n * @return snapSignature Raw payload with Notary signature for snapshot\n */\n function getNotarySnapshot(bytes memory attPayload)\n external\n view\n returns (bytes memory snapPayload, bytes memory snapSignature);\n\n /**\n * @notice Returns proof of inclusion of (root, origin) fields of a given snapshot's state\n * into the Snapshot Merkle Tree for a given attestation.\n * @dev Reverts if any of these is true:\n * - Attestation with given nonce hasn't been created yet.\n * - State index is out of range of snapshot list.\n * @param attNonce Nonce for the attestation\n * @param stateIndex Index of state in the attestation's snapshot\n * @return snapProof The snapshot proof\n */\n function getSnapshotProof(uint32 attNonce, uint8 stateIndex) external view returns (bytes32[] memory snapProof);\n}\n\n// contracts/interfaces/IStateHub.sol\n\ninterface IStateHub {\n /**\n * @notice Check that a given state is valid: matches the historical state of Origin contract.\n * Note: any Agent including an invalid state in their snapshot will be slashed\n * upon providing the snapshot and agent signature for it to Origin contract.\n * @dev Will revert if any of these is true:\n * - State payload is not properly formatted.\n * @param statePayload Raw payload with state data\n * @return isValid Whether the provided state is valid\n */\n function isValidState(bytes memory statePayload) external view returns (bool isValid);\n\n /**\n * @notice Returns the amount of saved states so far.\n * @dev This includes the initial state of \"empty Origin Merkle Tree\".\n */\n function statesAmount() external view returns (uint256);\n\n /**\n * @notice Suggest the data (state after latest sent message) to sign for an Agent.\n * Note: signing the suggested state data will will never lead to slashing of the actor,\n * assuming they have confirmed that the block, which number is included in the data,\n * is not subject to reorganization (which is different for every observed chain).\n * @return statePayload Raw payload with the latest state data\n */\n function suggestLatestState() external view returns (bytes memory statePayload);\n\n /**\n * @notice Given the historical nonce, suggest the state data to sign for an Agent.\n * Note: signing the suggested state data will will never lead to slashing of the actor,\n * assuming they have confirmed that the block, which number is included in the data,\n * is not subject to reorganization (which is different for every observed chain).\n * @param nonce Historical nonce to form a state\n * @return statePayload Raw payload with historical state data\n */\n function suggestState(uint32 nonce) external view returns (bytes memory statePayload);\n}\n\n// contracts/interfaces/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/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// node_modules/@openzeppelin/contracts/utils/math/Math.sol\n\n// OpenZeppelin Contracts (last updated v4.9.0) (utils/math/Math.sol)\n\n/**\n * @dev Standard math utilities missing in the Solidity language.\n */\nlibrary Math {\n enum Rounding {\n Down, // Toward negative infinity\n Up, // Toward infinity\n Zero // Toward zero\n }\n\n /**\n * @dev Returns the largest of two numbers.\n */\n function max(uint256 a, uint256 b) internal pure returns (uint256) {\n return a \u003e b ? a : b;\n }\n\n /**\n * @dev Returns the smallest of two numbers.\n */\n function min(uint256 a, uint256 b) internal pure returns (uint256) {\n return a \u003c b ? a : b;\n }\n\n /**\n * @dev Returns the average of two numbers. The result is rounded towards\n * zero.\n */\n function average(uint256 a, uint256 b) internal pure returns (uint256) {\n // (a + b) / 2 can overflow.\n return (a \u0026 b) + (a ^ b) / 2;\n }\n\n /**\n * @dev Returns the ceiling of the division of two numbers.\n *\n * This differs from standard division with `/` in that it rounds up instead\n * of rounding down.\n */\n function ceilDiv(uint256 a, uint256 b) internal pure returns (uint256) {\n // (a + b - 1) / b can overflow on addition, so we distribute.\n return a == 0 ? 0 : (a - 1) / b + 1;\n }\n\n /**\n * @notice Calculates floor(x * y / denominator) with full precision. Throws if result overflows a uint256 or denominator == 0\n * @dev Original credit to Remco Bloemen under MIT license (https://xn--2-umb.com/21/muldiv)\n * with further edits by Uniswap Labs also under MIT license.\n */\n function mulDiv(uint256 x, uint256 y, uint256 denominator) internal pure returns (uint256 result) {\n unchecked {\n // 512-bit multiply [prod1 prod0] = x * y. Compute the product mod 2^256 and mod 2^256 - 1, then use\n // use the Chinese Remainder Theorem to reconstruct the 512 bit result. The result is stored in two 256\n // variables such that product = prod1 * 2^256 + prod0.\n uint256 prod0; // Least significant 256 bits of the product\n uint256 prod1; // Most significant 256 bits of the product\n assembly {\n let mm := mulmod(x, y, not(0))\n prod0 := mul(x, y)\n prod1 := sub(sub(mm, prod0), lt(mm, prod0))\n }\n\n // Handle non-overflow cases, 256 by 256 division.\n if (prod1 == 0) {\n // Solidity will revert if denominator == 0, unlike the div opcode on its own.\n // The surrounding unchecked block does not change this fact.\n // See https://docs.soliditylang.org/en/latest/control-structures.html#checked-or-unchecked-arithmetic.\n return prod0 / denominator;\n }\n\n // Make sure the result is less than 2^256. Also prevents denominator == 0.\n require(denominator \u003e prod1, \"Math: mulDiv overflow\");\n\n ///////////////////////////////////////////////\n // 512 by 256 division.\n ///////////////////////////////////////////////\n\n // Make division exact by subtracting the remainder from [prod1 prod0].\n uint256 remainder;\n assembly {\n // Compute remainder using mulmod.\n remainder := mulmod(x, y, denominator)\n\n // Subtract 256 bit number from 512 bit number.\n prod1 := sub(prod1, gt(remainder, prod0))\n prod0 := sub(prod0, remainder)\n }\n\n // Factor powers of two out of denominator and compute largest power of two divisor of denominator. Always \u003e= 1.\n // See https://cs.stackexchange.com/q/138556/92363.\n\n // Does not overflow because the denominator cannot be zero at this stage in the function.\n uint256 twos = denominator \u0026 (~denominator + 1);\n assembly {\n // Divide denominator by twos.\n denominator := div(denominator, twos)\n\n // Divide [prod1 prod0] by twos.\n prod0 := div(prod0, twos)\n\n // Flip twos such that it is 2^256 / twos. If twos is zero, then it becomes one.\n twos := add(div(sub(0, twos), twos), 1)\n }\n\n // Shift in bits from prod1 into prod0.\n prod0 |= prod1 * twos;\n\n // Invert denominator mod 2^256. Now that denominator is an odd number, it has an inverse modulo 2^256 such\n // that denominator * inv = 1 mod 2^256. Compute the inverse by starting with a seed that is correct for\n // four bits. That is, denominator * inv = 1 mod 2^4.\n uint256 inverse = (3 * denominator) ^ 2;\n\n // Use the Newton-Raphson iteration to improve the precision. Thanks to Hensel's lifting lemma, this also works\n // in modular arithmetic, doubling the correct bits in each step.\n inverse *= 2 - denominator * inverse; // inverse mod 2^8\n inverse *= 2 - denominator * inverse; // inverse mod 2^16\n inverse *= 2 - denominator * inverse; // inverse mod 2^32\n inverse *= 2 - denominator * inverse; // inverse mod 2^64\n inverse *= 2 - denominator * inverse; // inverse mod 2^128\n inverse *= 2 - denominator * inverse; // inverse mod 2^256\n\n // Because the division is now exact we can divide by multiplying with the modular inverse of denominator.\n // This will give us the correct result modulo 2^256. Since the preconditions guarantee that the outcome is\n // less than 2^256, this is the final result. We don't need to compute the high bits of the result and prod1\n // is no longer required.\n result = prod0 * inverse;\n return result;\n }\n }\n\n /**\n * @notice Calculates x * y / denominator with full precision, following the selected rounding direction.\n */\n function mulDiv(uint256 x, uint256 y, uint256 denominator, Rounding rounding) internal pure returns (uint256) {\n uint256 result = mulDiv(x, y, denominator);\n if (rounding == Rounding.Up \u0026\u0026 mulmod(x, y, denominator) \u003e 0) {\n result += 1;\n }\n return result;\n }\n\n /**\n * @dev Returns the square root of a number. If the number is not a perfect square, the value is rounded down.\n *\n * Inspired by Henry S. Warren, Jr.'s \"Hacker's Delight\" (Chapter 11).\n */\n function sqrt(uint256 a) internal pure returns (uint256) {\n if (a == 0) {\n return 0;\n }\n\n // For our first guess, we get the biggest power of 2 which is smaller than the square root of the target.\n //\n // We know that the \"msb\" (most significant bit) of our target number `a` is a power of 2 such that we have\n // `msb(a) \u003c= a \u003c 2*msb(a)`. This value can be written `msb(a)=2**k` with `k=log2(a)`.\n //\n // This can be rewritten `2**log2(a) \u003c= a \u003c 2**(log2(a) + 1)`\n // → `sqrt(2**k) \u003c= sqrt(a) \u003c sqrt(2**(k+1))`\n // → `2**(k/2) \u003c= sqrt(a) \u003c 2**((k+1)/2) \u003c= 2**(k/2 + 1)`\n //\n // Consequently, `2**(log2(a) / 2)` is a good first approximation of `sqrt(a)` with at least 1 correct bit.\n uint256 result = 1 \u003c\u003c (log2(a) \u003e\u003e 1);\n\n // At this point `result` is an estimation with one bit of precision. We know the true value is a uint128,\n // since it is the square root of a uint256. Newton's method converges quadratically (precision doubles at\n // every iteration). We thus need at most 7 iteration to turn our partial result with one bit of precision\n // into the expected uint128 result.\n unchecked {\n result = (result + a / result) \u003e\u003e 1;\n result = (result + a / result) \u003e\u003e 1;\n result = (result + a / result) \u003e\u003e 1;\n result = (result + a / result) \u003e\u003e 1;\n result = (result + a / result) \u003e\u003e 1;\n result = (result + a / result) \u003e\u003e 1;\n result = (result + a / result) \u003e\u003e 1;\n return min(result, a / result);\n }\n }\n\n /**\n * @notice Calculates sqrt(a), following the selected rounding direction.\n */\n function sqrt(uint256 a, Rounding rounding) internal pure returns (uint256) {\n unchecked {\n uint256 result = sqrt(a);\n return result + (rounding == Rounding.Up \u0026\u0026 result * result \u003c a ? 1 : 0);\n }\n }\n\n /**\n * @dev Return the log in base 2, rounded down, of a positive value.\n * Returns 0 if given 0.\n */\n function log2(uint256 value) internal pure returns (uint256) {\n uint256 result = 0;\n unchecked {\n if (value \u003e\u003e 128 \u003e 0) {\n value \u003e\u003e= 128;\n result += 128;\n }\n if (value \u003e\u003e 64 \u003e 0) {\n value \u003e\u003e= 64;\n result += 64;\n }\n if (value \u003e\u003e 32 \u003e 0) {\n value \u003e\u003e= 32;\n result += 32;\n }\n if (value \u003e\u003e 16 \u003e 0) {\n value \u003e\u003e= 16;\n result += 16;\n }\n if (value \u003e\u003e 8 \u003e 0) {\n value \u003e\u003e= 8;\n result += 8;\n }\n if (value \u003e\u003e 4 \u003e 0) {\n value \u003e\u003e= 4;\n result += 4;\n }\n if (value \u003e\u003e 2 \u003e 0) {\n value \u003e\u003e= 2;\n result += 2;\n }\n if (value \u003e\u003e 1 \u003e 0) {\n result += 1;\n }\n }\n return result;\n }\n\n /**\n * @dev Return the log in base 2, following the selected rounding direction, of a positive value.\n * Returns 0 if given 0.\n */\n function log2(uint256 value, Rounding rounding) internal pure returns (uint256) {\n unchecked {\n uint256 result = log2(value);\n return result + (rounding == Rounding.Up \u0026\u0026 1 \u003c\u003c result \u003c value ? 1 : 0);\n }\n }\n\n /**\n * @dev Return the log in base 10, rounded down, of a positive value.\n * Returns 0 if given 0.\n */\n function log10(uint256 value) internal pure returns (uint256) {\n uint256 result = 0;\n unchecked {\n if (value \u003e= 10 ** 64) {\n value /= 10 ** 64;\n result += 64;\n }\n if (value \u003e= 10 ** 32) {\n value /= 10 ** 32;\n result += 32;\n }\n if (value \u003e= 10 ** 16) {\n value /= 10 ** 16;\n result += 16;\n }\n if (value \u003e= 10 ** 8) {\n value /= 10 ** 8;\n result += 8;\n }\n if (value \u003e= 10 ** 4) {\n value /= 10 ** 4;\n result += 4;\n }\n if (value \u003e= 10 ** 2) {\n value /= 10 ** 2;\n result += 2;\n }\n if (value \u003e= 10 ** 1) {\n result += 1;\n }\n }\n return result;\n }\n\n /**\n * @dev Return the log in base 10, following the selected rounding direction, of a positive value.\n * Returns 0 if given 0.\n */\n function log10(uint256 value, Rounding rounding) internal pure returns (uint256) {\n unchecked {\n uint256 result = log10(value);\n return result + (rounding == Rounding.Up \u0026\u0026 10 ** result \u003c value ? 1 : 0);\n }\n }\n\n /**\n * @dev Return the log in base 256, rounded down, of a positive value.\n * Returns 0 if given 0.\n *\n * Adding one to the result gives the number of pairs of hex symbols needed to represent `value` as a hex string.\n */\n function log256(uint256 value) internal pure returns (uint256) {\n uint256 result = 0;\n unchecked {\n if (value \u003e\u003e 128 \u003e 0) {\n value \u003e\u003e= 128;\n result += 16;\n }\n if (value \u003e\u003e 64 \u003e 0) {\n value \u003e\u003e= 64;\n result += 8;\n }\n if (value \u003e\u003e 32 \u003e 0) {\n value \u003e\u003e= 32;\n result += 4;\n }\n if (value \u003e\u003e 16 \u003e 0) {\n value \u003e\u003e= 16;\n result += 2;\n }\n if (value \u003e\u003e 8 \u003e 0) {\n result += 1;\n }\n }\n return result;\n }\n\n /**\n * @dev Return the log in base 256, following the selected rounding direction, of a positive value.\n * Returns 0 if given 0.\n */\n function log256(uint256 value, Rounding rounding) internal pure returns (uint256) {\n unchecked {\n uint256 result = log256(value);\n return result + (rounding == Rounding.Up \u0026\u0026 1 \u003c\u003c (result \u003c\u003c 3) \u003c value ? 1 : 0);\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/utils/math/SignedMath.sol\n\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/math/SignedMath.sol)\n\n/**\n * @dev Standard signed math utilities missing in the Solidity language.\n */\nlibrary SignedMath {\n /**\n * @dev Returns the largest of two signed numbers.\n */\n function max(int256 a, int256 b) internal pure returns (int256) {\n return a \u003e b ? a : b;\n }\n\n /**\n * @dev Returns the smallest of two signed numbers.\n */\n function min(int256 a, int256 b) internal pure returns (int256) {\n return a \u003c b ? a : b;\n }\n\n /**\n * @dev Returns the average of two signed numbers without overflow.\n * The result is rounded towards zero.\n */\n function average(int256 a, int256 b) internal pure returns (int256) {\n // Formula from the book \"Hacker's Delight\"\n int256 x = (a \u0026 b) + ((a ^ b) \u003e\u003e 1);\n return x + (int256(uint256(x) \u003e\u003e 255) \u0026 (a ^ b));\n }\n\n /**\n * @dev Returns the absolute unsigned value of a signed value.\n */\n function abs(int256 n) internal pure returns (uint256) {\n unchecked {\n // must be unchecked in order to support `n = type(int256).min`\n return uint256(n \u003e= 0 ? n : -n);\n }\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// 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/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/InterfaceSummit.sol\n\ninterface InterfaceSummit {\n // ══════════════════════════════════════════ ACCEPT AGENT STATEMENTS ══════════════════════════════════════════════\n\n /**\n * @notice Accepts a receipt, which local `AgentManager` verified to have been signed by an active Notary.\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 * - Notary who signed the receipt is referenced as the \"Receipt Notary\".\n * - Notary who signed the attestation on destination chain is referenced as the \"Attestation Notary\".\n * \u003e Will revert if any of these is true:\n * \u003e - Called by anyone other than local `AgentManager`.\n * \u003e - Receipt body payload is not properly formatted.\n * \u003e - Receipt signer is in Dispute.\n * \u003e - Receipt's snapshot root is unknown.\n * @param rcptNotaryIndex Index of Receipt Notary in Agent Merkle Tree\n * @param attNotaryIndex Index of Attestation Notary in Agent Merkle Tree\n * @param sigIndex Index of stored Notary signature\n * @param attNonce Nonce of the attestation used for proving the executed message\n * @param paddedTips Padded encoded paid tips information\n * @param rcptPayload Raw payload with message execution receipt\n * @return wasAccepted Whether the receipt was accepted\n */\n function acceptReceipt(\n uint32 rcptNotaryIndex,\n uint32 attNotaryIndex,\n uint256 sigIndex,\n uint32 attNonce,\n uint256 paddedTips,\n bytes memory rcptPayload\n ) external returns (bool wasAccepted);\n\n /**\n * @notice Accepts a snapshot, which local `AgentManager` verified to have been signed by an active Guard.\n * \u003e Snapshot is a list of states for a set of Origin contracts residing on any of the chains.\n * All the states in the Guard-signed snapshot become available for Notary signing.\n * \u003e Will revert if any of these is true:\n * \u003e - Called by anyone other than local `AgentManager`.\n * \u003e - Snapshot payload is not properly formatted.\n * \u003e - Snapshot contains a state older then the Guard has previously submitted.\n * @param guardIndex Index of Guard in Agent Merkle Tree\n * @param sigIndex Index of stored Agent signature\n * @param snapPayload Raw payload with snapshot data\n */\n function acceptGuardSnapshot(uint32 guardIndex, uint256 sigIndex, bytes memory snapPayload) external;\n\n /**\n * @notice Accepts a snapshot, which local `AgentManager` verified to have been signed by an active Notary.\n * \u003e Snapshot is a list of states for a set of Origin contracts residing on any of the chains.\n * Snapshot Merkle Root is calculated and saved for valid snapshots, i.e.\n * snapshots which are only using states previously submitted by any of the Guards.\n * - Notary could use states singed by the same of different Guards 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 - Called by anyone other than local `AgentManager`.\n * \u003e - Snapshot payload is not properly formatted.\n * \u003e - Snapshot contains a state older then the Notary has previously submitted.\n * \u003e - Snapshot contains a state that no Guard has previously submitted.\n * @param notaryIndex Index of Notary in Agent Merkle Tree\n * @param sigIndex Index of stored Agent signature\n * @param agentRoot Current root of the Agent Merkle Tree\n * @param snapPayload Raw payload with snapshot data\n * @return attPayload Raw payload with data for attestation derived from Notary snapshot.\n */\n function acceptNotarySnapshot(uint32 notaryIndex, uint256 sigIndex, bytes32 agentRoot, bytes memory snapPayload)\n external\n returns (bytes memory attPayload);\n\n // ════════════════════════════════════════════════ TIPS LOGIC ═════════════════════════════════════════════════════\n\n /**\n * @notice Distributes tips using the first Receipt from the \"receipt quarantine queue\".\n * Possible scenarios:\n * - Receipt queue is empty =\u003e does nothing\n * - Receipt optimistic period is not over =\u003e does nothing\n * - Either of Notaries present in Receipt was slashed =\u003e receipt is deleted from the queue\n * - Either of Notaries present in Receipt in Dispute =\u003e receipt is moved to the end of queue\n * - None of the above =\u003e receipt tips are distributed\n * @dev Returned value makes it possible to do the following: `while (distributeTips()) {}`\n * @return queuePopped Whether the first element was popped from the queue\n */\n function distributeTips() external returns (bool queuePopped);\n\n /**\n * @notice Withdraws locked base message tips from requested domain Origin to the recipient.\n * This is done by a call to a local Origin contract, or by a manager message to the remote chain.\n * @dev This will revert, if the pending balance of origin tips (earned-claimed) is lower than requested.\n * @param origin Domain of chain to withdraw tips on\n * @param amount Amount of tips to withdraw\n */\n function withdrawTips(uint32 origin, uint256 amount) external;\n\n // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════\n\n /**\n * @notice Returns earned and claimed tips for the actor.\n * Note: Tips for address(0) belong to the Treasury.\n * @param actor Address of the actor\n * @param origin Domain where the tips were initially paid\n * @return earned Total amount of origin tips the actor has earned so far\n * @return claimed Total amount of origin tips the actor has claimed so far\n */\n function actorTips(address actor, uint32 origin) external view returns (uint128 earned, uint128 claimed);\n\n /**\n * @notice Returns the amount of receipts in the \"Receipt Quarantine Queue\".\n */\n function receiptQueueLength() external view returns (uint256);\n\n /**\n * @notice Returns the state with the highest known nonce\n * submitted by any of the currently active Guards.\n * @param origin Domain of origin chain\n * @return statePayload Raw payload with latest active Guard state for origin\n */\n function getLatestState(uint32 origin) external view returns (bytes memory statePayload);\n}\n\n// node_modules/@openzeppelin/contracts/utils/Strings.sol\n\n// OpenZeppelin Contracts (last updated v4.9.0) (utils/Strings.sol)\n\n/**\n * @dev String operations.\n */\nlibrary Strings {\n bytes16 private constant _SYMBOLS = \"0123456789abcdef\";\n uint8 private constant _ADDRESS_LENGTH = 20;\n\n /**\n * @dev Converts a `uint256` to its ASCII `string` decimal representation.\n */\n function toString(uint256 value) internal pure returns (string memory) {\n unchecked {\n uint256 length = Math.log10(value) + 1;\n string memory buffer = new string(length);\n uint256 ptr;\n /// @solidity memory-safe-assembly\n assembly {\n ptr := add(buffer, add(32, length))\n }\n while (true) {\n ptr--;\n /// @solidity memory-safe-assembly\n assembly {\n mstore8(ptr, byte(mod(value, 10), _SYMBOLS))\n }\n value /= 10;\n if (value == 0) break;\n }\n return buffer;\n }\n }\n\n /**\n * @dev Converts a `int256` to its ASCII `string` decimal representation.\n */\n function toString(int256 value) internal pure returns (string memory) {\n return string(abi.encodePacked(value \u003c 0 ? \"-\" : \"\", toString(SignedMath.abs(value))));\n }\n\n /**\n * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation.\n */\n function toHexString(uint256 value) internal pure returns (string memory) {\n unchecked {\n return toHexString(value, Math.log256(value) + 1);\n }\n }\n\n /**\n * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length.\n */\n function toHexString(uint256 value, uint256 length) internal pure returns (string memory) {\n bytes memory buffer = new bytes(2 * length + 2);\n buffer[0] = \"0\";\n buffer[1] = \"x\";\n for (uint256 i = 2 * length + 1; i \u003e 1; --i) {\n buffer[i] = _SYMBOLS[value \u0026 0xf];\n value \u003e\u003e= 4;\n }\n require(value == 0, \"Strings: hex length insufficient\");\n return string(buffer);\n }\n\n /**\n * @dev Converts an `address` with fixed length of 20 bytes to its not checksummed ASCII `string` hexadecimal representation.\n */\n function toHexString(address addr) internal pure returns (string memory) {\n return toHexString(uint256(uint160(addr)), _ADDRESS_LENGTH);\n }\n\n /**\n * @dev Returns true if the two strings are equal.\n */\n function equal(string memory a, string memory b) internal pure returns (bool) {\n return keccak256(bytes(a)) == keccak256(bytes(b));\n }\n}\n\n// node_modules/@openzeppelin/contracts-upgradeable/utils/ContextUpgradeable.sol\n\n// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)\n\n/**\n * @dev Provides information about the current execution context, including the\n * sender of the transaction and its data. While these are generally available\n * via msg.sender and msg.data, they should not be accessed in such a direct\n * manner, since when dealing with meta-transactions the account sending and\n * paying for execution may not be the actual sender (as far as an application\n * is concerned).\n *\n * This contract is only required for intermediate, library-like contracts.\n */\nabstract contract ContextUpgradeable is Initializable {\n function __Context_init() internal onlyInitializing {\n }\n\n function __Context_init_unchained() internal onlyInitializing {\n }\n function _msgSender() internal view virtual returns (address) {\n return msg.sender;\n }\n\n function _msgData() internal view virtual returns (bytes calldata) {\n return msg.data;\n }\n\n /**\n * @dev This empty reserved space is put in place to allow future versions to add new\n * variables without shifting down storage in the inheritance chain.\n * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\n */\n uint256[50] private __gap;\n}\n\n// contracts/libs/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/utils/cryptography/ECDSA.sol\n\n// OpenZeppelin Contracts (last updated v4.9.0) (utils/cryptography/ECDSA.sol)\n\n/**\n * @dev Elliptic Curve Digital Signature Algorithm (ECDSA) operations.\n *\n * These functions can be used to verify that a message was signed by the holder\n * of the private keys of a given address.\n */\nlibrary ECDSA {\n enum RecoverError {\n NoError,\n InvalidSignature,\n InvalidSignatureLength,\n InvalidSignatureS,\n InvalidSignatureV // Deprecated in v4.8\n }\n\n function _throwError(RecoverError error) private pure {\n if (error == RecoverError.NoError) {\n return; // no error: do nothing\n } else if (error == RecoverError.InvalidSignature) {\n revert(\"ECDSA: invalid signature\");\n } else if (error == RecoverError.InvalidSignatureLength) {\n revert(\"ECDSA: invalid signature length\");\n } else if (error == RecoverError.InvalidSignatureS) {\n revert(\"ECDSA: invalid signature 's' value\");\n }\n }\n\n /**\n * @dev Returns the address that signed a hashed message (`hash`) with\n * `signature` or error string. This address can then be used for verification purposes.\n *\n * The `ecrecover` EVM opcode allows for malleable (non-unique) signatures:\n * this function rejects them by requiring the `s` value to be in the lower\n * half order, and the `v` value to be either 27 or 28.\n *\n * IMPORTANT: `hash` _must_ be the result of a hash operation for the\n * verification to be secure: it is possible to craft signatures that\n * recover to arbitrary addresses for non-hashed data. A safe way to ensure\n * this is by receiving a hash of the original message (which may otherwise\n * be too long), and then calling {toEthSignedMessageHash} on it.\n *\n * Documentation for signature generation:\n * - with https://web3js.readthedocs.io/en/v1.3.4/web3-eth-accounts.html#sign[Web3.js]\n * - with https://docs.ethers.io/v5/api/signer/#Signer-signMessage[ethers]\n *\n * _Available since v4.3._\n */\n function tryRecover(bytes32 hash, bytes memory signature) internal pure returns (address, RecoverError) {\n if (signature.length == 65) {\n bytes32 r;\n bytes32 s;\n uint8 v;\n // ecrecover takes the signature parameters, and the only way to get them\n // currently is to use assembly.\n /// @solidity memory-safe-assembly\n assembly {\n r := mload(add(signature, 0x20))\n s := mload(add(signature, 0x40))\n v := byte(0, mload(add(signature, 0x60)))\n }\n return tryRecover(hash, v, r, s);\n } else {\n return (address(0), RecoverError.InvalidSignatureLength);\n }\n }\n\n /**\n * @dev Returns the address that signed a hashed message (`hash`) with\n * `signature`. This address can then be used for verification purposes.\n *\n * The `ecrecover` EVM opcode allows for malleable (non-unique) signatures:\n * this function rejects them by requiring the `s` value to be in the lower\n * half order, and the `v` value to be either 27 or 28.\n *\n * IMPORTANT: `hash` _must_ be the result of a hash operation for the\n * verification to be secure: it is possible to craft signatures that\n * recover to arbitrary addresses for non-hashed data. A safe way to ensure\n * this is by receiving a hash of the original message (which may otherwise\n * be too long), and then calling {toEthSignedMessageHash} on it.\n */\n function recover(bytes32 hash, bytes memory signature) internal pure returns (address) {\n (address recovered, RecoverError error) = tryRecover(hash, signature);\n _throwError(error);\n return recovered;\n }\n\n /**\n * @dev Overload of {ECDSA-tryRecover} that receives the `r` and `vs` short-signature fields separately.\n *\n * See https://eips.ethereum.org/EIPS/eip-2098[EIP-2098 short signatures]\n *\n * _Available since v4.3._\n */\n function tryRecover(bytes32 hash, bytes32 r, bytes32 vs) internal pure returns (address, RecoverError) {\n bytes32 s = vs \u0026 bytes32(0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff);\n uint8 v = uint8((uint256(vs) \u003e\u003e 255) + 27);\n return tryRecover(hash, v, r, s);\n }\n\n /**\n * @dev Overload of {ECDSA-recover} that receives the `r and `vs` short-signature fields separately.\n *\n * _Available since v4.2._\n */\n function recover(bytes32 hash, bytes32 r, bytes32 vs) internal pure returns (address) {\n (address recovered, RecoverError error) = tryRecover(hash, r, vs);\n _throwError(error);\n return recovered;\n }\n\n /**\n * @dev Overload of {ECDSA-tryRecover} that receives the `v`,\n * `r` and `s` signature fields separately.\n *\n * _Available since v4.3._\n */\n function tryRecover(bytes32 hash, uint8 v, bytes32 r, bytes32 s) internal pure returns (address, RecoverError) {\n // EIP-2 still allows signature malleability for ecrecover(). Remove this possibility and make the signature\n // unique. Appendix F in the Ethereum Yellow paper (https://ethereum.github.io/yellowpaper/paper.pdf), defines\n // the valid range for s in (301): 0 \u003c s \u003c secp256k1n ÷ 2 + 1, and for v in (302): v ∈ {27, 28}. Most\n // signatures from current libraries generate a unique signature with an s-value in the lower half order.\n //\n // If your library generates malleable signatures, such as s-values in the upper range, calculate a new s-value\n // with 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141 - s1 and flip v from 27 to 28 or\n // vice versa. If your library also generates signatures with 0/1 for v instead 27/28, add 27 to v to accept\n // these malleable signatures as well.\n if (uint256(s) \u003e 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0) {\n return (address(0), RecoverError.InvalidSignatureS);\n }\n\n // If the signature is valid (and not malleable), return the signer address\n address signer = ecrecover(hash, v, r, s);\n if (signer == address(0)) {\n return (address(0), RecoverError.InvalidSignature);\n }\n\n return (signer, RecoverError.NoError);\n }\n\n /**\n * @dev Overload of {ECDSA-recover} that receives the `v`,\n * `r` and `s` signature fields separately.\n */\n function recover(bytes32 hash, uint8 v, bytes32 r, bytes32 s) internal pure returns (address) {\n (address recovered, RecoverError error) = tryRecover(hash, v, r, s);\n _throwError(error);\n return recovered;\n }\n\n /**\n * @dev Returns an Ethereum Signed Message, created from a `hash`. This\n * produces hash corresponding to the one signed with the\n * https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`]\n * JSON-RPC method as part of EIP-191.\n *\n * See {recover}.\n */\n function toEthSignedMessageHash(bytes32 hash) internal pure returns (bytes32 message) {\n // 32 is the length in bytes of hash,\n // enforced by the type signature above\n /// @solidity memory-safe-assembly\n assembly {\n mstore(0x00, \"\\x19Ethereum Signed Message:\\n32\")\n mstore(0x1c, hash)\n message := keccak256(0x00, 0x3c)\n }\n }\n\n /**\n * @dev Returns an Ethereum Signed Message, created from `s`. This\n * produces hash corresponding to the one signed with the\n * https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`]\n * JSON-RPC method as part of EIP-191.\n *\n * See {recover}.\n */\n function toEthSignedMessageHash(bytes memory s) internal pure returns (bytes32) {\n return keccak256(abi.encodePacked(\"\\x19Ethereum Signed Message:\\n\", Strings.toString(s.length), s));\n }\n\n /**\n * @dev Returns an Ethereum Signed Typed Data, created from a\n * `domainSeparator` and a `structHash`. This produces hash corresponding\n * to the one signed with the\n * https://eips.ethereum.org/EIPS/eip-712[`eth_signTypedData`]\n * JSON-RPC method as part of EIP-712.\n *\n * See {recover}.\n */\n function toTypedDataHash(bytes32 domainSeparator, bytes32 structHash) internal pure returns (bytes32 data) {\n /// @solidity memory-safe-assembly\n assembly {\n let ptr := mload(0x40)\n mstore(ptr, \"\\x19\\x01\")\n mstore(add(ptr, 0x02), domainSeparator)\n mstore(add(ptr, 0x22), structHash)\n data := keccak256(ptr, 0x42)\n }\n }\n\n /**\n * @dev Returns an Ethereum Signed Data with intended validator, created from a\n * `validator` and `data` according to the version 0 of EIP-191.\n *\n * See {recover}.\n */\n function toDataWithIntendedValidatorHash(address validator, bytes memory data) internal pure returns (bytes32) {\n return keccak256(abi.encodePacked(\"\\x19\\x00\", validator, data));\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/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/inbox/StatementInbox.sol\n\n// ══════════════════════════════ LIBRARY IMPORTS ══════════════════════════════\n\n// ═════════════════════════════ INTERNAL IMPORTS ══════════════════════════════\n\n// ═════════════════════════════ EXTERNAL IMPORTS ══════════════════════════════\n\n/// @notice `StatementInbox` is the entry point for all agent-signed statements. It verifies the\n/// agent signatures, and passes the unsigned statements to the contract to consume it via `acceptX` functions. Is is\n/// also used to verify the agent-signed statements and initiate the agent slashing, should the statement be invalid.\n/// `StatementInbox` is responsible for the following:\n/// - Accepting State and Receipt Reports to initiate a dispute between Guard and Notary.\n/// - Storing all the Guard Reports with the Guard signature leading to a dispute.\n/// - Verifying State/State Reports referencing the local chain and slashing the signer if statement is invalid.\n/// - Verifying Receipt/Receipt Reports referencing the local chain and slashing the signer if statement is invalid.\nabstract contract StatementInbox is MessagingBase, StatementInboxEvents, IStatementInbox {\n using AttestationLib for bytes;\n using ReceiptLib for bytes;\n using StateLib for bytes;\n using SnapshotLib for bytes;\n\n struct StoredReport {\n uint256 sigIndex;\n bytes statementPayload;\n }\n\n // ══════════════════════════════════════════════════ STORAGE ══════════════════════════════════════════════════════\n\n address public agentManager;\n address public origin;\n address public destination;\n\n // TODO: optimize this\n bytes[] internal _storedSignatures;\n StoredReport[] internal _storedReports;\n\n /// @dev gap for upgrade safety\n uint256[45] private __GAP; // solhint-disable-line var-name-mixedcase\n\n // ════════════════════════════════════════════════ INITIALIZER ════════════════════════════════════════════════════\n\n /// @dev Initializes the contract:\n /// - Sets up `msg.sender` as the owner of the contract.\n /// - Sets up `agentManager`, `origin`, and `destination`.\n // solhint-disable-next-line func-name-mixedcase\n function __StatementInbox_init(address agentManager_, address origin_, address destination_)\n internal\n onlyInitializing\n {\n agentManager = agentManager_;\n origin = origin_;\n destination = destination_;\n __Ownable2Step_init();\n }\n\n // ══════════════════════════════════════════ SUBMIT AGENT STATEMENTS ══════════════════════════════════════════════\n\n /// @inheritdoc IStatementInbox\n // solhint-disable-next-line ordering\n function submitStateReportWithSnapshot(\n uint8 stateIndex,\n bytes memory srSignature,\n bytes memory snapPayload,\n bytes memory snapSignature\n ) external returns (bool wasAccepted) {\n // This will revert if payload is not a snapshot\n Snapshot snapshot = snapPayload.castToSnapshot();\n // This will revert if the snapshot signer is not a known Notary\n (AgentStatus memory notaryStatus,) =\n _verifySnapshot({snapshot: snapshot, snapSignature: snapSignature, verifyNotary: true});\n // Notary needs to be Active/Unstaking\n notaryStatus.verifyActiveUnstaking();\n // Check if Notary is active on this chain\n _verifyNotaryDomain(notaryStatus.domain);\n // This will revert if state index is out of range\n State state = snapshot.state(stateIndex);\n // This will revert if the report signer is not an known Guard\n (AgentStatus memory guardStatus,) = _verifyStateReport(state, srSignature);\n // Check that Guard is active\n guardStatus.verifyActive();\n _saveReport(state.unwrap().clone(), srSignature);\n // This will revert if either actor is already in dispute\n IAgentManager(agentManager).openDispute(guardStatus.index, notaryStatus.index);\n return true;\n }\n\n /// @inheritdoc IStatementInbox\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 // This will revert if payload is not a snapshot\n Snapshot snapshot = snapPayload.castToSnapshot();\n // This will revert if state index is out of range\n State state = snapshot.state(stateIndex);\n // This will revert if the report signer is not an known Guard\n (AgentStatus memory guardStatus,) = _verifyStateReport(state, srSignature);\n // Check that Guard is active\n guardStatus.verifyActive();\n // This will revert if payload is not an attestation\n Attestation att = attPayload.castToAttestation();\n // This will revert if signer is not an known Notary\n (AgentStatus memory notaryStatus,) = _verifyAttestation(att, attSignature);\n // Notary needs to be Active/Unstaking\n notaryStatus.verifyActiveUnstaking();\n // Check if Notary is active on this chain\n _verifyNotaryDomain(notaryStatus.domain);\n if (snapshot.calculateRoot() != att.snapRoot()) revert IncorrectSnapshotRoot();\n _saveReport(state.unwrap().clone(), srSignature);\n // This will revert if either actor is already in dispute\n IAgentManager(agentManager).openDispute(guardStatus.index, notaryStatus.index);\n return true;\n }\n\n /// @inheritdoc IStatementInbox\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 // This will revert if payload is not a state\n State state = statePayload.castToState();\n // This will revert if the report signer is not an known Guard\n (AgentStatus memory guardStatus,) = _verifyStateReport(state, srSignature);\n // Check that Guard is active\n guardStatus.verifyActive();\n // This will revert if payload is not an attestation\n Attestation att = attPayload.castToAttestation();\n // This will revert if signer is not a known Notary\n (AgentStatus memory notaryStatus,) = _verifyAttestation(att, attSignature);\n // Notary needs to be Active/Unstaking\n notaryStatus.verifyActiveUnstaking();\n // Check if Notary is active on this chain\n _verifyNotaryDomain(notaryStatus.domain);\n // This will revert if any of these is true:\n // - Attestation root is not equal to Merkle Root derived from State and Snapshot Proof.\n // - Snapshot Proof's first element does not match the State metadata.\n // - Snapshot Proof length exceeds Snapshot tree Height.\n // - State index is out of range.\n _verifySnapshotMerkle(att, stateIndex, state, snapProof);\n _saveReport(statePayload, srSignature);\n // This will revert if either actor is already in dispute\n IAgentManager(agentManager).openDispute(guardStatus.index, notaryStatus.index);\n return true;\n }\n\n // ══════════════════════════════════════════ VERIFY AGENT STATEMENTS ══════════════════════════════════════════════\n\n /// @inheritdoc IStatementInbox\n function verifyReceipt(bytes memory rcptPayload, bytes memory rcptSignature)\n external\n returns (bool isValidReceipt)\n {\n // This will revert if payload is not a receipt\n Receipt rcpt = rcptPayload.castToReceipt();\n // This will revert if the attestation signer is not a known Notary\n (AgentStatus memory status, address notary) = _verifyReceipt(rcpt, rcptSignature);\n // Notary needs to be Active/Unstaking\n status.verifyActiveUnstaking();\n isValidReceipt = IExecutionHub(destination).isValidReceipt(rcptPayload);\n if (!isValidReceipt) {\n emit InvalidReceipt(rcptPayload, rcptSignature);\n IAgentManager(agentManager).slashAgent(status.domain, notary, msg.sender);\n }\n }\n\n /// @inheritdoc IStatementInbox\n function verifyReceiptReport(bytes memory rcptPayload, bytes memory rrSignature)\n external\n returns (bool isValidReport)\n {\n // This will revert if payload is not a receipt\n Receipt rcpt = rcptPayload.castToReceipt();\n // This will revert if the report signer is not a known Guard\n (AgentStatus memory status, address guard) = _verifyReceiptReport(rcpt, rrSignature);\n // Guard needs to be Active/Unstaking\n status.verifyActiveUnstaking();\n // Report is valid IF AND ONLY IF the reported receipt in invalid\n isValidReport = !IExecutionHub(destination).isValidReceipt(rcptPayload);\n if (!isValidReport) {\n emit InvalidReceiptReport(rcptPayload, rrSignature);\n IAgentManager(agentManager).slashAgent(status.domain, guard, msg.sender);\n }\n }\n\n /// @inheritdoc IStatementInbox\n function verifyStateWithAttestation(\n uint8 stateIndex,\n bytes memory snapPayload,\n bytes memory attPayload,\n bytes memory attSignature\n ) external returns (bool isValidState) {\n // This will revert if payload is not an attestation\n Attestation att = attPayload.castToAttestation();\n // This will revert if the attestation signer is not a known Notary\n (AgentStatus memory status, address notary) = _verifyAttestation(att, attSignature);\n // Notary needs to be Active/Unstaking\n status.verifyActiveUnstaking();\n // This will revert if payload is not a snapshot\n Snapshot snapshot = snapPayload.castToSnapshot();\n if (snapshot.calculateRoot() != att.snapRoot()) revert IncorrectSnapshotRoot();\n // This will revert if state does not refer to this chain\n bytes memory statePayload = snapshot.state(stateIndex).unwrap().clone();\n isValidState = IStateHub(origin).isValidState(statePayload);\n if (!isValidState) {\n emit InvalidStateWithAttestation(stateIndex, statePayload, attPayload, attSignature);\n IAgentManager(agentManager).slashAgent(status.domain, notary, msg.sender);\n }\n }\n\n /// @inheritdoc IStatementInbox\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 // This will revert if payload is not an attestation\n Attestation att = attPayload.castToAttestation();\n // This will revert if the attestation signer is not a known Notary\n (AgentStatus memory status, address notary) = _verifyAttestation(att, attSignature);\n // Notary needs to be Active/Unstaking\n status.verifyActiveUnstaking();\n // This will revert if payload is not a state\n State state = statePayload.castToState();\n // This will revert if any of these is true:\n // - Attestation root is not equal to Merkle Root derived from State and Snapshot Proof.\n // - Snapshot Proof's first element does not match the State metadata.\n // - Snapshot Proof length exceeds Snapshot tree Height.\n // - State index is out of range.\n _verifySnapshotMerkle(att, stateIndex, state, snapProof);\n // This will revert if state does not refer to this chain\n isValidState = IStateHub(origin).isValidState(statePayload);\n if (!isValidState) {\n emit InvalidStateWithAttestation(stateIndex, statePayload, attPayload, attSignature);\n IAgentManager(agentManager).slashAgent(status.domain, notary, msg.sender);\n }\n }\n\n /// @inheritdoc IStatementInbox\n function verifyStateWithSnapshot(uint8 stateIndex, bytes memory snapPayload, bytes memory snapSignature)\n external\n returns (bool isValidState)\n {\n // This will revert if payload is not a snapshot\n Snapshot snapshot = snapPayload.castToSnapshot();\n // This will revert if the snapshot signer is not a known Guard/Notary\n (AgentStatus memory status, address agent) =\n _verifySnapshot({snapshot: snapshot, snapSignature: snapSignature, verifyNotary: false});\n // Agent needs to be Active/Unstaking\n status.verifyActiveUnstaking();\n // This will revert if state does not refer to this chain\n isValidState = IStateHub(origin).isValidState(snapshot.state(stateIndex).unwrap().clone());\n if (!isValidState) {\n emit InvalidStateWithSnapshot(stateIndex, snapPayload, snapSignature);\n IAgentManager(agentManager).slashAgent(status.domain, agent, msg.sender);\n }\n }\n\n /// @inheritdoc IStatementInbox\n function verifyStateReport(bytes memory statePayload, bytes memory srSignature)\n external\n returns (bool isValidReport)\n {\n // This will revert if payload is not a state\n State state = statePayload.castToState();\n // This will revert if the report signer is not a known Guard\n (AgentStatus memory status, address guard) = _verifyStateReport(state, srSignature);\n // Guard needs to be Active/Unstaking\n status.verifyActiveUnstaking();\n // Report is valid IF AND ONLY IF the reported state in invalid\n // This will revert if the reported state does not refer to this chain\n isValidReport = !IStateHub(origin).isValidState(statePayload);\n if (!isValidReport) {\n emit InvalidStateReport(statePayload, srSignature);\n IAgentManager(agentManager).slashAgent(status.domain, guard, msg.sender);\n }\n }\n\n // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════\n\n /// @inheritdoc IStatementInbox\n function getReportsAmount() external view returns (uint256) {\n return _storedReports.length;\n }\n\n /// @inheritdoc IStatementInbox\n function getGuardReport(uint256 index)\n external\n view\n returns (bytes memory statementPayload, bytes memory reportSignature)\n {\n if (index \u003e= _storedReports.length) revert IndexOutOfRange();\n StoredReport memory storedReport = _storedReports[index];\n statementPayload = storedReport.statementPayload;\n reportSignature = _storedSignatures[storedReport.sigIndex];\n }\n\n /// @inheritdoc IStatementInbox\n function getStoredSignature(uint256 index) external view returns (bytes memory) {\n return _storedSignatures[index];\n }\n\n // ══════════════════════════════════════════════ INTERNAL LOGIC ═══════════════════════════════════════════════════\n\n /// @dev Saves the statement reported by Guard as invalid and the Guard Report signature.\n function _saveReport(bytes memory statementPayload, bytes memory reportSignature) internal {\n uint256 sigIndex = _saveSignature(reportSignature);\n _storedReports.push(StoredReport(sigIndex, statementPayload));\n }\n\n /// @dev Saves the signature and returns its index.\n function _saveSignature(bytes memory signature) internal returns (uint256 sigIndex) {\n sigIndex = _storedSignatures.length;\n _storedSignatures.push(signature);\n }\n\n // ═══════════════════════════════════════════════ AGENT CHECKS ════════════════════════════════════════════════════\n\n /**\n * @dev Recovers a signer from a hashed message, and a EIP-191 signature for it.\n * Will revert, if the signer is not a known agent.\n * @dev Agent flag could be any of these: Active/Unstaking/Resting/Fraudulent/Slashed\n * Further checks need to be performed in a caller function.\n * @param hashedStatement Hash of the statement that was signed by an Agent\n * @param signature Agent signature for the hashed statement\n * @return status Struct representing agent status:\n * - flag Unknown/Active/Unstaking/Resting/Fraudulent/Slashed\n * - domain Domain where agent is/was active\n * - index Index of agent in the Agent Merkle Tree\n * @return agent Agent that signed the statement\n */\n function _recoverAgent(bytes32 hashedStatement, bytes memory signature)\n internal\n view\n returns (AgentStatus memory status, address agent)\n {\n bytes32 ethSignedMsg = ECDSA.toEthSignedMessageHash(hashedStatement);\n agent = ECDSA.recover(ethSignedMsg, signature);\n status = IAgentManager(agentManager).agentStatus(agent);\n // Discard signature of unknown agents.\n // Further flag checks are supposed to be performed in a caller function.\n status.verifyKnown();\n }\n\n /// @dev Verifies that Notary signature is active on local domain.\n function _verifyNotaryDomain(uint32 notaryDomain) internal view {\n // Notary needs to be from the local domain (if contract is not deployed on Synapse Chain).\n // Or Notary could be from any domain (if contract is deployed on Synapse Chain).\n if (notaryDomain != localDomain \u0026\u0026 localDomain != synapseDomain) revert IncorrectAgentDomain();\n }\n\n // ════════════════════════════════════════ ATTESTATION RELATED CHECKS ═════════════════════════════════════════════\n\n /**\n * @dev Internal function to verify the signed attestation payload.\n * Reverts if any of these is true:\n * - Attestation signer is not a known Notary.\n * @param att Typed memory view over attestation payload\n * @param attSignature Notary signature for the attestation\n * @return status Struct representing agent status, see {_recoverAgent}\n * @return notary Notary that signed the snapshot\n */\n function _verifyAttestation(Attestation att, bytes memory attSignature)\n internal\n view\n returns (AgentStatus memory status, address notary)\n {\n // This will revert if signer is not a known agent\n (status, notary) = _recoverAgent(att.hashValid(), attSignature);\n // Attestation signer needs to be a Notary, not a Guard\n if (status.domain == 0) revert AgentNotNotary();\n }\n\n /**\n * @dev Internal function to verify the signed attestation report payload.\n * Reverts if any of these is true:\n * - Report signer is not a known Guard.\n * @param att Typed memory view over attestation payload that Guard reports as invalid\n * @param arSignature Guard signature for the \"invalid attestation\" report\n * @return status Struct representing guard status, see {_recoverAgent}\n * @return guard Guard that signed the report\n */\n function _verifyAttestationReport(Attestation att, bytes memory arSignature)\n internal\n view\n returns (AgentStatus memory status, address guard)\n {\n // This will revert if signer is not a known agent\n (status, guard) = _recoverAgent(att.hashInvalid(), arSignature);\n // Report signer needs to be a Guard, not a Notary\n if (status.domain != 0) revert AgentNotGuard();\n }\n\n // ══════════════════════════════════════════ RECEIPT RELATED CHECKS ═══════════════════════════════════════════════\n\n /**\n * @dev Internal function to verify the signed receipt payload.\n * Reverts if any of these is true:\n * - Receipt signer is not a known Notary.\n * @param rcpt Typed memory view over receipt payload\n * @param rcptSignature Notary signature for the receipt\n * @return status Struct representing agent status, see {_recoverAgent}\n * @return notary Notary that signed the snapshot\n */\n function _verifyReceipt(Receipt rcpt, bytes memory rcptSignature)\n internal\n view\n returns (AgentStatus memory status, address notary)\n {\n // This will revert if signer is not a known agent\n (status, notary) = _recoverAgent(rcpt.hashValid(), rcptSignature);\n // Receipt signer needs to be a Notary, not a Guard\n if (status.domain == 0) revert AgentNotNotary();\n }\n\n /**\n * @dev Internal function to verify the signed receipt report payload.\n * Reverts if any of these is true:\n * - Report signer is not a known Guard.\n * @param rcpt Typed memory view over receipt payload that Guard reports as invalid\n * @param rrSignature Guard signature for the \"invalid receipt\" report\n * @return status Struct representing guard status, see {_recoverAgent}\n * @return guard Guard that signed the report\n */\n function _verifyReceiptReport(Receipt rcpt, bytes memory rrSignature)\n internal\n view\n returns (AgentStatus memory status, address guard)\n {\n // This will revert if signer is not a known agent\n (status, guard) = _recoverAgent(rcpt.hashInvalid(), rrSignature);\n // Report signer needs to be a Guard, not a Notary\n if (status.domain != 0) revert AgentNotGuard();\n }\n\n // ═══════════════════════════════════════ STATE/SNAPSHOT RELATED CHECKS ═══════════════════════════════════════════\n\n /**\n * @dev Internal function to verify the signed snapshot report payload.\n * Reverts if any of these is true:\n * - Report signer is not a known Guard.\n * @param state Typed memory view over state payload that Guard reports as invalid\n * @param srSignature Guard signature for the report\n * @return status Struct representing guard status, see {_recoverAgent}\n * @return guard Guard that signed the report\n */\n function _verifyStateReport(State state, bytes memory srSignature)\n internal\n view\n returns (AgentStatus memory status, address guard)\n {\n // This will revert if signer is not a known agent\n (status, guard) = _recoverAgent(state.hashInvalid(), srSignature);\n // Report signer needs to be a Guard, not a Notary\n if (status.domain != 0) revert AgentNotGuard();\n }\n\n /**\n * @dev Internal function to verify the signed snapshot payload.\n * Reverts if any of these is true:\n * - Snapshot signer is not a known Agent.\n * - Snapshot signer is not a Notary (if verifyNotary is true).\n * @param snapshot Typed memory view over snapshot payload\n * @param snapSignature Agent signature for the snapshot\n * @param verifyNotary If true, snapshot signer needs to be a Notary, not a Guard\n * @return status Struct representing agent status, see {_recoverAgent}\n * @return agent Agent that signed the snapshot\n */\n function _verifySnapshot(Snapshot snapshot, bytes memory snapSignature, bool verifyNotary)\n internal\n view\n returns (AgentStatus memory status, address agent)\n {\n // This will revert if signer is not a known agent\n (status, agent) = _recoverAgent(snapshot.hashValid(), snapSignature);\n // If requested, snapshot signer needs to be a Notary, not a Guard\n if (verifyNotary \u0026\u0026 status.domain == 0) revert AgentNotNotary();\n }\n\n // ═══════════════════════════════════════════ MERKLE RELATED CHECKS ═══════════════════════════════════════════════\n\n /**\n * @dev Internal function to verify that snapshot roots match.\n * Reverts if any of these is true:\n * - Attestation root is not equal to Merkle Root derived from State and Snapshot Proof.\n * - Snapshot Proof's first element does not match the State metadata.\n * - Snapshot Proof length exceeds Snapshot tree Height.\n * - State index is out of range.\n * @param att Typed memory view over Attestation\n * @param stateIndex Index of state in the snapshot\n * @param state Typed memory view over the provided state payload\n * @param snapProof Raw payload with snapshot data\n */\n function _verifySnapshotMerkle(Attestation att, uint8 stateIndex, State state, bytes32[] memory snapProof)\n internal\n pure\n {\n // Snapshot proof first element should match State metadata (aka \"right sub-leaf\")\n (, bytes32 rightSubLeaf) = state.subLeafs();\n if (snapProof[0] != rightSubLeaf) revert IncorrectSnapshotProof();\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(state.root(), state.origin(), snapProof, stateIndex);\n // Snapshot root should match the attestation root\n if (att.snapRoot() != snapshotRoot) revert IncorrectSnapshotRoot();\n }\n}\n\n// contracts/inbox/Inbox.sol\n\n// ══════════════════════════════ LIBRARY IMPORTS ══════════════════════════════\n\n// ═════════════════════════════ INTERNAL IMPORTS ══════════════════════════════\n\n/// @notice `Inbox` is the child of `StatementInbox` contract, that is used on Synapse Chain.\n/// In addition to the functionality of `StatementInbox`, it also:\n/// - Accepts Guard and Notary Snapshots and passes them to `Summit` contract.\n/// - Accepts Notary-signed Receipts and passes them to `Summit` contract.\n/// - Accepts Receipt Reports to initiate a dispute between Guard and Notary.\n/// - Verifies Attestations and Attestation Reports, and slashes the signer if they are invalid.\ncontract Inbox is StatementInbox, InboxEvents, InterfaceInbox {\n using AttestationLib for bytes;\n using ReceiptLib for bytes;\n using SnapshotLib for bytes;\n\n // Struct to get around stack too deep error. TODO: revisit this\n struct ReceiptInfo {\n AgentStatus rcptNotaryStatus;\n address notary;\n uint32 attNonce;\n AgentStatus attNotaryStatus;\n }\n\n // ══════════════════════════════════════════════════ STORAGE ══════════════════════════════════════════════════════\n\n // The address of the Summit contract.\n address public summit;\n\n // ═════════════════════════════════════════ CONSTRUCTOR \u0026 INITIALIZER ═════════════════════════════════════════════\n\n constructor(uint32 synapseDomain_) MessagingBase(\"0.0.3\", synapseDomain_) {\n if (localDomain != synapseDomain) revert MustBeSynapseDomain();\n }\n\n /// @notice Initializes `Inbox` contract:\n /// - Sets `msg.sender` as the owner of the contract\n /// - Sets `agentManager`, `origin`, `destination` and `summit` addresses\n function initialize(address agentManager_, address origin_, address destination_, address summit_)\n external\n initializer\n {\n __StatementInbox_init(agentManager_, origin_, destination_);\n summit = summit_;\n }\n\n // ══════════════════════════════════════════ SUBMIT AGENT STATEMENTS ══════════════════════════════════════════════\n\n /// @inheritdoc InterfaceInbox\n function submitSnapshot(bytes memory snapPayload, bytes memory snapSignature)\n external\n returns (bytes memory attPayload, bytes32 agentRoot_, uint256[] memory snapGas)\n {\n // This will revert if payload is not a snapshot\n Snapshot snapshot = snapPayload.castToSnapshot();\n // This will revert if the signer is not a known Guard/Notary\n (AgentStatus memory status, address agent) =\n _verifySnapshot({snapshot: snapshot, snapSignature: snapSignature, verifyNotary: false});\n // Check that Agent is active\n status.verifyActive();\n // Store Agent signature for the Snapshot\n uint256 sigIndex = _saveSignature(snapSignature);\n if (status.domain == 0) {\n // Guard that is in Dispute could still submit new snapshots, so we don't check that\n InterfaceSummit(summit).acceptGuardSnapshot({\n guardIndex: status.index,\n sigIndex: sigIndex,\n snapPayload: snapPayload\n });\n } else {\n // Get current agentRoot from AgentManager\n agentRoot_ = IAgentManager(agentManager).agentRoot();\n // This will revert if Notary is in Dispute\n attPayload = InterfaceSummit(summit).acceptNotarySnapshot({\n notaryIndex: status.index,\n sigIndex: sigIndex,\n agentRoot: agentRoot_,\n snapPayload: snapPayload\n });\n ChainGas[] memory snapGas_ = snapshot.snapGas();\n // Pass created attestation to Destination to enable executing messages coming to Synapse Chain\n InterfaceDestination(destination).acceptAttestation(\n status.index, type(uint256).max, attPayload, agentRoot_, snapGas_\n );\n // Use assembly to cast ChainGas[] to uint256[] without copying. Highest bits are left zeroed.\n // solhint-disable-next-line no-inline-assembly\n assembly {\n snapGas := snapGas_\n }\n }\n emit SnapshotAccepted(status.domain, agent, snapPayload, snapSignature);\n }\n\n /// @inheritdoc InterfaceInbox\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 // Struct to get around stack too deep error.\n ReceiptInfo memory info;\n // This will revert if payload is not a receipt\n Receipt rcpt = rcptPayload.castToReceipt();\n // This will revert if the receipt signer is not a known Notary\n (info.rcptNotaryStatus, info.notary) = _verifyReceipt(rcpt, rcptSignature);\n // Receipt Notary needs to be Active\n info.rcptNotaryStatus.verifyActive();\n info.attNonce = IExecutionHub(destination).getAttestationNonce(rcpt.snapshotRoot());\n if (info.attNonce == 0) revert IncorrectSnapshotRoot();\n // Attestation Notary domain needs to match the destination domain\n info.attNotaryStatus = IAgentManager(agentManager).agentStatus(rcpt.attNotary());\n if (info.attNotaryStatus.domain != rcpt.destination()) revert IncorrectAgentDomain();\n // Check that the correct tip values for the message were provided\n _verifyReceiptTips(rcpt.messageHash(), paddedTips, headerHash, bodyHash);\n // Store Notary signature for the Receipt\n uint256 sigIndex = _saveSignature(rcptSignature);\n // This will revert if Receipt Notary is in Dispute\n wasAccepted = InterfaceSummit(summit).acceptReceipt({\n rcptNotaryIndex: info.rcptNotaryStatus.index,\n attNotaryIndex: info.attNotaryStatus.index,\n sigIndex: sigIndex,\n attNonce: info.attNonce,\n paddedTips: paddedTips,\n rcptPayload: rcptPayload\n });\n if (wasAccepted) {\n emit ReceiptAccepted(info.rcptNotaryStatus.domain, info.notary, rcptPayload, rcptSignature);\n }\n }\n\n /// @inheritdoc InterfaceInbox\n function submitReceiptReport(bytes memory rcptPayload, bytes memory rcptSignature, bytes memory rrSignature)\n external\n returns (bool wasAccepted)\n {\n // This will revert if payload is not a receipt\n Receipt rcpt = rcptPayload.castToReceipt();\n // This will revert if the receipt signer is not a known Guard\n (AgentStatus memory guardStatus,) = _verifyReceiptReport(rcpt, rrSignature);\n // Guard needs to be Active\n guardStatus.verifyActive();\n // This will revert if report signer is not a known Notary\n (AgentStatus memory notaryStatus,) = _verifyReceipt(rcpt, rcptSignature);\n // Notary needs to be Active/Unstaking\n notaryStatus.verifyActiveUnstaking();\n _saveReport(rcptPayload, rrSignature);\n // This will revert if either actor is already in dispute\n IAgentManager(agentManager).openDispute(guardStatus.index, notaryStatus.index);\n return true;\n }\n\n /// @inheritdoc InterfaceInbox\n function passReceipt(uint32 attNotaryIndex, uint32 attNonce, uint256 paddedTips, bytes memory rcptPayload)\n external\n returns (bool wasAccepted)\n {\n // Only Destination can pass receipts\n if (msg.sender != destination) revert CallerNotDestination();\n return InterfaceSummit(summit).acceptReceipt({\n rcptNotaryIndex: attNotaryIndex,\n attNotaryIndex: attNotaryIndex,\n sigIndex: type(uint256).max,\n attNonce: attNonce,\n paddedTips: paddedTips,\n rcptPayload: rcptPayload\n });\n }\n\n // ══════════════════════════════════════════ VERIFY AGENT STATEMENTS ══════════════════════════════════════════════\n\n /// @inheritdoc InterfaceInbox\n function verifyAttestation(bytes memory attPayload, bytes memory attSignature)\n external\n returns (bool isValidAttestation)\n {\n // This will revert if payload is not an attestation\n Attestation att = attPayload.castToAttestation();\n // This will revert if the attestation signer is not a known Notary\n (AgentStatus memory status, address notary) = _verifyAttestation(att, attSignature);\n // Notary needs to be Active/Unstaking\n status.verifyActiveUnstaking();\n isValidAttestation = ISnapshotHub(summit).isValidAttestation(attPayload);\n if (!isValidAttestation) {\n emit InvalidAttestation(attPayload, attSignature);\n IAgentManager(agentManager).slashAgent(status.domain, notary, msg.sender);\n }\n }\n\n /// @inheritdoc InterfaceInbox\n function verifyAttestationReport(bytes memory attPayload, bytes memory arSignature)\n external\n returns (bool isValidReport)\n {\n // This will revert if payload is not an attestation\n Attestation att = attPayload.castToAttestation();\n // This will revert if the report signer is not a known Guard\n (AgentStatus memory status, address guard) = _verifyAttestationReport(att, arSignature);\n // Guard needs to be Active/Unstaking\n status.verifyActiveUnstaking();\n // Report is valid IF AND ONLY IF the reported attestation in invalid\n isValidReport = !ISnapshotHub(summit).isValidAttestation(attPayload);\n if (!isValidReport) {\n emit InvalidAttestationReport(attPayload, arSignature);\n IAgentManager(agentManager).slashAgent(status.domain, guard, msg.sender);\n }\n }\n\n // ══════════════════════════════════════════════ INTERNAL VIEWS ═══════════════════════════════════════════════════\n\n /// @dev Verifies that tips proof matches the message hash.\n function _verifyReceiptTips(bytes32 msgHash, uint256 paddedTips, bytes32 headerHash, bytes32 bodyHash)\n internal\n pure\n {\n Tips tips = TipsLib.wrapPadded(paddedTips);\n // full message leaf is (header, baseMessage), while base message leaf is (tips, remainingBody).\n if (MerkleMath.getParent(headerHash, MerkleMath.getParent(tips.leaf(), bodyHash)) != msgHash) {\n revert IncorrectTipsProof();\n }\n }\n}\n","language":"Solidity","languageVersion":"0.8.17","compilerVersion":"0.8.17","compilerOptions":"--combined-json bin,bin-runtime,srcmap,srcmap-runtime,abi,userdoc,devdoc,metadata,hashes --optimize --optimize-runs 10000 --allow-paths ., ./, ../","srcMap":"","srcMapRuntime":"","abiDefinition":[{"inputs":[{"internalType":"uint32","name":"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/Inbox.sol\":\"InterfaceInbox\"},\"evmVersion\":\"london\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\"},\"optimizer\":{\"enabled\":true,\"runs\":10000},\"remappings\":[]},\"sources\":{\"solidity/Inbox.sol\":{\"keccak256\":\"0x9b516081a036814c0169e20e484d4a5499066b7a6f48fada952b5e844a1ca3e5\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://32bde393b3f24ef4307d9626d4143f337b3c0bd34e17bb969fd5a15221d96987\",\"dweb:/ipfs/QmTkt2XZRtgsbSpmsVQUM3c4ebETQoDVYbmEV9yheBghnr\"]}},\"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/Inbox.sol:InterfaceSummit":{"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/InboxEvents.sol\n\nabstract contract InboxEvents {\n /**\n * @notice Emitted when a snapshot is accepted by the Summit contract.\n * @param domain Domain where the signed Agent is active (ZERO for Guards)\n * @param agent Agent who signed the snapshot\n * @param snapPayload Raw payload with snapshot data\n * @param snapSignature Agent signature for the snapshot\n */\n event SnapshotAccepted(uint32 indexed domain, address indexed agent, bytes snapPayload, bytes snapSignature);\n\n /**\n * @notice Emitted when a snapshot is accepted by the Summit contract.\n * @param domain Domain where the signed Notary is active\n * @param notary Notary who signed the attestation\n * @param rcptPayload Raw payload with receipt data\n * @param rcptSignature Notary signature for the receipt\n */\n event ReceiptAccepted(uint32 domain, address notary, bytes rcptPayload, bytes rcptSignature);\n\n /**\n * @notice Emitted when a proof of invalid attestation is submitted.\n * @param attPayload Raw payload with Attestation data\n * @param attSignature Notary signature for the attestation\n */\n event InvalidAttestation(bytes attPayload, bytes attSignature);\n\n /**\n * @notice Emitted when a proof of invalid attestation report is submitted.\n * @param arPayload Raw payload with report data\n * @param arSignature Guard signature for the report\n */\n event InvalidAttestationReport(bytes arPayload, bytes arSignature);\n}\n\n// contracts/events/StatementInboxEvents.sol\n\nabstract contract StatementInboxEvents {\n // ════════════════════════════════════════════ STATEMENT ACCEPTED ═════════════════════════════════════════════════\n\n /**\n * @notice Emitted when a snapshot is accepted by the Destination contract.\n * @param domain Domain where the signed Notary is active\n * @param notary Notary who signed the attestation\n * @param attPayload Raw payload with attestation data\n * @param attSignature Notary signature for the attestation\n */\n event AttestationAccepted(uint32 domain, address notary, bytes attPayload, bytes attSignature);\n\n // ═════════════════════════════════════════ INVALID STATEMENT PROVED ══════════════════════════════════════════════\n\n /**\n * @notice Emitted when a proof of invalid receipt statement is submitted.\n * @param rcptPayload Raw payload with the receipt statement\n * @param rcptSignature Notary signature for the receipt statement\n */\n event InvalidReceipt(bytes rcptPayload, bytes rcptSignature);\n\n /**\n * @notice Emitted when a proof of invalid receipt report is submitted.\n * @param rrPayload Raw payload with report data\n * @param rrSignature Guard signature for the report\n */\n event InvalidReceiptReport(bytes rrPayload, bytes rrSignature);\n\n /**\n * @notice Emitted when a proof of invalid state in the signed attestation is submitted.\n * @param stateIndex Index of invalid state in the snapshot\n * @param statePayload Raw payload with state data\n * @param attPayload Raw payload with Attestation data for snapshot\n * @param attSignature Notary signature for the attestation\n */\n event InvalidStateWithAttestation(uint8 stateIndex, bytes statePayload, bytes attPayload, bytes attSignature);\n\n /**\n * @notice Emitted when a proof of invalid state in the signed snapshot is submitted.\n * @param stateIndex Index of invalid state in the snapshot\n * @param snapPayload Raw payload with snapshot data\n * @param snapSignature Agent signature for the snapshot\n */\n event InvalidStateWithSnapshot(uint8 stateIndex, bytes snapPayload, bytes snapSignature);\n\n /**\n * @notice Emitted when a proof of invalid state report is submitted.\n * @param srPayload Raw payload with report data\n * @param srSignature Guard signature for the report\n */\n event InvalidStateReport(bytes srPayload, bytes srSignature);\n}\n\n// contracts/interfaces/ISnapshotHub.sol\n\ninterface ISnapshotHub {\n /**\n * @notice Check that a given attestation is valid: matches the historical attestation\n * derived from an accepted Notary snapshot.\n * @dev Will revert if any of these is true:\n * - Attestation payload is not properly formatted.\n * @param attPayload Raw payload with attestation data\n * @return isValid Whether the provided attestation is valid\n */\n function isValidAttestation(bytes memory attPayload) external view returns (bool isValid);\n\n /**\n * @notice Returns saved attestation with the given nonce.\n * @dev Reverts if attestation with given nonce hasn't been created yet.\n * @param attNonce Nonce for the attestation\n * @return attPayload Raw payload with formatted Attestation data\n * @return agentRoot Agent root hash used for the attestation\n * @return snapGas Snapshot gas data used for the attestation\n */\n function getAttestation(uint32 attNonce)\n external\n view\n returns (bytes memory attPayload, bytes32 agentRoot, uint256[] memory snapGas);\n\n /**\n * @notice Returns the state with the highest known nonce submitted by a given Agent.\n * @param origin Domain of origin chain\n * @param agent Agent address\n * @return statePayload Raw payload with agent's latest state for origin\n */\n function getLatestAgentState(uint32 origin, address agent) external view returns (bytes memory statePayload);\n\n /**\n * @notice Returns latest saved attestation for a Notary.\n * @param notary Notary address\n * @return attPayload Raw payload with formatted Attestation data\n * @return agentRoot Agent root hash used for the attestation\n * @return snapGas Snapshot gas data used for the attestation\n */\n function getLatestNotaryAttestation(address notary)\n external\n view\n returns (bytes memory attPayload, bytes32 agentRoot, uint256[] memory snapGas);\n\n /**\n * @notice Returns Guard snapshot from the list of all accepted Guard snapshots.\n * @dev Reverts if snapshot with given index hasn't been accepted yet.\n * @param index Snapshot index in the list of all Guard snapshots\n * @return snapPayload Raw payload with Guard snapshot\n * @return snapSignature Raw payload with Guard signature for snapshot\n */\n function getGuardSnapshot(uint256 index)\n external\n view\n returns (bytes memory snapPayload, bytes memory snapSignature);\n\n /**\n * @notice Returns Notary snapshot from the list of all accepted Guard snapshots.\n * @dev Reverts if snapshot with given index hasn't been accepted yet.\n * @param index Snapshot index in the list of all Notary snapshots\n * @return snapPayload Raw payload with Notary snapshot\n * @return snapSignature Raw payload with Notary signature for snapshot\n */\n function getNotarySnapshot(uint256 index)\n external\n view\n returns (bytes memory snapPayload, bytes memory snapSignature);\n\n /**\n * @notice Returns Notary snapshot that was used for creating a given attestation.\n * @dev Reverts if any of these is true:\n * - Attestation payload is not properly formatted.\n * - Attestation is invalid (doesn't have a matching Notary snapshot).\n * @param attPayload Raw payload with attestation data\n * @return snapPayload Raw payload with Notary snapshot\n * @return snapSignature Raw payload with Notary signature for snapshot\n */\n function getNotarySnapshot(bytes memory attPayload)\n external\n view\n returns (bytes memory snapPayload, bytes memory snapSignature);\n\n /**\n * @notice Returns proof of inclusion of (root, origin) fields of a given snapshot's state\n * into the Snapshot Merkle Tree for a given attestation.\n * @dev Reverts if any of these is true:\n * - Attestation with given nonce hasn't been created yet.\n * - State index is out of range of snapshot list.\n * @param attNonce Nonce for the attestation\n * @param stateIndex Index of state in the attestation's snapshot\n * @return snapProof The snapshot proof\n */\n function getSnapshotProof(uint32 attNonce, uint8 stateIndex) external view returns (bytes32[] memory snapProof);\n}\n\n// contracts/interfaces/IStateHub.sol\n\ninterface IStateHub {\n /**\n * @notice Check that a given state is valid: matches the historical state of Origin contract.\n * Note: any Agent including an invalid state in their snapshot will be slashed\n * upon providing the snapshot and agent signature for it to Origin contract.\n * @dev Will revert if any of these is true:\n * - State payload is not properly formatted.\n * @param statePayload Raw payload with state data\n * @return isValid Whether the provided state is valid\n */\n function isValidState(bytes memory statePayload) external view returns (bool isValid);\n\n /**\n * @notice Returns the amount of saved states so far.\n * @dev This includes the initial state of \"empty Origin Merkle Tree\".\n */\n function statesAmount() external view returns (uint256);\n\n /**\n * @notice Suggest the data (state after latest sent message) to sign for an Agent.\n * Note: signing the suggested state data will will never lead to slashing of the actor,\n * assuming they have confirmed that the block, which number is included in the data,\n * is not subject to reorganization (which is different for every observed chain).\n * @return statePayload Raw payload with the latest state data\n */\n function suggestLatestState() external view returns (bytes memory statePayload);\n\n /**\n * @notice Given the historical nonce, suggest the state data to sign for an Agent.\n * Note: signing the suggested state data will will never lead to slashing of the actor,\n * assuming they have confirmed that the block, which number is included in the data,\n * is not subject to reorganization (which is different for every observed chain).\n * @param nonce Historical nonce to form a state\n * @return statePayload Raw payload with historical state data\n */\n function suggestState(uint32 nonce) external view returns (bytes memory statePayload);\n}\n\n// contracts/interfaces/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/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// node_modules/@openzeppelin/contracts/utils/math/Math.sol\n\n// OpenZeppelin Contracts (last updated v4.9.0) (utils/math/Math.sol)\n\n/**\n * @dev Standard math utilities missing in the Solidity language.\n */\nlibrary Math {\n enum Rounding {\n Down, // Toward negative infinity\n Up, // Toward infinity\n Zero // Toward zero\n }\n\n /**\n * @dev Returns the largest of two numbers.\n */\n function max(uint256 a, uint256 b) internal pure returns (uint256) {\n return a \u003e b ? a : b;\n }\n\n /**\n * @dev Returns the smallest of two numbers.\n */\n function min(uint256 a, uint256 b) internal pure returns (uint256) {\n return a \u003c b ? a : b;\n }\n\n /**\n * @dev Returns the average of two numbers. The result is rounded towards\n * zero.\n */\n function average(uint256 a, uint256 b) internal pure returns (uint256) {\n // (a + b) / 2 can overflow.\n return (a \u0026 b) + (a ^ b) / 2;\n }\n\n /**\n * @dev Returns the ceiling of the division of two numbers.\n *\n * This differs from standard division with `/` in that it rounds up instead\n * of rounding down.\n */\n function ceilDiv(uint256 a, uint256 b) internal pure returns (uint256) {\n // (a + b - 1) / b can overflow on addition, so we distribute.\n return a == 0 ? 0 : (a - 1) / b + 1;\n }\n\n /**\n * @notice Calculates floor(x * y / denominator) with full precision. Throws if result overflows a uint256 or denominator == 0\n * @dev Original credit to Remco Bloemen under MIT license (https://xn--2-umb.com/21/muldiv)\n * with further edits by Uniswap Labs also under MIT license.\n */\n function mulDiv(uint256 x, uint256 y, uint256 denominator) internal pure returns (uint256 result) {\n unchecked {\n // 512-bit multiply [prod1 prod0] = x * y. Compute the product mod 2^256 and mod 2^256 - 1, then use\n // use the Chinese Remainder Theorem to reconstruct the 512 bit result. The result is stored in two 256\n // variables such that product = prod1 * 2^256 + prod0.\n uint256 prod0; // Least significant 256 bits of the product\n uint256 prod1; // Most significant 256 bits of the product\n assembly {\n let mm := mulmod(x, y, not(0))\n prod0 := mul(x, y)\n prod1 := sub(sub(mm, prod0), lt(mm, prod0))\n }\n\n // Handle non-overflow cases, 256 by 256 division.\n if (prod1 == 0) {\n // Solidity will revert if denominator == 0, unlike the div opcode on its own.\n // The surrounding unchecked block does not change this fact.\n // See https://docs.soliditylang.org/en/latest/control-structures.html#checked-or-unchecked-arithmetic.\n return prod0 / denominator;\n }\n\n // Make sure the result is less than 2^256. Also prevents denominator == 0.\n require(denominator \u003e prod1, \"Math: mulDiv overflow\");\n\n ///////////////////////////////////////////////\n // 512 by 256 division.\n ///////////////////////////////////////////////\n\n // Make division exact by subtracting the remainder from [prod1 prod0].\n uint256 remainder;\n assembly {\n // Compute remainder using mulmod.\n remainder := mulmod(x, y, denominator)\n\n // Subtract 256 bit number from 512 bit number.\n prod1 := sub(prod1, gt(remainder, prod0))\n prod0 := sub(prod0, remainder)\n }\n\n // Factor powers of two out of denominator and compute largest power of two divisor of denominator. Always \u003e= 1.\n // See https://cs.stackexchange.com/q/138556/92363.\n\n // Does not overflow because the denominator cannot be zero at this stage in the function.\n uint256 twos = denominator \u0026 (~denominator + 1);\n assembly {\n // Divide denominator by twos.\n denominator := div(denominator, twos)\n\n // Divide [prod1 prod0] by twos.\n prod0 := div(prod0, twos)\n\n // Flip twos such that it is 2^256 / twos. If twos is zero, then it becomes one.\n twos := add(div(sub(0, twos), twos), 1)\n }\n\n // Shift in bits from prod1 into prod0.\n prod0 |= prod1 * twos;\n\n // Invert denominator mod 2^256. Now that denominator is an odd number, it has an inverse modulo 2^256 such\n // that denominator * inv = 1 mod 2^256. Compute the inverse by starting with a seed that is correct for\n // four bits. That is, denominator * inv = 1 mod 2^4.\n uint256 inverse = (3 * denominator) ^ 2;\n\n // Use the Newton-Raphson iteration to improve the precision. Thanks to Hensel's lifting lemma, this also works\n // in modular arithmetic, doubling the correct bits in each step.\n inverse *= 2 - denominator * inverse; // inverse mod 2^8\n inverse *= 2 - denominator * inverse; // inverse mod 2^16\n inverse *= 2 - denominator * inverse; // inverse mod 2^32\n inverse *= 2 - denominator * inverse; // inverse mod 2^64\n inverse *= 2 - denominator * inverse; // inverse mod 2^128\n inverse *= 2 - denominator * inverse; // inverse mod 2^256\n\n // Because the division is now exact we can divide by multiplying with the modular inverse of denominator.\n // This will give us the correct result modulo 2^256. Since the preconditions guarantee that the outcome is\n // less than 2^256, this is the final result. We don't need to compute the high bits of the result and prod1\n // is no longer required.\n result = prod0 * inverse;\n return result;\n }\n }\n\n /**\n * @notice Calculates x * y / denominator with full precision, following the selected rounding direction.\n */\n function mulDiv(uint256 x, uint256 y, uint256 denominator, Rounding rounding) internal pure returns (uint256) {\n uint256 result = mulDiv(x, y, denominator);\n if (rounding == Rounding.Up \u0026\u0026 mulmod(x, y, denominator) \u003e 0) {\n result += 1;\n }\n return result;\n }\n\n /**\n * @dev Returns the square root of a number. If the number is not a perfect square, the value is rounded down.\n *\n * Inspired by Henry S. Warren, Jr.'s \"Hacker's Delight\" (Chapter 11).\n */\n function sqrt(uint256 a) internal pure returns (uint256) {\n if (a == 0) {\n return 0;\n }\n\n // For our first guess, we get the biggest power of 2 which is smaller than the square root of the target.\n //\n // We know that the \"msb\" (most significant bit) of our target number `a` is a power of 2 such that we have\n // `msb(a) \u003c= a \u003c 2*msb(a)`. This value can be written `msb(a)=2**k` with `k=log2(a)`.\n //\n // This can be rewritten `2**log2(a) \u003c= a \u003c 2**(log2(a) + 1)`\n // → `sqrt(2**k) \u003c= sqrt(a) \u003c sqrt(2**(k+1))`\n // → `2**(k/2) \u003c= sqrt(a) \u003c 2**((k+1)/2) \u003c= 2**(k/2 + 1)`\n //\n // Consequently, `2**(log2(a) / 2)` is a good first approximation of `sqrt(a)` with at least 1 correct bit.\n uint256 result = 1 \u003c\u003c (log2(a) \u003e\u003e 1);\n\n // At this point `result` is an estimation with one bit of precision. We know the true value is a uint128,\n // since it is the square root of a uint256. Newton's method converges quadratically (precision doubles at\n // every iteration). We thus need at most 7 iteration to turn our partial result with one bit of precision\n // into the expected uint128 result.\n unchecked {\n result = (result + a / result) \u003e\u003e 1;\n result = (result + a / result) \u003e\u003e 1;\n result = (result + a / result) \u003e\u003e 1;\n result = (result + a / result) \u003e\u003e 1;\n result = (result + a / result) \u003e\u003e 1;\n result = (result + a / result) \u003e\u003e 1;\n result = (result + a / result) \u003e\u003e 1;\n return min(result, a / result);\n }\n }\n\n /**\n * @notice Calculates sqrt(a), following the selected rounding direction.\n */\n function sqrt(uint256 a, Rounding rounding) internal pure returns (uint256) {\n unchecked {\n uint256 result = sqrt(a);\n return result + (rounding == Rounding.Up \u0026\u0026 result * result \u003c a ? 1 : 0);\n }\n }\n\n /**\n * @dev Return the log in base 2, rounded down, of a positive value.\n * Returns 0 if given 0.\n */\n function log2(uint256 value) internal pure returns (uint256) {\n uint256 result = 0;\n unchecked {\n if (value \u003e\u003e 128 \u003e 0) {\n value \u003e\u003e= 128;\n result += 128;\n }\n if (value \u003e\u003e 64 \u003e 0) {\n value \u003e\u003e= 64;\n result += 64;\n }\n if (value \u003e\u003e 32 \u003e 0) {\n value \u003e\u003e= 32;\n result += 32;\n }\n if (value \u003e\u003e 16 \u003e 0) {\n value \u003e\u003e= 16;\n result += 16;\n }\n if (value \u003e\u003e 8 \u003e 0) {\n value \u003e\u003e= 8;\n result += 8;\n }\n if (value \u003e\u003e 4 \u003e 0) {\n value \u003e\u003e= 4;\n result += 4;\n }\n if (value \u003e\u003e 2 \u003e 0) {\n value \u003e\u003e= 2;\n result += 2;\n }\n if (value \u003e\u003e 1 \u003e 0) {\n result += 1;\n }\n }\n return result;\n }\n\n /**\n * @dev Return the log in base 2, following the selected rounding direction, of a positive value.\n * Returns 0 if given 0.\n */\n function log2(uint256 value, Rounding rounding) internal pure returns (uint256) {\n unchecked {\n uint256 result = log2(value);\n return result + (rounding == Rounding.Up \u0026\u0026 1 \u003c\u003c result \u003c value ? 1 : 0);\n }\n }\n\n /**\n * @dev Return the log in base 10, rounded down, of a positive value.\n * Returns 0 if given 0.\n */\n function log10(uint256 value) internal pure returns (uint256) {\n uint256 result = 0;\n unchecked {\n if (value \u003e= 10 ** 64) {\n value /= 10 ** 64;\n result += 64;\n }\n if (value \u003e= 10 ** 32) {\n value /= 10 ** 32;\n result += 32;\n }\n if (value \u003e= 10 ** 16) {\n value /= 10 ** 16;\n result += 16;\n }\n if (value \u003e= 10 ** 8) {\n value /= 10 ** 8;\n result += 8;\n }\n if (value \u003e= 10 ** 4) {\n value /= 10 ** 4;\n result += 4;\n }\n if (value \u003e= 10 ** 2) {\n value /= 10 ** 2;\n result += 2;\n }\n if (value \u003e= 10 ** 1) {\n result += 1;\n }\n }\n return result;\n }\n\n /**\n * @dev Return the log in base 10, following the selected rounding direction, of a positive value.\n * Returns 0 if given 0.\n */\n function log10(uint256 value, Rounding rounding) internal pure returns (uint256) {\n unchecked {\n uint256 result = log10(value);\n return result + (rounding == Rounding.Up \u0026\u0026 10 ** result \u003c value ? 1 : 0);\n }\n }\n\n /**\n * @dev Return the log in base 256, rounded down, of a positive value.\n * Returns 0 if given 0.\n *\n * Adding one to the result gives the number of pairs of hex symbols needed to represent `value` as a hex string.\n */\n function log256(uint256 value) internal pure returns (uint256) {\n uint256 result = 0;\n unchecked {\n if (value \u003e\u003e 128 \u003e 0) {\n value \u003e\u003e= 128;\n result += 16;\n }\n if (value \u003e\u003e 64 \u003e 0) {\n value \u003e\u003e= 64;\n result += 8;\n }\n if (value \u003e\u003e 32 \u003e 0) {\n value \u003e\u003e= 32;\n result += 4;\n }\n if (value \u003e\u003e 16 \u003e 0) {\n value \u003e\u003e= 16;\n result += 2;\n }\n if (value \u003e\u003e 8 \u003e 0) {\n result += 1;\n }\n }\n return result;\n }\n\n /**\n * @dev Return the log in base 256, following the selected rounding direction, of a positive value.\n * Returns 0 if given 0.\n */\n function log256(uint256 value, Rounding rounding) internal pure returns (uint256) {\n unchecked {\n uint256 result = log256(value);\n return result + (rounding == Rounding.Up \u0026\u0026 1 \u003c\u003c (result \u003c\u003c 3) \u003c value ? 1 : 0);\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/utils/math/SignedMath.sol\n\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/math/SignedMath.sol)\n\n/**\n * @dev Standard signed math utilities missing in the Solidity language.\n */\nlibrary SignedMath {\n /**\n * @dev Returns the largest of two signed numbers.\n */\n function max(int256 a, int256 b) internal pure returns (int256) {\n return a \u003e b ? a : b;\n }\n\n /**\n * @dev Returns the smallest of two signed numbers.\n */\n function min(int256 a, int256 b) internal pure returns (int256) {\n return a \u003c b ? a : b;\n }\n\n /**\n * @dev Returns the average of two signed numbers without overflow.\n * The result is rounded towards zero.\n */\n function average(int256 a, int256 b) internal pure returns (int256) {\n // Formula from the book \"Hacker's Delight\"\n int256 x = (a \u0026 b) + ((a ^ b) \u003e\u003e 1);\n return x + (int256(uint256(x) \u003e\u003e 255) \u0026 (a ^ b));\n }\n\n /**\n * @dev Returns the absolute unsigned value of a signed value.\n */\n function abs(int256 n) internal pure returns (uint256) {\n unchecked {\n // must be unchecked in order to support `n = type(int256).min`\n return uint256(n \u003e= 0 ? n : -n);\n }\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// 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/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/InterfaceSummit.sol\n\ninterface InterfaceSummit {\n // ══════════════════════════════════════════ ACCEPT AGENT STATEMENTS ══════════════════════════════════════════════\n\n /**\n * @notice Accepts a receipt, which local `AgentManager` verified to have been signed by an active Notary.\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 * - Notary who signed the receipt is referenced as the \"Receipt Notary\".\n * - Notary who signed the attestation on destination chain is referenced as the \"Attestation Notary\".\n * \u003e Will revert if any of these is true:\n * \u003e - Called by anyone other than local `AgentManager`.\n * \u003e - Receipt body payload is not properly formatted.\n * \u003e - Receipt signer is in Dispute.\n * \u003e - Receipt's snapshot root is unknown.\n * @param rcptNotaryIndex Index of Receipt Notary in Agent Merkle Tree\n * @param attNotaryIndex Index of Attestation Notary in Agent Merkle Tree\n * @param sigIndex Index of stored Notary signature\n * @param attNonce Nonce of the attestation used for proving the executed message\n * @param paddedTips Padded encoded paid tips information\n * @param rcptPayload Raw payload with message execution receipt\n * @return wasAccepted Whether the receipt was accepted\n */\n function acceptReceipt(\n uint32 rcptNotaryIndex,\n uint32 attNotaryIndex,\n uint256 sigIndex,\n uint32 attNonce,\n uint256 paddedTips,\n bytes memory rcptPayload\n ) external returns (bool wasAccepted);\n\n /**\n * @notice Accepts a snapshot, which local `AgentManager` verified to have been signed by an active Guard.\n * \u003e Snapshot is a list of states for a set of Origin contracts residing on any of the chains.\n * All the states in the Guard-signed snapshot become available for Notary signing.\n * \u003e Will revert if any of these is true:\n * \u003e - Called by anyone other than local `AgentManager`.\n * \u003e - Snapshot payload is not properly formatted.\n * \u003e - Snapshot contains a state older then the Guard has previously submitted.\n * @param guardIndex Index of Guard in Agent Merkle Tree\n * @param sigIndex Index of stored Agent signature\n * @param snapPayload Raw payload with snapshot data\n */\n function acceptGuardSnapshot(uint32 guardIndex, uint256 sigIndex, bytes memory snapPayload) external;\n\n /**\n * @notice Accepts a snapshot, which local `AgentManager` verified to have been signed by an active Notary.\n * \u003e Snapshot is a list of states for a set of Origin contracts residing on any of the chains.\n * Snapshot Merkle Root is calculated and saved for valid snapshots, i.e.\n * snapshots which are only using states previously submitted by any of the Guards.\n * - Notary could use states singed by the same of different Guards 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 - Called by anyone other than local `AgentManager`.\n * \u003e - Snapshot payload is not properly formatted.\n * \u003e - Snapshot contains a state older then the Notary has previously submitted.\n * \u003e - Snapshot contains a state that no Guard has previously submitted.\n * @param notaryIndex Index of Notary in Agent Merkle Tree\n * @param sigIndex Index of stored Agent signature\n * @param agentRoot Current root of the Agent Merkle Tree\n * @param snapPayload Raw payload with snapshot data\n * @return attPayload Raw payload with data for attestation derived from Notary snapshot.\n */\n function acceptNotarySnapshot(uint32 notaryIndex, uint256 sigIndex, bytes32 agentRoot, bytes memory snapPayload)\n external\n returns (bytes memory attPayload);\n\n // ════════════════════════════════════════════════ TIPS LOGIC ═════════════════════════════════════════════════════\n\n /**\n * @notice Distributes tips using the first Receipt from the \"receipt quarantine queue\".\n * Possible scenarios:\n * - Receipt queue is empty =\u003e does nothing\n * - Receipt optimistic period is not over =\u003e does nothing\n * - Either of Notaries present in Receipt was slashed =\u003e receipt is deleted from the queue\n * - Either of Notaries present in Receipt in Dispute =\u003e receipt is moved to the end of queue\n * - None of the above =\u003e receipt tips are distributed\n * @dev Returned value makes it possible to do the following: `while (distributeTips()) {}`\n * @return queuePopped Whether the first element was popped from the queue\n */\n function distributeTips() external returns (bool queuePopped);\n\n /**\n * @notice Withdraws locked base message tips from requested domain Origin to the recipient.\n * This is done by a call to a local Origin contract, or by a manager message to the remote chain.\n * @dev This will revert, if the pending balance of origin tips (earned-claimed) is lower than requested.\n * @param origin Domain of chain to withdraw tips on\n * @param amount Amount of tips to withdraw\n */\n function withdrawTips(uint32 origin, uint256 amount) external;\n\n // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════\n\n /**\n * @notice Returns earned and claimed tips for the actor.\n * Note: Tips for address(0) belong to the Treasury.\n * @param actor Address of the actor\n * @param origin Domain where the tips were initially paid\n * @return earned Total amount of origin tips the actor has earned so far\n * @return claimed Total amount of origin tips the actor has claimed so far\n */\n function actorTips(address actor, uint32 origin) external view returns (uint128 earned, uint128 claimed);\n\n /**\n * @notice Returns the amount of receipts in the \"Receipt Quarantine Queue\".\n */\n function receiptQueueLength() external view returns (uint256);\n\n /**\n * @notice Returns the state with the highest known nonce\n * submitted by any of the currently active Guards.\n * @param origin Domain of origin chain\n * @return statePayload Raw payload with latest active Guard state for origin\n */\n function getLatestState(uint32 origin) external view returns (bytes memory statePayload);\n}\n\n// node_modules/@openzeppelin/contracts/utils/Strings.sol\n\n// OpenZeppelin Contracts (last updated v4.9.0) (utils/Strings.sol)\n\n/**\n * @dev String operations.\n */\nlibrary Strings {\n bytes16 private constant _SYMBOLS = \"0123456789abcdef\";\n uint8 private constant _ADDRESS_LENGTH = 20;\n\n /**\n * @dev Converts a `uint256` to its ASCII `string` decimal representation.\n */\n function toString(uint256 value) internal pure returns (string memory) {\n unchecked {\n uint256 length = Math.log10(value) + 1;\n string memory buffer = new string(length);\n uint256 ptr;\n /// @solidity memory-safe-assembly\n assembly {\n ptr := add(buffer, add(32, length))\n }\n while (true) {\n ptr--;\n /// @solidity memory-safe-assembly\n assembly {\n mstore8(ptr, byte(mod(value, 10), _SYMBOLS))\n }\n value /= 10;\n if (value == 0) break;\n }\n return buffer;\n }\n }\n\n /**\n * @dev Converts a `int256` to its ASCII `string` decimal representation.\n */\n function toString(int256 value) internal pure returns (string memory) {\n return string(abi.encodePacked(value \u003c 0 ? \"-\" : \"\", toString(SignedMath.abs(value))));\n }\n\n /**\n * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation.\n */\n function toHexString(uint256 value) internal pure returns (string memory) {\n unchecked {\n return toHexString(value, Math.log256(value) + 1);\n }\n }\n\n /**\n * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length.\n */\n function toHexString(uint256 value, uint256 length) internal pure returns (string memory) {\n bytes memory buffer = new bytes(2 * length + 2);\n buffer[0] = \"0\";\n buffer[1] = \"x\";\n for (uint256 i = 2 * length + 1; i \u003e 1; --i) {\n buffer[i] = _SYMBOLS[value \u0026 0xf];\n value \u003e\u003e= 4;\n }\n require(value == 0, \"Strings: hex length insufficient\");\n return string(buffer);\n }\n\n /**\n * @dev Converts an `address` with fixed length of 20 bytes to its not checksummed ASCII `string` hexadecimal representation.\n */\n function toHexString(address addr) internal pure returns (string memory) {\n return toHexString(uint256(uint160(addr)), _ADDRESS_LENGTH);\n }\n\n /**\n * @dev Returns true if the two strings are equal.\n */\n function equal(string memory a, string memory b) internal pure returns (bool) {\n return keccak256(bytes(a)) == keccak256(bytes(b));\n }\n}\n\n// node_modules/@openzeppelin/contracts-upgradeable/utils/ContextUpgradeable.sol\n\n// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)\n\n/**\n * @dev Provides information about the current execution context, including the\n * sender of the transaction and its data. While these are generally available\n * via msg.sender and msg.data, they should not be accessed in such a direct\n * manner, since when dealing with meta-transactions the account sending and\n * paying for execution may not be the actual sender (as far as an application\n * is concerned).\n *\n * This contract is only required for intermediate, library-like contracts.\n */\nabstract contract ContextUpgradeable is Initializable {\n function __Context_init() internal onlyInitializing {\n }\n\n function __Context_init_unchained() internal onlyInitializing {\n }\n function _msgSender() internal view virtual returns (address) {\n return msg.sender;\n }\n\n function _msgData() internal view virtual returns (bytes calldata) {\n return msg.data;\n }\n\n /**\n * @dev This empty reserved space is put in place to allow future versions to add new\n * variables without shifting down storage in the inheritance chain.\n * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\n */\n uint256[50] private __gap;\n}\n\n// contracts/libs/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/utils/cryptography/ECDSA.sol\n\n// OpenZeppelin Contracts (last updated v4.9.0) (utils/cryptography/ECDSA.sol)\n\n/**\n * @dev Elliptic Curve Digital Signature Algorithm (ECDSA) operations.\n *\n * These functions can be used to verify that a message was signed by the holder\n * of the private keys of a given address.\n */\nlibrary ECDSA {\n enum RecoverError {\n NoError,\n InvalidSignature,\n InvalidSignatureLength,\n InvalidSignatureS,\n InvalidSignatureV // Deprecated in v4.8\n }\n\n function _throwError(RecoverError error) private pure {\n if (error == RecoverError.NoError) {\n return; // no error: do nothing\n } else if (error == RecoverError.InvalidSignature) {\n revert(\"ECDSA: invalid signature\");\n } else if (error == RecoverError.InvalidSignatureLength) {\n revert(\"ECDSA: invalid signature length\");\n } else if (error == RecoverError.InvalidSignatureS) {\n revert(\"ECDSA: invalid signature 's' value\");\n }\n }\n\n /**\n * @dev Returns the address that signed a hashed message (`hash`) with\n * `signature` or error string. This address can then be used for verification purposes.\n *\n * The `ecrecover` EVM opcode allows for malleable (non-unique) signatures:\n * this function rejects them by requiring the `s` value to be in the lower\n * half order, and the `v` value to be either 27 or 28.\n *\n * IMPORTANT: `hash` _must_ be the result of a hash operation for the\n * verification to be secure: it is possible to craft signatures that\n * recover to arbitrary addresses for non-hashed data. A safe way to ensure\n * this is by receiving a hash of the original message (which may otherwise\n * be too long), and then calling {toEthSignedMessageHash} on it.\n *\n * Documentation for signature generation:\n * - with https://web3js.readthedocs.io/en/v1.3.4/web3-eth-accounts.html#sign[Web3.js]\n * - with https://docs.ethers.io/v5/api/signer/#Signer-signMessage[ethers]\n *\n * _Available since v4.3._\n */\n function tryRecover(bytes32 hash, bytes memory signature) internal pure returns (address, RecoverError) {\n if (signature.length == 65) {\n bytes32 r;\n bytes32 s;\n uint8 v;\n // ecrecover takes the signature parameters, and the only way to get them\n // currently is to use assembly.\n /// @solidity memory-safe-assembly\n assembly {\n r := mload(add(signature, 0x20))\n s := mload(add(signature, 0x40))\n v := byte(0, mload(add(signature, 0x60)))\n }\n return tryRecover(hash, v, r, s);\n } else {\n return (address(0), RecoverError.InvalidSignatureLength);\n }\n }\n\n /**\n * @dev Returns the address that signed a hashed message (`hash`) with\n * `signature`. This address can then be used for verification purposes.\n *\n * The `ecrecover` EVM opcode allows for malleable (non-unique) signatures:\n * this function rejects them by requiring the `s` value to be in the lower\n * half order, and the `v` value to be either 27 or 28.\n *\n * IMPORTANT: `hash` _must_ be the result of a hash operation for the\n * verification to be secure: it is possible to craft signatures that\n * recover to arbitrary addresses for non-hashed data. A safe way to ensure\n * this is by receiving a hash of the original message (which may otherwise\n * be too long), and then calling {toEthSignedMessageHash} on it.\n */\n function recover(bytes32 hash, bytes memory signature) internal pure returns (address) {\n (address recovered, RecoverError error) = tryRecover(hash, signature);\n _throwError(error);\n return recovered;\n }\n\n /**\n * @dev Overload of {ECDSA-tryRecover} that receives the `r` and `vs` short-signature fields separately.\n *\n * See https://eips.ethereum.org/EIPS/eip-2098[EIP-2098 short signatures]\n *\n * _Available since v4.3._\n */\n function tryRecover(bytes32 hash, bytes32 r, bytes32 vs) internal pure returns (address, RecoverError) {\n bytes32 s = vs \u0026 bytes32(0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff);\n uint8 v = uint8((uint256(vs) \u003e\u003e 255) + 27);\n return tryRecover(hash, v, r, s);\n }\n\n /**\n * @dev Overload of {ECDSA-recover} that receives the `r and `vs` short-signature fields separately.\n *\n * _Available since v4.2._\n */\n function recover(bytes32 hash, bytes32 r, bytes32 vs) internal pure returns (address) {\n (address recovered, RecoverError error) = tryRecover(hash, r, vs);\n _throwError(error);\n return recovered;\n }\n\n /**\n * @dev Overload of {ECDSA-tryRecover} that receives the `v`,\n * `r` and `s` signature fields separately.\n *\n * _Available since v4.3._\n */\n function tryRecover(bytes32 hash, uint8 v, bytes32 r, bytes32 s) internal pure returns (address, RecoverError) {\n // EIP-2 still allows signature malleability for ecrecover(). Remove this possibility and make the signature\n // unique. Appendix F in the Ethereum Yellow paper (https://ethereum.github.io/yellowpaper/paper.pdf), defines\n // the valid range for s in (301): 0 \u003c s \u003c secp256k1n ÷ 2 + 1, and for v in (302): v ∈ {27, 28}. Most\n // signatures from current libraries generate a unique signature with an s-value in the lower half order.\n //\n // If your library generates malleable signatures, such as s-values in the upper range, calculate a new s-value\n // with 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141 - s1 and flip v from 27 to 28 or\n // vice versa. If your library also generates signatures with 0/1 for v instead 27/28, add 27 to v to accept\n // these malleable signatures as well.\n if (uint256(s) \u003e 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0) {\n return (address(0), RecoverError.InvalidSignatureS);\n }\n\n // If the signature is valid (and not malleable), return the signer address\n address signer = ecrecover(hash, v, r, s);\n if (signer == address(0)) {\n return (address(0), RecoverError.InvalidSignature);\n }\n\n return (signer, RecoverError.NoError);\n }\n\n /**\n * @dev Overload of {ECDSA-recover} that receives the `v`,\n * `r` and `s` signature fields separately.\n */\n function recover(bytes32 hash, uint8 v, bytes32 r, bytes32 s) internal pure returns (address) {\n (address recovered, RecoverError error) = tryRecover(hash, v, r, s);\n _throwError(error);\n return recovered;\n }\n\n /**\n * @dev Returns an Ethereum Signed Message, created from a `hash`. This\n * produces hash corresponding to the one signed with the\n * https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`]\n * JSON-RPC method as part of EIP-191.\n *\n * See {recover}.\n */\n function toEthSignedMessageHash(bytes32 hash) internal pure returns (bytes32 message) {\n // 32 is the length in bytes of hash,\n // enforced by the type signature above\n /// @solidity memory-safe-assembly\n assembly {\n mstore(0x00, \"\\x19Ethereum Signed Message:\\n32\")\n mstore(0x1c, hash)\n message := keccak256(0x00, 0x3c)\n }\n }\n\n /**\n * @dev Returns an Ethereum Signed Message, created from `s`. This\n * produces hash corresponding to the one signed with the\n * https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`]\n * JSON-RPC method as part of EIP-191.\n *\n * See {recover}.\n */\n function toEthSignedMessageHash(bytes memory s) internal pure returns (bytes32) {\n return keccak256(abi.encodePacked(\"\\x19Ethereum Signed Message:\\n\", Strings.toString(s.length), s));\n }\n\n /**\n * @dev Returns an Ethereum Signed Typed Data, created from a\n * `domainSeparator` and a `structHash`. This produces hash corresponding\n * to the one signed with the\n * https://eips.ethereum.org/EIPS/eip-712[`eth_signTypedData`]\n * JSON-RPC method as part of EIP-712.\n *\n * See {recover}.\n */\n function toTypedDataHash(bytes32 domainSeparator, bytes32 structHash) internal pure returns (bytes32 data) {\n /// @solidity memory-safe-assembly\n assembly {\n let ptr := mload(0x40)\n mstore(ptr, \"\\x19\\x01\")\n mstore(add(ptr, 0x02), domainSeparator)\n mstore(add(ptr, 0x22), structHash)\n data := keccak256(ptr, 0x42)\n }\n }\n\n /**\n * @dev Returns an Ethereum Signed Data with intended validator, created from a\n * `validator` and `data` according to the version 0 of EIP-191.\n *\n * See {recover}.\n */\n function toDataWithIntendedValidatorHash(address validator, bytes memory data) internal pure returns (bytes32) {\n return keccak256(abi.encodePacked(\"\\x19\\x00\", validator, data));\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/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/inbox/StatementInbox.sol\n\n// ══════════════════════════════ LIBRARY IMPORTS ══════════════════════════════\n\n// ═════════════════════════════ INTERNAL IMPORTS ══════════════════════════════\n\n// ═════════════════════════════ EXTERNAL IMPORTS ══════════════════════════════\n\n/// @notice `StatementInbox` is the entry point for all agent-signed statements. It verifies the\n/// agent signatures, and passes the unsigned statements to the contract to consume it via `acceptX` functions. Is is\n/// also used to verify the agent-signed statements and initiate the agent slashing, should the statement be invalid.\n/// `StatementInbox` is responsible for the following:\n/// - Accepting State and Receipt Reports to initiate a dispute between Guard and Notary.\n/// - Storing all the Guard Reports with the Guard signature leading to a dispute.\n/// - Verifying State/State Reports referencing the local chain and slashing the signer if statement is invalid.\n/// - Verifying Receipt/Receipt Reports referencing the local chain and slashing the signer if statement is invalid.\nabstract contract StatementInbox is MessagingBase, StatementInboxEvents, IStatementInbox {\n using AttestationLib for bytes;\n using ReceiptLib for bytes;\n using StateLib for bytes;\n using SnapshotLib for bytes;\n\n struct StoredReport {\n uint256 sigIndex;\n bytes statementPayload;\n }\n\n // ══════════════════════════════════════════════════ STORAGE ══════════════════════════════════════════════════════\n\n address public agentManager;\n address public origin;\n address public destination;\n\n // TODO: optimize this\n bytes[] internal _storedSignatures;\n StoredReport[] internal _storedReports;\n\n /// @dev gap for upgrade safety\n uint256[45] private __GAP; // solhint-disable-line var-name-mixedcase\n\n // ════════════════════════════════════════════════ INITIALIZER ════════════════════════════════════════════════════\n\n /// @dev Initializes the contract:\n /// - Sets up `msg.sender` as the owner of the contract.\n /// - Sets up `agentManager`, `origin`, and `destination`.\n // solhint-disable-next-line func-name-mixedcase\n function __StatementInbox_init(address agentManager_, address origin_, address destination_)\n internal\n onlyInitializing\n {\n agentManager = agentManager_;\n origin = origin_;\n destination = destination_;\n __Ownable2Step_init();\n }\n\n // ══════════════════════════════════════════ SUBMIT AGENT STATEMENTS ══════════════════════════════════════════════\n\n /// @inheritdoc IStatementInbox\n // solhint-disable-next-line ordering\n function submitStateReportWithSnapshot(\n uint8 stateIndex,\n bytes memory srSignature,\n bytes memory snapPayload,\n bytes memory snapSignature\n ) external returns (bool wasAccepted) {\n // This will revert if payload is not a snapshot\n Snapshot snapshot = snapPayload.castToSnapshot();\n // This will revert if the snapshot signer is not a known Notary\n (AgentStatus memory notaryStatus,) =\n _verifySnapshot({snapshot: snapshot, snapSignature: snapSignature, verifyNotary: true});\n // Notary needs to be Active/Unstaking\n notaryStatus.verifyActiveUnstaking();\n // Check if Notary is active on this chain\n _verifyNotaryDomain(notaryStatus.domain);\n // This will revert if state index is out of range\n State state = snapshot.state(stateIndex);\n // This will revert if the report signer is not an known Guard\n (AgentStatus memory guardStatus,) = _verifyStateReport(state, srSignature);\n // Check that Guard is active\n guardStatus.verifyActive();\n _saveReport(state.unwrap().clone(), srSignature);\n // This will revert if either actor is already in dispute\n IAgentManager(agentManager).openDispute(guardStatus.index, notaryStatus.index);\n return true;\n }\n\n /// @inheritdoc IStatementInbox\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 // This will revert if payload is not a snapshot\n Snapshot snapshot = snapPayload.castToSnapshot();\n // This will revert if state index is out of range\n State state = snapshot.state(stateIndex);\n // This will revert if the report signer is not an known Guard\n (AgentStatus memory guardStatus,) = _verifyStateReport(state, srSignature);\n // Check that Guard is active\n guardStatus.verifyActive();\n // This will revert if payload is not an attestation\n Attestation att = attPayload.castToAttestation();\n // This will revert if signer is not an known Notary\n (AgentStatus memory notaryStatus,) = _verifyAttestation(att, attSignature);\n // Notary needs to be Active/Unstaking\n notaryStatus.verifyActiveUnstaking();\n // Check if Notary is active on this chain\n _verifyNotaryDomain(notaryStatus.domain);\n if (snapshot.calculateRoot() != att.snapRoot()) revert IncorrectSnapshotRoot();\n _saveReport(state.unwrap().clone(), srSignature);\n // This will revert if either actor is already in dispute\n IAgentManager(agentManager).openDispute(guardStatus.index, notaryStatus.index);\n return true;\n }\n\n /// @inheritdoc IStatementInbox\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 // This will revert if payload is not a state\n State state = statePayload.castToState();\n // This will revert if the report signer is not an known Guard\n (AgentStatus memory guardStatus,) = _verifyStateReport(state, srSignature);\n // Check that Guard is active\n guardStatus.verifyActive();\n // This will revert if payload is not an attestation\n Attestation att = attPayload.castToAttestation();\n // This will revert if signer is not a known Notary\n (AgentStatus memory notaryStatus,) = _verifyAttestation(att, attSignature);\n // Notary needs to be Active/Unstaking\n notaryStatus.verifyActiveUnstaking();\n // Check if Notary is active on this chain\n _verifyNotaryDomain(notaryStatus.domain);\n // This will revert if any of these is true:\n // - Attestation root is not equal to Merkle Root derived from State and Snapshot Proof.\n // - Snapshot Proof's first element does not match the State metadata.\n // - Snapshot Proof length exceeds Snapshot tree Height.\n // - State index is out of range.\n _verifySnapshotMerkle(att, stateIndex, state, snapProof);\n _saveReport(statePayload, srSignature);\n // This will revert if either actor is already in dispute\n IAgentManager(agentManager).openDispute(guardStatus.index, notaryStatus.index);\n return true;\n }\n\n // ══════════════════════════════════════════ VERIFY AGENT STATEMENTS ══════════════════════════════════════════════\n\n /// @inheritdoc IStatementInbox\n function verifyReceipt(bytes memory rcptPayload, bytes memory rcptSignature)\n external\n returns (bool isValidReceipt)\n {\n // This will revert if payload is not a receipt\n Receipt rcpt = rcptPayload.castToReceipt();\n // This will revert if the attestation signer is not a known Notary\n (AgentStatus memory status, address notary) = _verifyReceipt(rcpt, rcptSignature);\n // Notary needs to be Active/Unstaking\n status.verifyActiveUnstaking();\n isValidReceipt = IExecutionHub(destination).isValidReceipt(rcptPayload);\n if (!isValidReceipt) {\n emit InvalidReceipt(rcptPayload, rcptSignature);\n IAgentManager(agentManager).slashAgent(status.domain, notary, msg.sender);\n }\n }\n\n /// @inheritdoc IStatementInbox\n function verifyReceiptReport(bytes memory rcptPayload, bytes memory rrSignature)\n external\n returns (bool isValidReport)\n {\n // This will revert if payload is not a receipt\n Receipt rcpt = rcptPayload.castToReceipt();\n // This will revert if the report signer is not a known Guard\n (AgentStatus memory status, address guard) = _verifyReceiptReport(rcpt, rrSignature);\n // Guard needs to be Active/Unstaking\n status.verifyActiveUnstaking();\n // Report is valid IF AND ONLY IF the reported receipt in invalid\n isValidReport = !IExecutionHub(destination).isValidReceipt(rcptPayload);\n if (!isValidReport) {\n emit InvalidReceiptReport(rcptPayload, rrSignature);\n IAgentManager(agentManager).slashAgent(status.domain, guard, msg.sender);\n }\n }\n\n /// @inheritdoc IStatementInbox\n function verifyStateWithAttestation(\n uint8 stateIndex,\n bytes memory snapPayload,\n bytes memory attPayload,\n bytes memory attSignature\n ) external returns (bool isValidState) {\n // This will revert if payload is not an attestation\n Attestation att = attPayload.castToAttestation();\n // This will revert if the attestation signer is not a known Notary\n (AgentStatus memory status, address notary) = _verifyAttestation(att, attSignature);\n // Notary needs to be Active/Unstaking\n status.verifyActiveUnstaking();\n // This will revert if payload is not a snapshot\n Snapshot snapshot = snapPayload.castToSnapshot();\n if (snapshot.calculateRoot() != att.snapRoot()) revert IncorrectSnapshotRoot();\n // This will revert if state does not refer to this chain\n bytes memory statePayload = snapshot.state(stateIndex).unwrap().clone();\n isValidState = IStateHub(origin).isValidState(statePayload);\n if (!isValidState) {\n emit InvalidStateWithAttestation(stateIndex, statePayload, attPayload, attSignature);\n IAgentManager(agentManager).slashAgent(status.domain, notary, msg.sender);\n }\n }\n\n /// @inheritdoc IStatementInbox\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 // This will revert if payload is not an attestation\n Attestation att = attPayload.castToAttestation();\n // This will revert if the attestation signer is not a known Notary\n (AgentStatus memory status, address notary) = _verifyAttestation(att, attSignature);\n // Notary needs to be Active/Unstaking\n status.verifyActiveUnstaking();\n // This will revert if payload is not a state\n State state = statePayload.castToState();\n // This will revert if any of these is true:\n // - Attestation root is not equal to Merkle Root derived from State and Snapshot Proof.\n // - Snapshot Proof's first element does not match the State metadata.\n // - Snapshot Proof length exceeds Snapshot tree Height.\n // - State index is out of range.\n _verifySnapshotMerkle(att, stateIndex, state, snapProof);\n // This will revert if state does not refer to this chain\n isValidState = IStateHub(origin).isValidState(statePayload);\n if (!isValidState) {\n emit InvalidStateWithAttestation(stateIndex, statePayload, attPayload, attSignature);\n IAgentManager(agentManager).slashAgent(status.domain, notary, msg.sender);\n }\n }\n\n /// @inheritdoc IStatementInbox\n function verifyStateWithSnapshot(uint8 stateIndex, bytes memory snapPayload, bytes memory snapSignature)\n external\n returns (bool isValidState)\n {\n // This will revert if payload is not a snapshot\n Snapshot snapshot = snapPayload.castToSnapshot();\n // This will revert if the snapshot signer is not a known Guard/Notary\n (AgentStatus memory status, address agent) =\n _verifySnapshot({snapshot: snapshot, snapSignature: snapSignature, verifyNotary: false});\n // Agent needs to be Active/Unstaking\n status.verifyActiveUnstaking();\n // This will revert if state does not refer to this chain\n isValidState = IStateHub(origin).isValidState(snapshot.state(stateIndex).unwrap().clone());\n if (!isValidState) {\n emit InvalidStateWithSnapshot(stateIndex, snapPayload, snapSignature);\n IAgentManager(agentManager).slashAgent(status.domain, agent, msg.sender);\n }\n }\n\n /// @inheritdoc IStatementInbox\n function verifyStateReport(bytes memory statePayload, bytes memory srSignature)\n external\n returns (bool isValidReport)\n {\n // This will revert if payload is not a state\n State state = statePayload.castToState();\n // This will revert if the report signer is not a known Guard\n (AgentStatus memory status, address guard) = _verifyStateReport(state, srSignature);\n // Guard needs to be Active/Unstaking\n status.verifyActiveUnstaking();\n // Report is valid IF AND ONLY IF the reported state in invalid\n // This will revert if the reported state does not refer to this chain\n isValidReport = !IStateHub(origin).isValidState(statePayload);\n if (!isValidReport) {\n emit InvalidStateReport(statePayload, srSignature);\n IAgentManager(agentManager).slashAgent(status.domain, guard, msg.sender);\n }\n }\n\n // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════\n\n /// @inheritdoc IStatementInbox\n function getReportsAmount() external view returns (uint256) {\n return _storedReports.length;\n }\n\n /// @inheritdoc IStatementInbox\n function getGuardReport(uint256 index)\n external\n view\n returns (bytes memory statementPayload, bytes memory reportSignature)\n {\n if (index \u003e= _storedReports.length) revert IndexOutOfRange();\n StoredReport memory storedReport = _storedReports[index];\n statementPayload = storedReport.statementPayload;\n reportSignature = _storedSignatures[storedReport.sigIndex];\n }\n\n /// @inheritdoc IStatementInbox\n function getStoredSignature(uint256 index) external view returns (bytes memory) {\n return _storedSignatures[index];\n }\n\n // ══════════════════════════════════════════════ INTERNAL LOGIC ═══════════════════════════════════════════════════\n\n /// @dev Saves the statement reported by Guard as invalid and the Guard Report signature.\n function _saveReport(bytes memory statementPayload, bytes memory reportSignature) internal {\n uint256 sigIndex = _saveSignature(reportSignature);\n _storedReports.push(StoredReport(sigIndex, statementPayload));\n }\n\n /// @dev Saves the signature and returns its index.\n function _saveSignature(bytes memory signature) internal returns (uint256 sigIndex) {\n sigIndex = _storedSignatures.length;\n _storedSignatures.push(signature);\n }\n\n // ═══════════════════════════════════════════════ AGENT CHECKS ════════════════════════════════════════════════════\n\n /**\n * @dev Recovers a signer from a hashed message, and a EIP-191 signature for it.\n * Will revert, if the signer is not a known agent.\n * @dev Agent flag could be any of these: Active/Unstaking/Resting/Fraudulent/Slashed\n * Further checks need to be performed in a caller function.\n * @param hashedStatement Hash of the statement that was signed by an Agent\n * @param signature Agent signature for the hashed statement\n * @return status Struct representing agent status:\n * - flag Unknown/Active/Unstaking/Resting/Fraudulent/Slashed\n * - domain Domain where agent is/was active\n * - index Index of agent in the Agent Merkle Tree\n * @return agent Agent that signed the statement\n */\n function _recoverAgent(bytes32 hashedStatement, bytes memory signature)\n internal\n view\n returns (AgentStatus memory status, address agent)\n {\n bytes32 ethSignedMsg = ECDSA.toEthSignedMessageHash(hashedStatement);\n agent = ECDSA.recover(ethSignedMsg, signature);\n status = IAgentManager(agentManager).agentStatus(agent);\n // Discard signature of unknown agents.\n // Further flag checks are supposed to be performed in a caller function.\n status.verifyKnown();\n }\n\n /// @dev Verifies that Notary signature is active on local domain.\n function _verifyNotaryDomain(uint32 notaryDomain) internal view {\n // Notary needs to be from the local domain (if contract is not deployed on Synapse Chain).\n // Or Notary could be from any domain (if contract is deployed on Synapse Chain).\n if (notaryDomain != localDomain \u0026\u0026 localDomain != synapseDomain) revert IncorrectAgentDomain();\n }\n\n // ════════════════════════════════════════ ATTESTATION RELATED CHECKS ═════════════════════════════════════════════\n\n /**\n * @dev Internal function to verify the signed attestation payload.\n * Reverts if any of these is true:\n * - Attestation signer is not a known Notary.\n * @param att Typed memory view over attestation payload\n * @param attSignature Notary signature for the attestation\n * @return status Struct representing agent status, see {_recoverAgent}\n * @return notary Notary that signed the snapshot\n */\n function _verifyAttestation(Attestation att, bytes memory attSignature)\n internal\n view\n returns (AgentStatus memory status, address notary)\n {\n // This will revert if signer is not a known agent\n (status, notary) = _recoverAgent(att.hashValid(), attSignature);\n // Attestation signer needs to be a Notary, not a Guard\n if (status.domain == 0) revert AgentNotNotary();\n }\n\n /**\n * @dev Internal function to verify the signed attestation report payload.\n * Reverts if any of these is true:\n * - Report signer is not a known Guard.\n * @param att Typed memory view over attestation payload that Guard reports as invalid\n * @param arSignature Guard signature for the \"invalid attestation\" report\n * @return status Struct representing guard status, see {_recoverAgent}\n * @return guard Guard that signed the report\n */\n function _verifyAttestationReport(Attestation att, bytes memory arSignature)\n internal\n view\n returns (AgentStatus memory status, address guard)\n {\n // This will revert if signer is not a known agent\n (status, guard) = _recoverAgent(att.hashInvalid(), arSignature);\n // Report signer needs to be a Guard, not a Notary\n if (status.domain != 0) revert AgentNotGuard();\n }\n\n // ══════════════════════════════════════════ RECEIPT RELATED CHECKS ═══════════════════════════════════════════════\n\n /**\n * @dev Internal function to verify the signed receipt payload.\n * Reverts if any of these is true:\n * - Receipt signer is not a known Notary.\n * @param rcpt Typed memory view over receipt payload\n * @param rcptSignature Notary signature for the receipt\n * @return status Struct representing agent status, see {_recoverAgent}\n * @return notary Notary that signed the snapshot\n */\n function _verifyReceipt(Receipt rcpt, bytes memory rcptSignature)\n internal\n view\n returns (AgentStatus memory status, address notary)\n {\n // This will revert if signer is not a known agent\n (status, notary) = _recoverAgent(rcpt.hashValid(), rcptSignature);\n // Receipt signer needs to be a Notary, not a Guard\n if (status.domain == 0) revert AgentNotNotary();\n }\n\n /**\n * @dev Internal function to verify the signed receipt report payload.\n * Reverts if any of these is true:\n * - Report signer is not a known Guard.\n * @param rcpt Typed memory view over receipt payload that Guard reports as invalid\n * @param rrSignature Guard signature for the \"invalid receipt\" report\n * @return status Struct representing guard status, see {_recoverAgent}\n * @return guard Guard that signed the report\n */\n function _verifyReceiptReport(Receipt rcpt, bytes memory rrSignature)\n internal\n view\n returns (AgentStatus memory status, address guard)\n {\n // This will revert if signer is not a known agent\n (status, guard) = _recoverAgent(rcpt.hashInvalid(), rrSignature);\n // Report signer needs to be a Guard, not a Notary\n if (status.domain != 0) revert AgentNotGuard();\n }\n\n // ═══════════════════════════════════════ STATE/SNAPSHOT RELATED CHECKS ═══════════════════════════════════════════\n\n /**\n * @dev Internal function to verify the signed snapshot report payload.\n * Reverts if any of these is true:\n * - Report signer is not a known Guard.\n * @param state Typed memory view over state payload that Guard reports as invalid\n * @param srSignature Guard signature for the report\n * @return status Struct representing guard status, see {_recoverAgent}\n * @return guard Guard that signed the report\n */\n function _verifyStateReport(State state, bytes memory srSignature)\n internal\n view\n returns (AgentStatus memory status, address guard)\n {\n // This will revert if signer is not a known agent\n (status, guard) = _recoverAgent(state.hashInvalid(), srSignature);\n // Report signer needs to be a Guard, not a Notary\n if (status.domain != 0) revert AgentNotGuard();\n }\n\n /**\n * @dev Internal function to verify the signed snapshot payload.\n * Reverts if any of these is true:\n * - Snapshot signer is not a known Agent.\n * - Snapshot signer is not a Notary (if verifyNotary is true).\n * @param snapshot Typed memory view over snapshot payload\n * @param snapSignature Agent signature for the snapshot\n * @param verifyNotary If true, snapshot signer needs to be a Notary, not a Guard\n * @return status Struct representing agent status, see {_recoverAgent}\n * @return agent Agent that signed the snapshot\n */\n function _verifySnapshot(Snapshot snapshot, bytes memory snapSignature, bool verifyNotary)\n internal\n view\n returns (AgentStatus memory status, address agent)\n {\n // This will revert if signer is not a known agent\n (status, agent) = _recoverAgent(snapshot.hashValid(), snapSignature);\n // If requested, snapshot signer needs to be a Notary, not a Guard\n if (verifyNotary \u0026\u0026 status.domain == 0) revert AgentNotNotary();\n }\n\n // ═══════════════════════════════════════════ MERKLE RELATED CHECKS ═══════════════════════════════════════════════\n\n /**\n * @dev Internal function to verify that snapshot roots match.\n * Reverts if any of these is true:\n * - Attestation root is not equal to Merkle Root derived from State and Snapshot Proof.\n * - Snapshot Proof's first element does not match the State metadata.\n * - Snapshot Proof length exceeds Snapshot tree Height.\n * - State index is out of range.\n * @param att Typed memory view over Attestation\n * @param stateIndex Index of state in the snapshot\n * @param state Typed memory view over the provided state payload\n * @param snapProof Raw payload with snapshot data\n */\n function _verifySnapshotMerkle(Attestation att, uint8 stateIndex, State state, bytes32[] memory snapProof)\n internal\n pure\n {\n // Snapshot proof first element should match State metadata (aka \"right sub-leaf\")\n (, bytes32 rightSubLeaf) = state.subLeafs();\n if (snapProof[0] != rightSubLeaf) revert IncorrectSnapshotProof();\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(state.root(), state.origin(), snapProof, stateIndex);\n // Snapshot root should match the attestation root\n if (att.snapRoot() != snapshotRoot) revert IncorrectSnapshotRoot();\n }\n}\n\n// contracts/inbox/Inbox.sol\n\n// ══════════════════════════════ LIBRARY IMPORTS ══════════════════════════════\n\n// ═════════════════════════════ INTERNAL IMPORTS ══════════════════════════════\n\n/// @notice `Inbox` is the child of `StatementInbox` contract, that is used on Synapse Chain.\n/// In addition to the functionality of `StatementInbox`, it also:\n/// - Accepts Guard and Notary Snapshots and passes them to `Summit` contract.\n/// - Accepts Notary-signed Receipts and passes them to `Summit` contract.\n/// - Accepts Receipt Reports to initiate a dispute between Guard and Notary.\n/// - Verifies Attestations and Attestation Reports, and slashes the signer if they are invalid.\ncontract Inbox is StatementInbox, InboxEvents, InterfaceInbox {\n using AttestationLib for bytes;\n using ReceiptLib for bytes;\n using SnapshotLib for bytes;\n\n // Struct to get around stack too deep error. TODO: revisit this\n struct ReceiptInfo {\n AgentStatus rcptNotaryStatus;\n address notary;\n uint32 attNonce;\n AgentStatus attNotaryStatus;\n }\n\n // ══════════════════════════════════════════════════ STORAGE ══════════════════════════════════════════════════════\n\n // The address of the Summit contract.\n address public summit;\n\n // ═════════════════════════════════════════ CONSTRUCTOR \u0026 INITIALIZER ═════════════════════════════════════════════\n\n constructor(uint32 synapseDomain_) MessagingBase(\"0.0.3\", synapseDomain_) {\n if (localDomain != synapseDomain) revert MustBeSynapseDomain();\n }\n\n /// @notice Initializes `Inbox` contract:\n /// - Sets `msg.sender` as the owner of the contract\n /// - Sets `agentManager`, `origin`, `destination` and `summit` addresses\n function initialize(address agentManager_, address origin_, address destination_, address summit_)\n external\n initializer\n {\n __StatementInbox_init(agentManager_, origin_, destination_);\n summit = summit_;\n }\n\n // ══════════════════════════════════════════ SUBMIT AGENT STATEMENTS ══════════════════════════════════════════════\n\n /// @inheritdoc InterfaceInbox\n function submitSnapshot(bytes memory snapPayload, bytes memory snapSignature)\n external\n returns (bytes memory attPayload, bytes32 agentRoot_, uint256[] memory snapGas)\n {\n // This will revert if payload is not a snapshot\n Snapshot snapshot = snapPayload.castToSnapshot();\n // This will revert if the signer is not a known Guard/Notary\n (AgentStatus memory status, address agent) =\n _verifySnapshot({snapshot: snapshot, snapSignature: snapSignature, verifyNotary: false});\n // Check that Agent is active\n status.verifyActive();\n // Store Agent signature for the Snapshot\n uint256 sigIndex = _saveSignature(snapSignature);\n if (status.domain == 0) {\n // Guard that is in Dispute could still submit new snapshots, so we don't check that\n InterfaceSummit(summit).acceptGuardSnapshot({\n guardIndex: status.index,\n sigIndex: sigIndex,\n snapPayload: snapPayload\n });\n } else {\n // Get current agentRoot from AgentManager\n agentRoot_ = IAgentManager(agentManager).agentRoot();\n // This will revert if Notary is in Dispute\n attPayload = InterfaceSummit(summit).acceptNotarySnapshot({\n notaryIndex: status.index,\n sigIndex: sigIndex,\n agentRoot: agentRoot_,\n snapPayload: snapPayload\n });\n ChainGas[] memory snapGas_ = snapshot.snapGas();\n // Pass created attestation to Destination to enable executing messages coming to Synapse Chain\n InterfaceDestination(destination).acceptAttestation(\n status.index, type(uint256).max, attPayload, agentRoot_, snapGas_\n );\n // Use assembly to cast ChainGas[] to uint256[] without copying. Highest bits are left zeroed.\n // solhint-disable-next-line no-inline-assembly\n assembly {\n snapGas := snapGas_\n }\n }\n emit SnapshotAccepted(status.domain, agent, snapPayload, snapSignature);\n }\n\n /// @inheritdoc InterfaceInbox\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 // Struct to get around stack too deep error.\n ReceiptInfo memory info;\n // This will revert if payload is not a receipt\n Receipt rcpt = rcptPayload.castToReceipt();\n // This will revert if the receipt signer is not a known Notary\n (info.rcptNotaryStatus, info.notary) = _verifyReceipt(rcpt, rcptSignature);\n // Receipt Notary needs to be Active\n info.rcptNotaryStatus.verifyActive();\n info.attNonce = IExecutionHub(destination).getAttestationNonce(rcpt.snapshotRoot());\n if (info.attNonce == 0) revert IncorrectSnapshotRoot();\n // Attestation Notary domain needs to match the destination domain\n info.attNotaryStatus = IAgentManager(agentManager).agentStatus(rcpt.attNotary());\n if (info.attNotaryStatus.domain != rcpt.destination()) revert IncorrectAgentDomain();\n // Check that the correct tip values for the message were provided\n _verifyReceiptTips(rcpt.messageHash(), paddedTips, headerHash, bodyHash);\n // Store Notary signature for the Receipt\n uint256 sigIndex = _saveSignature(rcptSignature);\n // This will revert if Receipt Notary is in Dispute\n wasAccepted = InterfaceSummit(summit).acceptReceipt({\n rcptNotaryIndex: info.rcptNotaryStatus.index,\n attNotaryIndex: info.attNotaryStatus.index,\n sigIndex: sigIndex,\n attNonce: info.attNonce,\n paddedTips: paddedTips,\n rcptPayload: rcptPayload\n });\n if (wasAccepted) {\n emit ReceiptAccepted(info.rcptNotaryStatus.domain, info.notary, rcptPayload, rcptSignature);\n }\n }\n\n /// @inheritdoc InterfaceInbox\n function submitReceiptReport(bytes memory rcptPayload, bytes memory rcptSignature, bytes memory rrSignature)\n external\n returns (bool wasAccepted)\n {\n // This will revert if payload is not a receipt\n Receipt rcpt = rcptPayload.castToReceipt();\n // This will revert if the receipt signer is not a known Guard\n (AgentStatus memory guardStatus,) = _verifyReceiptReport(rcpt, rrSignature);\n // Guard needs to be Active\n guardStatus.verifyActive();\n // This will revert if report signer is not a known Notary\n (AgentStatus memory notaryStatus,) = _verifyReceipt(rcpt, rcptSignature);\n // Notary needs to be Active/Unstaking\n notaryStatus.verifyActiveUnstaking();\n _saveReport(rcptPayload, rrSignature);\n // This will revert if either actor is already in dispute\n IAgentManager(agentManager).openDispute(guardStatus.index, notaryStatus.index);\n return true;\n }\n\n /// @inheritdoc InterfaceInbox\n function passReceipt(uint32 attNotaryIndex, uint32 attNonce, uint256 paddedTips, bytes memory rcptPayload)\n external\n returns (bool wasAccepted)\n {\n // Only Destination can pass receipts\n if (msg.sender != destination) revert CallerNotDestination();\n return InterfaceSummit(summit).acceptReceipt({\n rcptNotaryIndex: attNotaryIndex,\n attNotaryIndex: attNotaryIndex,\n sigIndex: type(uint256).max,\n attNonce: attNonce,\n paddedTips: paddedTips,\n rcptPayload: rcptPayload\n });\n }\n\n // ══════════════════════════════════════════ VERIFY AGENT STATEMENTS ══════════════════════════════════════════════\n\n /// @inheritdoc InterfaceInbox\n function verifyAttestation(bytes memory attPayload, bytes memory attSignature)\n external\n returns (bool isValidAttestation)\n {\n // This will revert if payload is not an attestation\n Attestation att = attPayload.castToAttestation();\n // This will revert if the attestation signer is not a known Notary\n (AgentStatus memory status, address notary) = _verifyAttestation(att, attSignature);\n // Notary needs to be Active/Unstaking\n status.verifyActiveUnstaking();\n isValidAttestation = ISnapshotHub(summit).isValidAttestation(attPayload);\n if (!isValidAttestation) {\n emit InvalidAttestation(attPayload, attSignature);\n IAgentManager(agentManager).slashAgent(status.domain, notary, msg.sender);\n }\n }\n\n /// @inheritdoc InterfaceInbox\n function verifyAttestationReport(bytes memory attPayload, bytes memory arSignature)\n external\n returns (bool isValidReport)\n {\n // This will revert if payload is not an attestation\n Attestation att = attPayload.castToAttestation();\n // This will revert if the report signer is not a known Guard\n (AgentStatus memory status, address guard) = _verifyAttestationReport(att, arSignature);\n // Guard needs to be Active/Unstaking\n status.verifyActiveUnstaking();\n // Report is valid IF AND ONLY IF the reported attestation in invalid\n isValidReport = !ISnapshotHub(summit).isValidAttestation(attPayload);\n if (!isValidReport) {\n emit InvalidAttestationReport(attPayload, arSignature);\n IAgentManager(agentManager).slashAgent(status.domain, guard, msg.sender);\n }\n }\n\n // ══════════════════════════════════════════════ INTERNAL VIEWS ═══════════════════════════════════════════════════\n\n /// @dev Verifies that tips proof matches the message hash.\n function _verifyReceiptTips(bytes32 msgHash, uint256 paddedTips, bytes32 headerHash, bytes32 bodyHash)\n internal\n pure\n {\n Tips tips = TipsLib.wrapPadded(paddedTips);\n // full message leaf is (header, baseMessage), while base message leaf is (tips, remainingBody).\n if (MerkleMath.getParent(headerHash, MerkleMath.getParent(tips.leaf(), bodyHash)) != msgHash) {\n revert IncorrectTipsProof();\n }\n }\n}\n","language":"Solidity","languageVersion":"0.8.17","compilerVersion":"0.8.17","compilerOptions":"--combined-json bin,bin-runtime,srcmap,srcmap-runtime,abi,userdoc,devdoc,metadata,hashes --optimize --optimize-runs 10000 --allow-paths ., ./, ../","srcMap":"","srcMapRuntime":"","abiDefinition":[{"inputs":[{"internalType":"uint32","name":"guardIndex","type":"uint32"},{"internalType":"uint256","name":"sigIndex","type":"uint256"},{"internalType":"bytes","name":"snapPayload","type":"bytes"}],"name":"acceptGuardSnapshot","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint32","name":"notaryIndex","type":"uint32"},{"internalType":"uint256","name":"sigIndex","type":"uint256"},{"internalType":"bytes32","name":"agentRoot","type":"bytes32"},{"internalType":"bytes","name":"snapPayload","type":"bytes"}],"name":"acceptNotarySnapshot","outputs":[{"internalType":"bytes","name":"attPayload","type":"bytes"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint32","name":"rcptNotaryIndex","type":"uint32"},{"internalType":"uint32","name":"attNotaryIndex","type":"uint32"},{"internalType":"uint256","name":"sigIndex","type":"uint256"},{"internalType":"uint32","name":"attNonce","type":"uint32"},{"internalType":"uint256","name":"paddedTips","type":"uint256"},{"internalType":"bytes","name":"rcptPayload","type":"bytes"}],"name":"acceptReceipt","outputs":[{"internalType":"bool","name":"wasAccepted","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"actor","type":"address"},{"internalType":"uint32","name":"origin","type":"uint32"}],"name":"actorTips","outputs":[{"internalType":"uint128","name":"earned","type":"uint128"},{"internalType":"uint128","name":"claimed","type":"uint128"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"distributeTips","outputs":[{"internalType":"bool","name":"queuePopped","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint32","name":"origin","type":"uint32"}],"name":"getLatestState","outputs":[{"internalType":"bytes","name":"statePayload","type":"bytes"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"receiptQueueLength","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint32","name":"origin","type":"uint32"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"withdrawTips","outputs":[],"stateMutability":"nonpayable","type":"function"}],"userDoc":{"kind":"user","methods":{"acceptGuardSnapshot(uint32,uint256,bytes)":{"notice":"Accepts a snapshot, which local `AgentManager` verified to have been signed by an active Guard. \u003e Snapshot is a list of states for a set of Origin contracts residing on any of the chains. All the states in the Guard-signed snapshot become available for Notary signing. \u003e Will revert if any of these is true: \u003e - Called by anyone other than local `AgentManager`. \u003e - Snapshot payload is not properly formatted. \u003e - Snapshot contains a state older then the Guard has previously submitted."},"acceptNotarySnapshot(uint32,uint256,bytes32,bytes)":{"notice":"Accepts a snapshot, which local `AgentManager` verified to have been signed by an active Notary. \u003e Snapshot is a list of states for a set of Origin contracts residing on any of the chains. Snapshot Merkle Root is calculated and saved for valid snapshots, i.e. snapshots which are only using states previously submitted by any of the Guards. - Notary could use states singed by the same of different Guards 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 - Called by anyone other than local `AgentManager`. \u003e - Snapshot payload is not properly formatted. \u003e - Snapshot contains a state older then the Notary has previously submitted. \u003e - Snapshot contains a state that no Guard has previously submitted."},"acceptReceipt(uint32,uint32,uint256,uint32,uint256,bytes)":{"notice":"Accepts a receipt, which local `AgentManager` verified to have been signed by an active Notary. \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. - Notary who signed the receipt is referenced as the \"Receipt Notary\". - Notary who signed the attestation on destination chain is referenced as the \"Attestation Notary\". \u003e Will revert if any of these is true: \u003e - Called by anyone other than local `AgentManager`. \u003e - Receipt body payload is not properly formatted. \u003e - Receipt signer is in Dispute. \u003e - Receipt's snapshot root is unknown."},"actorTips(address,uint32)":{"notice":"Returns earned and claimed tips for the actor. Note: Tips for address(0) belong to the Treasury."},"distributeTips()":{"notice":"Distributes tips using the first Receipt from the \"receipt quarantine queue\". Possible scenarios: - Receipt queue is empty =\u003e does nothing - Receipt optimistic period is not over =\u003e does nothing - Either of Notaries present in Receipt was slashed =\u003e receipt is deleted from the queue - Either of Notaries present in Receipt in Dispute =\u003e receipt is moved to the end of queue - None of the above =\u003e receipt tips are distributed"},"getLatestState(uint32)":{"notice":"Returns the state with the highest known nonce submitted by any of the currently active Guards."},"receiptQueueLength()":{"notice":"Returns the amount of receipts in the \"Receipt Quarantine Queue\"."},"withdrawTips(uint32,uint256)":{"notice":"Withdraws locked base message tips from requested domain Origin to the recipient. This is done by a call to a local Origin contract, or by a manager message to the remote chain."}},"version":1},"developerDoc":{"kind":"dev","methods":{"acceptGuardSnapshot(uint32,uint256,bytes)":{"params":{"guardIndex":"Index of Guard in Agent Merkle Tree","sigIndex":"Index of stored Agent signature","snapPayload":"Raw payload with snapshot data"}},"acceptNotarySnapshot(uint32,uint256,bytes32,bytes)":{"params":{"agentRoot":"Current root of the Agent Merkle Tree","notaryIndex":"Index of Notary in Agent Merkle Tree","sigIndex":"Index of stored Agent signature","snapPayload":"Raw payload with snapshot data"},"returns":{"attPayload":" Raw payload with data for attestation derived from Notary snapshot."}},"acceptReceipt(uint32,uint32,uint256,uint32,uint256,bytes)":{"params":{"attNonce":"Nonce of the attestation used for proving the executed message","attNotaryIndex":"Index of Attestation Notary in Agent Merkle Tree","paddedTips":"Padded encoded paid tips information","rcptNotaryIndex":"Index of Receipt Notary in Agent Merkle Tree","rcptPayload":"Raw payload with message execution receipt","sigIndex":"Index of stored Notary signature"},"returns":{"wasAccepted":" Whether the receipt was accepted"}},"actorTips(address,uint32)":{"params":{"actor":"Address of the actor","origin":"Domain where the tips were initially paid"},"returns":{"claimed":" Total amount of origin tips the actor has claimed so far","earned":" Total amount of origin tips the actor has earned so far"}},"distributeTips()":{"details":"Returned value makes it possible to do the following: `while (distributeTips()) {}`","returns":{"queuePopped":" Whether the first element was popped from the queue"}},"getLatestState(uint32)":{"params":{"origin":"Domain of origin chain"},"returns":{"statePayload":"Raw payload with latest active Guard state for origin"}},"withdrawTips(uint32,uint256)":{"details":"This will revert, if the pending balance of origin tips (earned-claimed) is lower than requested.","params":{"amount":"Amount of tips to withdraw","origin":"Domain of chain to withdraw tips on"}}},"version":1},"metadata":"{\"compiler\":{\"version\":\"0.8.17+commit.8df45f5f\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"uint32\",\"name\":\"guardIndex\",\"type\":\"uint32\"},{\"internalType\":\"uint256\",\"name\":\"sigIndex\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"snapPayload\",\"type\":\"bytes\"}],\"name\":\"acceptGuardSnapshot\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint32\",\"name\":\"notaryIndex\",\"type\":\"uint32\"},{\"internalType\":\"uint256\",\"name\":\"sigIndex\",\"type\":\"uint256\"},{\"internalType\":\"bytes32\",\"name\":\"agentRoot\",\"type\":\"bytes32\"},{\"internalType\":\"bytes\",\"name\":\"snapPayload\",\"type\":\"bytes\"}],\"name\":\"acceptNotarySnapshot\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"attPayload\",\"type\":\"bytes\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint32\",\"name\":\"rcptNotaryIndex\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"attNotaryIndex\",\"type\":\"uint32\"},{\"internalType\":\"uint256\",\"name\":\"sigIndex\",\"type\":\"uint256\"},{\"internalType\":\"uint32\",\"name\":\"attNonce\",\"type\":\"uint32\"},{\"internalType\":\"uint256\",\"name\":\"paddedTips\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"rcptPayload\",\"type\":\"bytes\"}],\"name\":\"acceptReceipt\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"wasAccepted\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"actor\",\"type\":\"address\"},{\"internalType\":\"uint32\",\"name\":\"origin\",\"type\":\"uint32\"}],\"name\":\"actorTips\",\"outputs\":[{\"internalType\":\"uint128\",\"name\":\"earned\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"claimed\",\"type\":\"uint128\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"distributeTips\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"queuePopped\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint32\",\"name\":\"origin\",\"type\":\"uint32\"}],\"name\":\"getLatestState\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"statePayload\",\"type\":\"bytes\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"receiptQueueLength\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint32\",\"name\":\"origin\",\"type\":\"uint32\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"withdrawTips\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{\"acceptGuardSnapshot(uint32,uint256,bytes)\":{\"params\":{\"guardIndex\":\"Index of Guard in Agent Merkle Tree\",\"sigIndex\":\"Index of stored Agent signature\",\"snapPayload\":\"Raw payload with snapshot data\"}},\"acceptNotarySnapshot(uint32,uint256,bytes32,bytes)\":{\"params\":{\"agentRoot\":\"Current root of the Agent Merkle Tree\",\"notaryIndex\":\"Index of Notary in Agent Merkle Tree\",\"sigIndex\":\"Index of stored Agent signature\",\"snapPayload\":\"Raw payload with snapshot data\"},\"returns\":{\"attPayload\":\" Raw payload with data for attestation derived from Notary snapshot.\"}},\"acceptReceipt(uint32,uint32,uint256,uint32,uint256,bytes)\":{\"params\":{\"attNonce\":\"Nonce of the attestation used for proving the executed message\",\"attNotaryIndex\":\"Index of Attestation Notary in Agent Merkle Tree\",\"paddedTips\":\"Padded encoded paid tips information\",\"rcptNotaryIndex\":\"Index of Receipt Notary in Agent Merkle Tree\",\"rcptPayload\":\"Raw payload with message execution receipt\",\"sigIndex\":\"Index of stored Notary signature\"},\"returns\":{\"wasAccepted\":\" Whether the receipt was accepted\"}},\"actorTips(address,uint32)\":{\"params\":{\"actor\":\"Address of the actor\",\"origin\":\"Domain where the tips were initially paid\"},\"returns\":{\"claimed\":\" Total amount of origin tips the actor has claimed so far\",\"earned\":\" Total amount of origin tips the actor has earned so far\"}},\"distributeTips()\":{\"details\":\"Returned value makes it possible to do the following: `while (distributeTips()) {}`\",\"returns\":{\"queuePopped\":\" Whether the first element was popped from the queue\"}},\"getLatestState(uint32)\":{\"params\":{\"origin\":\"Domain of origin chain\"},\"returns\":{\"statePayload\":\"Raw payload with latest active Guard state for origin\"}},\"withdrawTips(uint32,uint256)\":{\"details\":\"This will revert, if the pending balance of origin tips (earned-claimed) is lower than requested.\",\"params\":{\"amount\":\"Amount of tips to withdraw\",\"origin\":\"Domain of chain to withdraw tips on\"}}},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{\"acceptGuardSnapshot(uint32,uint256,bytes)\":{\"notice\":\"Accepts a snapshot, which local `AgentManager` verified to have been signed by an active Guard. \u003e Snapshot is a list of states for a set of Origin contracts residing on any of the chains. All the states in the Guard-signed snapshot become available for Notary signing. \u003e Will revert if any of these is true: \u003e - Called by anyone other than local `AgentManager`. \u003e - Snapshot payload is not properly formatted. \u003e - Snapshot contains a state older then the Guard has previously submitted.\"},\"acceptNotarySnapshot(uint32,uint256,bytes32,bytes)\":{\"notice\":\"Accepts a snapshot, which local `AgentManager` verified to have been signed by an active Notary. \u003e Snapshot is a list of states for a set of Origin contracts residing on any of the chains. Snapshot Merkle Root is calculated and saved for valid snapshots, i.e. snapshots which are only using states previously submitted by any of the Guards. - Notary could use states singed by the same of different Guards 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 - Called by anyone other than local `AgentManager`. \u003e - Snapshot payload is not properly formatted. \u003e - Snapshot contains a state older then the Notary has previously submitted. \u003e - Snapshot contains a state that no Guard has previously submitted.\"},\"acceptReceipt(uint32,uint32,uint256,uint32,uint256,bytes)\":{\"notice\":\"Accepts a receipt, which local `AgentManager` verified to have been signed by an active Notary. \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. - Notary who signed the receipt is referenced as the \\\"Receipt Notary\\\". - Notary who signed the attestation on destination chain is referenced as the \\\"Attestation Notary\\\". \u003e Will revert if any of these is true: \u003e - Called by anyone other than local `AgentManager`. \u003e - Receipt body payload is not properly formatted. \u003e - Receipt signer is in Dispute. \u003e - Receipt's snapshot root is unknown.\"},\"actorTips(address,uint32)\":{\"notice\":\"Returns earned and claimed tips for the actor. Note: Tips for address(0) belong to the Treasury.\"},\"distributeTips()\":{\"notice\":\"Distributes tips using the first Receipt from the \\\"receipt quarantine queue\\\". Possible scenarios: - Receipt queue is empty =\u003e does nothing - Receipt optimistic period is not over =\u003e does nothing - Either of Notaries present in Receipt was slashed =\u003e receipt is deleted from the queue - Either of Notaries present in Receipt in Dispute =\u003e receipt is moved to the end of queue - None of the above =\u003e receipt tips are distributed\"},\"getLatestState(uint32)\":{\"notice\":\"Returns the state with the highest known nonce submitted by any of the currently active Guards.\"},\"receiptQueueLength()\":{\"notice\":\"Returns the amount of receipts in the \\\"Receipt Quarantine Queue\\\".\"},\"withdrawTips(uint32,uint256)\":{\"notice\":\"Withdraws locked base message tips from requested domain Origin to the recipient. This is done by a call to a local Origin contract, or by a manager message to the remote chain.\"}},\"version\":1}},\"settings\":{\"compilationTarget\":{\"solidity/Inbox.sol\":\"InterfaceSummit\"},\"evmVersion\":\"london\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\"},\"optimizer\":{\"enabled\":true,\"runs\":10000},\"remappings\":[]},\"sources\":{\"solidity/Inbox.sol\":{\"keccak256\":\"0x9b516081a036814c0169e20e484d4a5499066b7a6f48fada952b5e844a1ca3e5\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://32bde393b3f24ef4307d9626d4143f337b3c0bd34e17bb969fd5a15221d96987\",\"dweb:/ipfs/QmTkt2XZRtgsbSpmsVQUM3c4ebETQoDVYbmEV9yheBghnr\"]}},\"version\":1}"},"hashes":{"acceptGuardSnapshot(uint32,uint256,bytes)":"9cc1bb31","acceptNotarySnapshot(uint32,uint256,bytes32,bytes)":"00f34054","acceptReceipt(uint32,uint32,uint256,uint32,uint256,bytes)":"c79a431b","actorTips(address,uint32)":"47ca1b14","distributeTips()":"0729ae8a","getLatestState(uint32)":"d17db53a","receiptQueueLength()":"a5ba1a55","withdrawTips(uint32,uint256)":"6170e4e6"}},"solidity/Inbox.sol:Math":{"code":"0x60566037600b82828239805160001a607314602a57634e487b7160e01b600052600060045260246000fd5b30600052607381538281f3fe73000000000000000000000000000000000000000030146080604052600080fdfea2646970667358221220b3ea781c00e695f7d534d1dd94b26f86d210e5b83612202d38f35d805f8a8cce64736f6c63430008110033","runtime-code":"0x73000000000000000000000000000000000000000030146080604052600080fdfea2646970667358221220b3ea781c00e695f7d534d1dd94b26f86d210e5b83612202d38f35d805f8a8cce64736f6c63430008110033","info":{"source":"// SPDX-License-Identifier: MIT\npragma solidity =0.8.17 ^0.8.0 ^0.8.1 ^0.8.2;\n\n// contracts/events/InboxEvents.sol\n\nabstract contract InboxEvents {\n /**\n * @notice Emitted when a snapshot is accepted by the Summit contract.\n * @param domain Domain where the signed Agent is active (ZERO for Guards)\n * @param agent Agent who signed the snapshot\n * @param snapPayload Raw payload with snapshot data\n * @param snapSignature Agent signature for the snapshot\n */\n event SnapshotAccepted(uint32 indexed domain, address indexed agent, bytes snapPayload, bytes snapSignature);\n\n /**\n * @notice Emitted when a snapshot is accepted by the Summit contract.\n * @param domain Domain where the signed Notary is active\n * @param notary Notary who signed the attestation\n * @param rcptPayload Raw payload with receipt data\n * @param rcptSignature Notary signature for the receipt\n */\n event ReceiptAccepted(uint32 domain, address notary, bytes rcptPayload, bytes rcptSignature);\n\n /**\n * @notice Emitted when a proof of invalid attestation is submitted.\n * @param attPayload Raw payload with Attestation data\n * @param attSignature Notary signature for the attestation\n */\n event InvalidAttestation(bytes attPayload, bytes attSignature);\n\n /**\n * @notice Emitted when a proof of invalid attestation report is submitted.\n * @param arPayload Raw payload with report data\n * @param arSignature Guard signature for the report\n */\n event InvalidAttestationReport(bytes arPayload, bytes arSignature);\n}\n\n// contracts/events/StatementInboxEvents.sol\n\nabstract contract StatementInboxEvents {\n // ════════════════════════════════════════════ STATEMENT ACCEPTED ═════════════════════════════════════════════════\n\n /**\n * @notice Emitted when a snapshot is accepted by the Destination contract.\n * @param domain Domain where the signed Notary is active\n * @param notary Notary who signed the attestation\n * @param attPayload Raw payload with attestation data\n * @param attSignature Notary signature for the attestation\n */\n event AttestationAccepted(uint32 domain, address notary, bytes attPayload, bytes attSignature);\n\n // ═════════════════════════════════════════ INVALID STATEMENT PROVED ══════════════════════════════════════════════\n\n /**\n * @notice Emitted when a proof of invalid receipt statement is submitted.\n * @param rcptPayload Raw payload with the receipt statement\n * @param rcptSignature Notary signature for the receipt statement\n */\n event InvalidReceipt(bytes rcptPayload, bytes rcptSignature);\n\n /**\n * @notice Emitted when a proof of invalid receipt report is submitted.\n * @param rrPayload Raw payload with report data\n * @param rrSignature Guard signature for the report\n */\n event InvalidReceiptReport(bytes rrPayload, bytes rrSignature);\n\n /**\n * @notice Emitted when a proof of invalid state in the signed attestation is submitted.\n * @param stateIndex Index of invalid state in the snapshot\n * @param statePayload Raw payload with state data\n * @param attPayload Raw payload with Attestation data for snapshot\n * @param attSignature Notary signature for the attestation\n */\n event InvalidStateWithAttestation(uint8 stateIndex, bytes statePayload, bytes attPayload, bytes attSignature);\n\n /**\n * @notice Emitted when a proof of invalid state in the signed snapshot is submitted.\n * @param stateIndex Index of invalid state in the snapshot\n * @param snapPayload Raw payload with snapshot data\n * @param snapSignature Agent signature for the snapshot\n */\n event InvalidStateWithSnapshot(uint8 stateIndex, bytes snapPayload, bytes snapSignature);\n\n /**\n * @notice Emitted when a proof of invalid state report is submitted.\n * @param srPayload Raw payload with report data\n * @param srSignature Guard signature for the report\n */\n event InvalidStateReport(bytes srPayload, bytes srSignature);\n}\n\n// contracts/interfaces/ISnapshotHub.sol\n\ninterface ISnapshotHub {\n /**\n * @notice Check that a given attestation is valid: matches the historical attestation\n * derived from an accepted Notary snapshot.\n * @dev Will revert if any of these is true:\n * - Attestation payload is not properly formatted.\n * @param attPayload Raw payload with attestation data\n * @return isValid Whether the provided attestation is valid\n */\n function isValidAttestation(bytes memory attPayload) external view returns (bool isValid);\n\n /**\n * @notice Returns saved attestation with the given nonce.\n * @dev Reverts if attestation with given nonce hasn't been created yet.\n * @param attNonce Nonce for the attestation\n * @return attPayload Raw payload with formatted Attestation data\n * @return agentRoot Agent root hash used for the attestation\n * @return snapGas Snapshot gas data used for the attestation\n */\n function getAttestation(uint32 attNonce)\n external\n view\n returns (bytes memory attPayload, bytes32 agentRoot, uint256[] memory snapGas);\n\n /**\n * @notice Returns the state with the highest known nonce submitted by a given Agent.\n * @param origin Domain of origin chain\n * @param agent Agent address\n * @return statePayload Raw payload with agent's latest state for origin\n */\n function getLatestAgentState(uint32 origin, address agent) external view returns (bytes memory statePayload);\n\n /**\n * @notice Returns latest saved attestation for a Notary.\n * @param notary Notary address\n * @return attPayload Raw payload with formatted Attestation data\n * @return agentRoot Agent root hash used for the attestation\n * @return snapGas Snapshot gas data used for the attestation\n */\n function getLatestNotaryAttestation(address notary)\n external\n view\n returns (bytes memory attPayload, bytes32 agentRoot, uint256[] memory snapGas);\n\n /**\n * @notice Returns Guard snapshot from the list of all accepted Guard snapshots.\n * @dev Reverts if snapshot with given index hasn't been accepted yet.\n * @param index Snapshot index in the list of all Guard snapshots\n * @return snapPayload Raw payload with Guard snapshot\n * @return snapSignature Raw payload with Guard signature for snapshot\n */\n function getGuardSnapshot(uint256 index)\n external\n view\n returns (bytes memory snapPayload, bytes memory snapSignature);\n\n /**\n * @notice Returns Notary snapshot from the list of all accepted Guard snapshots.\n * @dev Reverts if snapshot with given index hasn't been accepted yet.\n * @param index Snapshot index in the list of all Notary snapshots\n * @return snapPayload Raw payload with Notary snapshot\n * @return snapSignature Raw payload with Notary signature for snapshot\n */\n function getNotarySnapshot(uint256 index)\n external\n view\n returns (bytes memory snapPayload, bytes memory snapSignature);\n\n /**\n * @notice Returns Notary snapshot that was used for creating a given attestation.\n * @dev Reverts if any of these is true:\n * - Attestation payload is not properly formatted.\n * - Attestation is invalid (doesn't have a matching Notary snapshot).\n * @param attPayload Raw payload with attestation data\n * @return snapPayload Raw payload with Notary snapshot\n * @return snapSignature Raw payload with Notary signature for snapshot\n */\n function getNotarySnapshot(bytes memory attPayload)\n external\n view\n returns (bytes memory snapPayload, bytes memory snapSignature);\n\n /**\n * @notice Returns proof of inclusion of (root, origin) fields of a given snapshot's state\n * into the Snapshot Merkle Tree for a given attestation.\n * @dev Reverts if any of these is true:\n * - Attestation with given nonce hasn't been created yet.\n * - State index is out of range of snapshot list.\n * @param attNonce Nonce for the attestation\n * @param stateIndex Index of state in the attestation's snapshot\n * @return snapProof The snapshot proof\n */\n function getSnapshotProof(uint32 attNonce, uint8 stateIndex) external view returns (bytes32[] memory snapProof);\n}\n\n// contracts/interfaces/IStateHub.sol\n\ninterface IStateHub {\n /**\n * @notice Check that a given state is valid: matches the historical state of Origin contract.\n * Note: any Agent including an invalid state in their snapshot will be slashed\n * upon providing the snapshot and agent signature for it to Origin contract.\n * @dev Will revert if any of these is true:\n * - State payload is not properly formatted.\n * @param statePayload Raw payload with state data\n * @return isValid Whether the provided state is valid\n */\n function isValidState(bytes memory statePayload) external view returns (bool isValid);\n\n /**\n * @notice Returns the amount of saved states so far.\n * @dev This includes the initial state of \"empty Origin Merkle Tree\".\n */\n function statesAmount() external view returns (uint256);\n\n /**\n * @notice Suggest the data (state after latest sent message) to sign for an Agent.\n * Note: signing the suggested state data will will never lead to slashing of the actor,\n * assuming they have confirmed that the block, which number is included in the data,\n * is not subject to reorganization (which is different for every observed chain).\n * @return statePayload Raw payload with the latest state data\n */\n function suggestLatestState() external view returns (bytes memory statePayload);\n\n /**\n * @notice Given the historical nonce, suggest the state data to sign for an Agent.\n * Note: signing the suggested state data will will never lead to slashing of the actor,\n * assuming they have confirmed that the block, which number is included in the data,\n * is not subject to reorganization (which is different for every observed chain).\n * @param nonce Historical nonce to form a state\n * @return statePayload Raw payload with historical state data\n */\n function suggestState(uint32 nonce) external view returns (bytes memory statePayload);\n}\n\n// contracts/interfaces/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/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// node_modules/@openzeppelin/contracts/utils/math/Math.sol\n\n// OpenZeppelin Contracts (last updated v4.9.0) (utils/math/Math.sol)\n\n/**\n * @dev Standard math utilities missing in the Solidity language.\n */\nlibrary Math {\n enum Rounding {\n Down, // Toward negative infinity\n Up, // Toward infinity\n Zero // Toward zero\n }\n\n /**\n * @dev Returns the largest of two numbers.\n */\n function max(uint256 a, uint256 b) internal pure returns (uint256) {\n return a \u003e b ? a : b;\n }\n\n /**\n * @dev Returns the smallest of two numbers.\n */\n function min(uint256 a, uint256 b) internal pure returns (uint256) {\n return a \u003c b ? a : b;\n }\n\n /**\n * @dev Returns the average of two numbers. The result is rounded towards\n * zero.\n */\n function average(uint256 a, uint256 b) internal pure returns (uint256) {\n // (a + b) / 2 can overflow.\n return (a \u0026 b) + (a ^ b) / 2;\n }\n\n /**\n * @dev Returns the ceiling of the division of two numbers.\n *\n * This differs from standard division with `/` in that it rounds up instead\n * of rounding down.\n */\n function ceilDiv(uint256 a, uint256 b) internal pure returns (uint256) {\n // (a + b - 1) / b can overflow on addition, so we distribute.\n return a == 0 ? 0 : (a - 1) / b + 1;\n }\n\n /**\n * @notice Calculates floor(x * y / denominator) with full precision. Throws if result overflows a uint256 or denominator == 0\n * @dev Original credit to Remco Bloemen under MIT license (https://xn--2-umb.com/21/muldiv)\n * with further edits by Uniswap Labs also under MIT license.\n */\n function mulDiv(uint256 x, uint256 y, uint256 denominator) internal pure returns (uint256 result) {\n unchecked {\n // 512-bit multiply [prod1 prod0] = x * y. Compute the product mod 2^256 and mod 2^256 - 1, then use\n // use the Chinese Remainder Theorem to reconstruct the 512 bit result. The result is stored in two 256\n // variables such that product = prod1 * 2^256 + prod0.\n uint256 prod0; // Least significant 256 bits of the product\n uint256 prod1; // Most significant 256 bits of the product\n assembly {\n let mm := mulmod(x, y, not(0))\n prod0 := mul(x, y)\n prod1 := sub(sub(mm, prod0), lt(mm, prod0))\n }\n\n // Handle non-overflow cases, 256 by 256 division.\n if (prod1 == 0) {\n // Solidity will revert if denominator == 0, unlike the div opcode on its own.\n // The surrounding unchecked block does not change this fact.\n // See https://docs.soliditylang.org/en/latest/control-structures.html#checked-or-unchecked-arithmetic.\n return prod0 / denominator;\n }\n\n // Make sure the result is less than 2^256. Also prevents denominator == 0.\n require(denominator \u003e prod1, \"Math: mulDiv overflow\");\n\n ///////////////////////////////////////////////\n // 512 by 256 division.\n ///////////////////////////////////////////////\n\n // Make division exact by subtracting the remainder from [prod1 prod0].\n uint256 remainder;\n assembly {\n // Compute remainder using mulmod.\n remainder := mulmod(x, y, denominator)\n\n // Subtract 256 bit number from 512 bit number.\n prod1 := sub(prod1, gt(remainder, prod0))\n prod0 := sub(prod0, remainder)\n }\n\n // Factor powers of two out of denominator and compute largest power of two divisor of denominator. Always \u003e= 1.\n // See https://cs.stackexchange.com/q/138556/92363.\n\n // Does not overflow because the denominator cannot be zero at this stage in the function.\n uint256 twos = denominator \u0026 (~denominator + 1);\n assembly {\n // Divide denominator by twos.\n denominator := div(denominator, twos)\n\n // Divide [prod1 prod0] by twos.\n prod0 := div(prod0, twos)\n\n // Flip twos such that it is 2^256 / twos. If twos is zero, then it becomes one.\n twos := add(div(sub(0, twos), twos), 1)\n }\n\n // Shift in bits from prod1 into prod0.\n prod0 |= prod1 * twos;\n\n // Invert denominator mod 2^256. Now that denominator is an odd number, it has an inverse modulo 2^256 such\n // that denominator * inv = 1 mod 2^256. Compute the inverse by starting with a seed that is correct for\n // four bits. That is, denominator * inv = 1 mod 2^4.\n uint256 inverse = (3 * denominator) ^ 2;\n\n // Use the Newton-Raphson iteration to improve the precision. Thanks to Hensel's lifting lemma, this also works\n // in modular arithmetic, doubling the correct bits in each step.\n inverse *= 2 - denominator * inverse; // inverse mod 2^8\n inverse *= 2 - denominator * inverse; // inverse mod 2^16\n inverse *= 2 - denominator * inverse; // inverse mod 2^32\n inverse *= 2 - denominator * inverse; // inverse mod 2^64\n inverse *= 2 - denominator * inverse; // inverse mod 2^128\n inverse *= 2 - denominator * inverse; // inverse mod 2^256\n\n // Because the division is now exact we can divide by multiplying with the modular inverse of denominator.\n // This will give us the correct result modulo 2^256. Since the preconditions guarantee that the outcome is\n // less than 2^256, this is the final result. We don't need to compute the high bits of the result and prod1\n // is no longer required.\n result = prod0 * inverse;\n return result;\n }\n }\n\n /**\n * @notice Calculates x * y / denominator with full precision, following the selected rounding direction.\n */\n function mulDiv(uint256 x, uint256 y, uint256 denominator, Rounding rounding) internal pure returns (uint256) {\n uint256 result = mulDiv(x, y, denominator);\n if (rounding == Rounding.Up \u0026\u0026 mulmod(x, y, denominator) \u003e 0) {\n result += 1;\n }\n return result;\n }\n\n /**\n * @dev Returns the square root of a number. If the number is not a perfect square, the value is rounded down.\n *\n * Inspired by Henry S. Warren, Jr.'s \"Hacker's Delight\" (Chapter 11).\n */\n function sqrt(uint256 a) internal pure returns (uint256) {\n if (a == 0) {\n return 0;\n }\n\n // For our first guess, we get the biggest power of 2 which is smaller than the square root of the target.\n //\n // We know that the \"msb\" (most significant bit) of our target number `a` is a power of 2 such that we have\n // `msb(a) \u003c= a \u003c 2*msb(a)`. This value can be written `msb(a)=2**k` with `k=log2(a)`.\n //\n // This can be rewritten `2**log2(a) \u003c= a \u003c 2**(log2(a) + 1)`\n // → `sqrt(2**k) \u003c= sqrt(a) \u003c sqrt(2**(k+1))`\n // → `2**(k/2) \u003c= sqrt(a) \u003c 2**((k+1)/2) \u003c= 2**(k/2 + 1)`\n //\n // Consequently, `2**(log2(a) / 2)` is a good first approximation of `sqrt(a)` with at least 1 correct bit.\n uint256 result = 1 \u003c\u003c (log2(a) \u003e\u003e 1);\n\n // At this point `result` is an estimation with one bit of precision. We know the true value is a uint128,\n // since it is the square root of a uint256. Newton's method converges quadratically (precision doubles at\n // every iteration). We thus need at most 7 iteration to turn our partial result with one bit of precision\n // into the expected uint128 result.\n unchecked {\n result = (result + a / result) \u003e\u003e 1;\n result = (result + a / result) \u003e\u003e 1;\n result = (result + a / result) \u003e\u003e 1;\n result = (result + a / result) \u003e\u003e 1;\n result = (result + a / result) \u003e\u003e 1;\n result = (result + a / result) \u003e\u003e 1;\n result = (result + a / result) \u003e\u003e 1;\n return min(result, a / result);\n }\n }\n\n /**\n * @notice Calculates sqrt(a), following the selected rounding direction.\n */\n function sqrt(uint256 a, Rounding rounding) internal pure returns (uint256) {\n unchecked {\n uint256 result = sqrt(a);\n return result + (rounding == Rounding.Up \u0026\u0026 result * result \u003c a ? 1 : 0);\n }\n }\n\n /**\n * @dev Return the log in base 2, rounded down, of a positive value.\n * Returns 0 if given 0.\n */\n function log2(uint256 value) internal pure returns (uint256) {\n uint256 result = 0;\n unchecked {\n if (value \u003e\u003e 128 \u003e 0) {\n value \u003e\u003e= 128;\n result += 128;\n }\n if (value \u003e\u003e 64 \u003e 0) {\n value \u003e\u003e= 64;\n result += 64;\n }\n if (value \u003e\u003e 32 \u003e 0) {\n value \u003e\u003e= 32;\n result += 32;\n }\n if (value \u003e\u003e 16 \u003e 0) {\n value \u003e\u003e= 16;\n result += 16;\n }\n if (value \u003e\u003e 8 \u003e 0) {\n value \u003e\u003e= 8;\n result += 8;\n }\n if (value \u003e\u003e 4 \u003e 0) {\n value \u003e\u003e= 4;\n result += 4;\n }\n if (value \u003e\u003e 2 \u003e 0) {\n value \u003e\u003e= 2;\n result += 2;\n }\n if (value \u003e\u003e 1 \u003e 0) {\n result += 1;\n }\n }\n return result;\n }\n\n /**\n * @dev Return the log in base 2, following the selected rounding direction, of a positive value.\n * Returns 0 if given 0.\n */\n function log2(uint256 value, Rounding rounding) internal pure returns (uint256) {\n unchecked {\n uint256 result = log2(value);\n return result + (rounding == Rounding.Up \u0026\u0026 1 \u003c\u003c result \u003c value ? 1 : 0);\n }\n }\n\n /**\n * @dev Return the log in base 10, rounded down, of a positive value.\n * Returns 0 if given 0.\n */\n function log10(uint256 value) internal pure returns (uint256) {\n uint256 result = 0;\n unchecked {\n if (value \u003e= 10 ** 64) {\n value /= 10 ** 64;\n result += 64;\n }\n if (value \u003e= 10 ** 32) {\n value /= 10 ** 32;\n result += 32;\n }\n if (value \u003e= 10 ** 16) {\n value /= 10 ** 16;\n result += 16;\n }\n if (value \u003e= 10 ** 8) {\n value /= 10 ** 8;\n result += 8;\n }\n if (value \u003e= 10 ** 4) {\n value /= 10 ** 4;\n result += 4;\n }\n if (value \u003e= 10 ** 2) {\n value /= 10 ** 2;\n result += 2;\n }\n if (value \u003e= 10 ** 1) {\n result += 1;\n }\n }\n return result;\n }\n\n /**\n * @dev Return the log in base 10, following the selected rounding direction, of a positive value.\n * Returns 0 if given 0.\n */\n function log10(uint256 value, Rounding rounding) internal pure returns (uint256) {\n unchecked {\n uint256 result = log10(value);\n return result + (rounding == Rounding.Up \u0026\u0026 10 ** result \u003c value ? 1 : 0);\n }\n }\n\n /**\n * @dev Return the log in base 256, rounded down, of a positive value.\n * Returns 0 if given 0.\n *\n * Adding one to the result gives the number of pairs of hex symbols needed to represent `value` as a hex string.\n */\n function log256(uint256 value) internal pure returns (uint256) {\n uint256 result = 0;\n unchecked {\n if (value \u003e\u003e 128 \u003e 0) {\n value \u003e\u003e= 128;\n result += 16;\n }\n if (value \u003e\u003e 64 \u003e 0) {\n value \u003e\u003e= 64;\n result += 8;\n }\n if (value \u003e\u003e 32 \u003e 0) {\n value \u003e\u003e= 32;\n result += 4;\n }\n if (value \u003e\u003e 16 \u003e 0) {\n value \u003e\u003e= 16;\n result += 2;\n }\n if (value \u003e\u003e 8 \u003e 0) {\n result += 1;\n }\n }\n return result;\n }\n\n /**\n * @dev Return the log in base 256, following the selected rounding direction, of a positive value.\n * Returns 0 if given 0.\n */\n function log256(uint256 value, Rounding rounding) internal pure returns (uint256) {\n unchecked {\n uint256 result = log256(value);\n return result + (rounding == Rounding.Up \u0026\u0026 1 \u003c\u003c (result \u003c\u003c 3) \u003c value ? 1 : 0);\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/utils/math/SignedMath.sol\n\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/math/SignedMath.sol)\n\n/**\n * @dev Standard signed math utilities missing in the Solidity language.\n */\nlibrary SignedMath {\n /**\n * @dev Returns the largest of two signed numbers.\n */\n function max(int256 a, int256 b) internal pure returns (int256) {\n return a \u003e b ? a : b;\n }\n\n /**\n * @dev Returns the smallest of two signed numbers.\n */\n function min(int256 a, int256 b) internal pure returns (int256) {\n return a \u003c b ? a : b;\n }\n\n /**\n * @dev Returns the average of two signed numbers without overflow.\n * The result is rounded towards zero.\n */\n function average(int256 a, int256 b) internal pure returns (int256) {\n // Formula from the book \"Hacker's Delight\"\n int256 x = (a \u0026 b) + ((a ^ b) \u003e\u003e 1);\n return x + (int256(uint256(x) \u003e\u003e 255) \u0026 (a ^ b));\n }\n\n /**\n * @dev Returns the absolute unsigned value of a signed value.\n */\n function abs(int256 n) internal pure returns (uint256) {\n unchecked {\n // must be unchecked in order to support `n = type(int256).min`\n return uint256(n \u003e= 0 ? n : -n);\n }\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// 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/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/InterfaceSummit.sol\n\ninterface InterfaceSummit {\n // ══════════════════════════════════════════ ACCEPT AGENT STATEMENTS ══════════════════════════════════════════════\n\n /**\n * @notice Accepts a receipt, which local `AgentManager` verified to have been signed by an active Notary.\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 * - Notary who signed the receipt is referenced as the \"Receipt Notary\".\n * - Notary who signed the attestation on destination chain is referenced as the \"Attestation Notary\".\n * \u003e Will revert if any of these is true:\n * \u003e - Called by anyone other than local `AgentManager`.\n * \u003e - Receipt body payload is not properly formatted.\n * \u003e - Receipt signer is in Dispute.\n * \u003e - Receipt's snapshot root is unknown.\n * @param rcptNotaryIndex Index of Receipt Notary in Agent Merkle Tree\n * @param attNotaryIndex Index of Attestation Notary in Agent Merkle Tree\n * @param sigIndex Index of stored Notary signature\n * @param attNonce Nonce of the attestation used for proving the executed message\n * @param paddedTips Padded encoded paid tips information\n * @param rcptPayload Raw payload with message execution receipt\n * @return wasAccepted Whether the receipt was accepted\n */\n function acceptReceipt(\n uint32 rcptNotaryIndex,\n uint32 attNotaryIndex,\n uint256 sigIndex,\n uint32 attNonce,\n uint256 paddedTips,\n bytes memory rcptPayload\n ) external returns (bool wasAccepted);\n\n /**\n * @notice Accepts a snapshot, which local `AgentManager` verified to have been signed by an active Guard.\n * \u003e Snapshot is a list of states for a set of Origin contracts residing on any of the chains.\n * All the states in the Guard-signed snapshot become available for Notary signing.\n * \u003e Will revert if any of these is true:\n * \u003e - Called by anyone other than local `AgentManager`.\n * \u003e - Snapshot payload is not properly formatted.\n * \u003e - Snapshot contains a state older then the Guard has previously submitted.\n * @param guardIndex Index of Guard in Agent Merkle Tree\n * @param sigIndex Index of stored Agent signature\n * @param snapPayload Raw payload with snapshot data\n */\n function acceptGuardSnapshot(uint32 guardIndex, uint256 sigIndex, bytes memory snapPayload) external;\n\n /**\n * @notice Accepts a snapshot, which local `AgentManager` verified to have been signed by an active Notary.\n * \u003e Snapshot is a list of states for a set of Origin contracts residing on any of the chains.\n * Snapshot Merkle Root is calculated and saved for valid snapshots, i.e.\n * snapshots which are only using states previously submitted by any of the Guards.\n * - Notary could use states singed by the same of different Guards 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 - Called by anyone other than local `AgentManager`.\n * \u003e - Snapshot payload is not properly formatted.\n * \u003e - Snapshot contains a state older then the Notary has previously submitted.\n * \u003e - Snapshot contains a state that no Guard has previously submitted.\n * @param notaryIndex Index of Notary in Agent Merkle Tree\n * @param sigIndex Index of stored Agent signature\n * @param agentRoot Current root of the Agent Merkle Tree\n * @param snapPayload Raw payload with snapshot data\n * @return attPayload Raw payload with data for attestation derived from Notary snapshot.\n */\n function acceptNotarySnapshot(uint32 notaryIndex, uint256 sigIndex, bytes32 agentRoot, bytes memory snapPayload)\n external\n returns (bytes memory attPayload);\n\n // ════════════════════════════════════════════════ TIPS LOGIC ═════════════════════════════════════════════════════\n\n /**\n * @notice Distributes tips using the first Receipt from the \"receipt quarantine queue\".\n * Possible scenarios:\n * - Receipt queue is empty =\u003e does nothing\n * - Receipt optimistic period is not over =\u003e does nothing\n * - Either of Notaries present in Receipt was slashed =\u003e receipt is deleted from the queue\n * - Either of Notaries present in Receipt in Dispute =\u003e receipt is moved to the end of queue\n * - None of the above =\u003e receipt tips are distributed\n * @dev Returned value makes it possible to do the following: `while (distributeTips()) {}`\n * @return queuePopped Whether the first element was popped from the queue\n */\n function distributeTips() external returns (bool queuePopped);\n\n /**\n * @notice Withdraws locked base message tips from requested domain Origin to the recipient.\n * This is done by a call to a local Origin contract, or by a manager message to the remote chain.\n * @dev This will revert, if the pending balance of origin tips (earned-claimed) is lower than requested.\n * @param origin Domain of chain to withdraw tips on\n * @param amount Amount of tips to withdraw\n */\n function withdrawTips(uint32 origin, uint256 amount) external;\n\n // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════\n\n /**\n * @notice Returns earned and claimed tips for the actor.\n * Note: Tips for address(0) belong to the Treasury.\n * @param actor Address of the actor\n * @param origin Domain where the tips were initially paid\n * @return earned Total amount of origin tips the actor has earned so far\n * @return claimed Total amount of origin tips the actor has claimed so far\n */\n function actorTips(address actor, uint32 origin) external view returns (uint128 earned, uint128 claimed);\n\n /**\n * @notice Returns the amount of receipts in the \"Receipt Quarantine Queue\".\n */\n function receiptQueueLength() external view returns (uint256);\n\n /**\n * @notice Returns the state with the highest known nonce\n * submitted by any of the currently active Guards.\n * @param origin Domain of origin chain\n * @return statePayload Raw payload with latest active Guard state for origin\n */\n function getLatestState(uint32 origin) external view returns (bytes memory statePayload);\n}\n\n// node_modules/@openzeppelin/contracts/utils/Strings.sol\n\n// OpenZeppelin Contracts (last updated v4.9.0) (utils/Strings.sol)\n\n/**\n * @dev String operations.\n */\nlibrary Strings {\n bytes16 private constant _SYMBOLS = \"0123456789abcdef\";\n uint8 private constant _ADDRESS_LENGTH = 20;\n\n /**\n * @dev Converts a `uint256` to its ASCII `string` decimal representation.\n */\n function toString(uint256 value) internal pure returns (string memory) {\n unchecked {\n uint256 length = Math.log10(value) + 1;\n string memory buffer = new string(length);\n uint256 ptr;\n /// @solidity memory-safe-assembly\n assembly {\n ptr := add(buffer, add(32, length))\n }\n while (true) {\n ptr--;\n /// @solidity memory-safe-assembly\n assembly {\n mstore8(ptr, byte(mod(value, 10), _SYMBOLS))\n }\n value /= 10;\n if (value == 0) break;\n }\n return buffer;\n }\n }\n\n /**\n * @dev Converts a `int256` to its ASCII `string` decimal representation.\n */\n function toString(int256 value) internal pure returns (string memory) {\n return string(abi.encodePacked(value \u003c 0 ? \"-\" : \"\", toString(SignedMath.abs(value))));\n }\n\n /**\n * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation.\n */\n function toHexString(uint256 value) internal pure returns (string memory) {\n unchecked {\n return toHexString(value, Math.log256(value) + 1);\n }\n }\n\n /**\n * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length.\n */\n function toHexString(uint256 value, uint256 length) internal pure returns (string memory) {\n bytes memory buffer = new bytes(2 * length + 2);\n buffer[0] = \"0\";\n buffer[1] = \"x\";\n for (uint256 i = 2 * length + 1; i \u003e 1; --i) {\n buffer[i] = _SYMBOLS[value \u0026 0xf];\n value \u003e\u003e= 4;\n }\n require(value == 0, \"Strings: hex length insufficient\");\n return string(buffer);\n }\n\n /**\n * @dev Converts an `address` with fixed length of 20 bytes to its not checksummed ASCII `string` hexadecimal representation.\n */\n function toHexString(address addr) internal pure returns (string memory) {\n return toHexString(uint256(uint160(addr)), _ADDRESS_LENGTH);\n }\n\n /**\n * @dev Returns true if the two strings are equal.\n */\n function equal(string memory a, string memory b) internal pure returns (bool) {\n return keccak256(bytes(a)) == keccak256(bytes(b));\n }\n}\n\n// node_modules/@openzeppelin/contracts-upgradeable/utils/ContextUpgradeable.sol\n\n// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)\n\n/**\n * @dev Provides information about the current execution context, including the\n * sender of the transaction and its data. While these are generally available\n * via msg.sender and msg.data, they should not be accessed in such a direct\n * manner, since when dealing with meta-transactions the account sending and\n * paying for execution may not be the actual sender (as far as an application\n * is concerned).\n *\n * This contract is only required for intermediate, library-like contracts.\n */\nabstract contract ContextUpgradeable is Initializable {\n function __Context_init() internal onlyInitializing {\n }\n\n function __Context_init_unchained() internal onlyInitializing {\n }\n function _msgSender() internal view virtual returns (address) {\n return msg.sender;\n }\n\n function _msgData() internal view virtual returns (bytes calldata) {\n return msg.data;\n }\n\n /**\n * @dev This empty reserved space is put in place to allow future versions to add new\n * variables without shifting down storage in the inheritance chain.\n * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\n */\n uint256[50] private __gap;\n}\n\n// contracts/libs/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/utils/cryptography/ECDSA.sol\n\n// OpenZeppelin Contracts (last updated v4.9.0) (utils/cryptography/ECDSA.sol)\n\n/**\n * @dev Elliptic Curve Digital Signature Algorithm (ECDSA) operations.\n *\n * These functions can be used to verify that a message was signed by the holder\n * of the private keys of a given address.\n */\nlibrary ECDSA {\n enum RecoverError {\n NoError,\n InvalidSignature,\n InvalidSignatureLength,\n InvalidSignatureS,\n InvalidSignatureV // Deprecated in v4.8\n }\n\n function _throwError(RecoverError error) private pure {\n if (error == RecoverError.NoError) {\n return; // no error: do nothing\n } else if (error == RecoverError.InvalidSignature) {\n revert(\"ECDSA: invalid signature\");\n } else if (error == RecoverError.InvalidSignatureLength) {\n revert(\"ECDSA: invalid signature length\");\n } else if (error == RecoverError.InvalidSignatureS) {\n revert(\"ECDSA: invalid signature 's' value\");\n }\n }\n\n /**\n * @dev Returns the address that signed a hashed message (`hash`) with\n * `signature` or error string. This address can then be used for verification purposes.\n *\n * The `ecrecover` EVM opcode allows for malleable (non-unique) signatures:\n * this function rejects them by requiring the `s` value to be in the lower\n * half order, and the `v` value to be either 27 or 28.\n *\n * IMPORTANT: `hash` _must_ be the result of a hash operation for the\n * verification to be secure: it is possible to craft signatures that\n * recover to arbitrary addresses for non-hashed data. A safe way to ensure\n * this is by receiving a hash of the original message (which may otherwise\n * be too long), and then calling {toEthSignedMessageHash} on it.\n *\n * Documentation for signature generation:\n * - with https://web3js.readthedocs.io/en/v1.3.4/web3-eth-accounts.html#sign[Web3.js]\n * - with https://docs.ethers.io/v5/api/signer/#Signer-signMessage[ethers]\n *\n * _Available since v4.3._\n */\n function tryRecover(bytes32 hash, bytes memory signature) internal pure returns (address, RecoverError) {\n if (signature.length == 65) {\n bytes32 r;\n bytes32 s;\n uint8 v;\n // ecrecover takes the signature parameters, and the only way to get them\n // currently is to use assembly.\n /// @solidity memory-safe-assembly\n assembly {\n r := mload(add(signature, 0x20))\n s := mload(add(signature, 0x40))\n v := byte(0, mload(add(signature, 0x60)))\n }\n return tryRecover(hash, v, r, s);\n } else {\n return (address(0), RecoverError.InvalidSignatureLength);\n }\n }\n\n /**\n * @dev Returns the address that signed a hashed message (`hash`) with\n * `signature`. This address can then be used for verification purposes.\n *\n * The `ecrecover` EVM opcode allows for malleable (non-unique) signatures:\n * this function rejects them by requiring the `s` value to be in the lower\n * half order, and the `v` value to be either 27 or 28.\n *\n * IMPORTANT: `hash` _must_ be the result of a hash operation for the\n * verification to be secure: it is possible to craft signatures that\n * recover to arbitrary addresses for non-hashed data. A safe way to ensure\n * this is by receiving a hash of the original message (which may otherwise\n * be too long), and then calling {toEthSignedMessageHash} on it.\n */\n function recover(bytes32 hash, bytes memory signature) internal pure returns (address) {\n (address recovered, RecoverError error) = tryRecover(hash, signature);\n _throwError(error);\n return recovered;\n }\n\n /**\n * @dev Overload of {ECDSA-tryRecover} that receives the `r` and `vs` short-signature fields separately.\n *\n * See https://eips.ethereum.org/EIPS/eip-2098[EIP-2098 short signatures]\n *\n * _Available since v4.3._\n */\n function tryRecover(bytes32 hash, bytes32 r, bytes32 vs) internal pure returns (address, RecoverError) {\n bytes32 s = vs \u0026 bytes32(0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff);\n uint8 v = uint8((uint256(vs) \u003e\u003e 255) + 27);\n return tryRecover(hash, v, r, s);\n }\n\n /**\n * @dev Overload of {ECDSA-recover} that receives the `r and `vs` short-signature fields separately.\n *\n * _Available since v4.2._\n */\n function recover(bytes32 hash, bytes32 r, bytes32 vs) internal pure returns (address) {\n (address recovered, RecoverError error) = tryRecover(hash, r, vs);\n _throwError(error);\n return recovered;\n }\n\n /**\n * @dev Overload of {ECDSA-tryRecover} that receives the `v`,\n * `r` and `s` signature fields separately.\n *\n * _Available since v4.3._\n */\n function tryRecover(bytes32 hash, uint8 v, bytes32 r, bytes32 s) internal pure returns (address, RecoverError) {\n // EIP-2 still allows signature malleability for ecrecover(). Remove this possibility and make the signature\n // unique. Appendix F in the Ethereum Yellow paper (https://ethereum.github.io/yellowpaper/paper.pdf), defines\n // the valid range for s in (301): 0 \u003c s \u003c secp256k1n ÷ 2 + 1, and for v in (302): v ∈ {27, 28}. Most\n // signatures from current libraries generate a unique signature with an s-value in the lower half order.\n //\n // If your library generates malleable signatures, such as s-values in the upper range, calculate a new s-value\n // with 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141 - s1 and flip v from 27 to 28 or\n // vice versa. If your library also generates signatures with 0/1 for v instead 27/28, add 27 to v to accept\n // these malleable signatures as well.\n if (uint256(s) \u003e 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0) {\n return (address(0), RecoverError.InvalidSignatureS);\n }\n\n // If the signature is valid (and not malleable), return the signer address\n address signer = ecrecover(hash, v, r, s);\n if (signer == address(0)) {\n return (address(0), RecoverError.InvalidSignature);\n }\n\n return (signer, RecoverError.NoError);\n }\n\n /**\n * @dev Overload of {ECDSA-recover} that receives the `v`,\n * `r` and `s` signature fields separately.\n */\n function recover(bytes32 hash, uint8 v, bytes32 r, bytes32 s) internal pure returns (address) {\n (address recovered, RecoverError error) = tryRecover(hash, v, r, s);\n _throwError(error);\n return recovered;\n }\n\n /**\n * @dev Returns an Ethereum Signed Message, created from a `hash`. This\n * produces hash corresponding to the one signed with the\n * https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`]\n * JSON-RPC method as part of EIP-191.\n *\n * See {recover}.\n */\n function toEthSignedMessageHash(bytes32 hash) internal pure returns (bytes32 message) {\n // 32 is the length in bytes of hash,\n // enforced by the type signature above\n /// @solidity memory-safe-assembly\n assembly {\n mstore(0x00, \"\\x19Ethereum Signed Message:\\n32\")\n mstore(0x1c, hash)\n message := keccak256(0x00, 0x3c)\n }\n }\n\n /**\n * @dev Returns an Ethereum Signed Message, created from `s`. This\n * produces hash corresponding to the one signed with the\n * https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`]\n * JSON-RPC method as part of EIP-191.\n *\n * See {recover}.\n */\n function toEthSignedMessageHash(bytes memory s) internal pure returns (bytes32) {\n return keccak256(abi.encodePacked(\"\\x19Ethereum Signed Message:\\n\", Strings.toString(s.length), s));\n }\n\n /**\n * @dev Returns an Ethereum Signed Typed Data, created from a\n * `domainSeparator` and a `structHash`. This produces hash corresponding\n * to the one signed with the\n * https://eips.ethereum.org/EIPS/eip-712[`eth_signTypedData`]\n * JSON-RPC method as part of EIP-712.\n *\n * See {recover}.\n */\n function toTypedDataHash(bytes32 domainSeparator, bytes32 structHash) internal pure returns (bytes32 data) {\n /// @solidity memory-safe-assembly\n assembly {\n let ptr := mload(0x40)\n mstore(ptr, \"\\x19\\x01\")\n mstore(add(ptr, 0x02), domainSeparator)\n mstore(add(ptr, 0x22), structHash)\n data := keccak256(ptr, 0x42)\n }\n }\n\n /**\n * @dev Returns an Ethereum Signed Data with intended validator, created from a\n * `validator` and `data` according to the version 0 of EIP-191.\n *\n * See {recover}.\n */\n function toDataWithIntendedValidatorHash(address validator, bytes memory data) internal pure returns (bytes32) {\n return keccak256(abi.encodePacked(\"\\x19\\x00\", validator, data));\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/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/inbox/StatementInbox.sol\n\n// ══════════════════════════════ LIBRARY IMPORTS ══════════════════════════════\n\n// ═════════════════════════════ INTERNAL IMPORTS ══════════════════════════════\n\n// ═════════════════════════════ EXTERNAL IMPORTS ══════════════════════════════\n\n/// @notice `StatementInbox` is the entry point for all agent-signed statements. It verifies the\n/// agent signatures, and passes the unsigned statements to the contract to consume it via `acceptX` functions. Is is\n/// also used to verify the agent-signed statements and initiate the agent slashing, should the statement be invalid.\n/// `StatementInbox` is responsible for the following:\n/// - Accepting State and Receipt Reports to initiate a dispute between Guard and Notary.\n/// - Storing all the Guard Reports with the Guard signature leading to a dispute.\n/// - Verifying State/State Reports referencing the local chain and slashing the signer if statement is invalid.\n/// - Verifying Receipt/Receipt Reports referencing the local chain and slashing the signer if statement is invalid.\nabstract contract StatementInbox is MessagingBase, StatementInboxEvents, IStatementInbox {\n using AttestationLib for bytes;\n using ReceiptLib for bytes;\n using StateLib for bytes;\n using SnapshotLib for bytes;\n\n struct StoredReport {\n uint256 sigIndex;\n bytes statementPayload;\n }\n\n // ══════════════════════════════════════════════════ STORAGE ══════════════════════════════════════════════════════\n\n address public agentManager;\n address public origin;\n address public destination;\n\n // TODO: optimize this\n bytes[] internal _storedSignatures;\n StoredReport[] internal _storedReports;\n\n /// @dev gap for upgrade safety\n uint256[45] private __GAP; // solhint-disable-line var-name-mixedcase\n\n // ════════════════════════════════════════════════ INITIALIZER ════════════════════════════════════════════════════\n\n /// @dev Initializes the contract:\n /// - Sets up `msg.sender` as the owner of the contract.\n /// - Sets up `agentManager`, `origin`, and `destination`.\n // solhint-disable-next-line func-name-mixedcase\n function __StatementInbox_init(address agentManager_, address origin_, address destination_)\n internal\n onlyInitializing\n {\n agentManager = agentManager_;\n origin = origin_;\n destination = destination_;\n __Ownable2Step_init();\n }\n\n // ══════════════════════════════════════════ SUBMIT AGENT STATEMENTS ══════════════════════════════════════════════\n\n /// @inheritdoc IStatementInbox\n // solhint-disable-next-line ordering\n function submitStateReportWithSnapshot(\n uint8 stateIndex,\n bytes memory srSignature,\n bytes memory snapPayload,\n bytes memory snapSignature\n ) external returns (bool wasAccepted) {\n // This will revert if payload is not a snapshot\n Snapshot snapshot = snapPayload.castToSnapshot();\n // This will revert if the snapshot signer is not a known Notary\n (AgentStatus memory notaryStatus,) =\n _verifySnapshot({snapshot: snapshot, snapSignature: snapSignature, verifyNotary: true});\n // Notary needs to be Active/Unstaking\n notaryStatus.verifyActiveUnstaking();\n // Check if Notary is active on this chain\n _verifyNotaryDomain(notaryStatus.domain);\n // This will revert if state index is out of range\n State state = snapshot.state(stateIndex);\n // This will revert if the report signer is not an known Guard\n (AgentStatus memory guardStatus,) = _verifyStateReport(state, srSignature);\n // Check that Guard is active\n guardStatus.verifyActive();\n _saveReport(state.unwrap().clone(), srSignature);\n // This will revert if either actor is already in dispute\n IAgentManager(agentManager).openDispute(guardStatus.index, notaryStatus.index);\n return true;\n }\n\n /// @inheritdoc IStatementInbox\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 // This will revert if payload is not a snapshot\n Snapshot snapshot = snapPayload.castToSnapshot();\n // This will revert if state index is out of range\n State state = snapshot.state(stateIndex);\n // This will revert if the report signer is not an known Guard\n (AgentStatus memory guardStatus,) = _verifyStateReport(state, srSignature);\n // Check that Guard is active\n guardStatus.verifyActive();\n // This will revert if payload is not an attestation\n Attestation att = attPayload.castToAttestation();\n // This will revert if signer is not an known Notary\n (AgentStatus memory notaryStatus,) = _verifyAttestation(att, attSignature);\n // Notary needs to be Active/Unstaking\n notaryStatus.verifyActiveUnstaking();\n // Check if Notary is active on this chain\n _verifyNotaryDomain(notaryStatus.domain);\n if (snapshot.calculateRoot() != att.snapRoot()) revert IncorrectSnapshotRoot();\n _saveReport(state.unwrap().clone(), srSignature);\n // This will revert if either actor is already in dispute\n IAgentManager(agentManager).openDispute(guardStatus.index, notaryStatus.index);\n return true;\n }\n\n /// @inheritdoc IStatementInbox\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 // This will revert if payload is not a state\n State state = statePayload.castToState();\n // This will revert if the report signer is not an known Guard\n (AgentStatus memory guardStatus,) = _verifyStateReport(state, srSignature);\n // Check that Guard is active\n guardStatus.verifyActive();\n // This will revert if payload is not an attestation\n Attestation att = attPayload.castToAttestation();\n // This will revert if signer is not a known Notary\n (AgentStatus memory notaryStatus,) = _verifyAttestation(att, attSignature);\n // Notary needs to be Active/Unstaking\n notaryStatus.verifyActiveUnstaking();\n // Check if Notary is active on this chain\n _verifyNotaryDomain(notaryStatus.domain);\n // This will revert if any of these is true:\n // - Attestation root is not equal to Merkle Root derived from State and Snapshot Proof.\n // - Snapshot Proof's first element does not match the State metadata.\n // - Snapshot Proof length exceeds Snapshot tree Height.\n // - State index is out of range.\n _verifySnapshotMerkle(att, stateIndex, state, snapProof);\n _saveReport(statePayload, srSignature);\n // This will revert if either actor is already in dispute\n IAgentManager(agentManager).openDispute(guardStatus.index, notaryStatus.index);\n return true;\n }\n\n // ══════════════════════════════════════════ VERIFY AGENT STATEMENTS ══════════════════════════════════════════════\n\n /// @inheritdoc IStatementInbox\n function verifyReceipt(bytes memory rcptPayload, bytes memory rcptSignature)\n external\n returns (bool isValidReceipt)\n {\n // This will revert if payload is not a receipt\n Receipt rcpt = rcptPayload.castToReceipt();\n // This will revert if the attestation signer is not a known Notary\n (AgentStatus memory status, address notary) = _verifyReceipt(rcpt, rcptSignature);\n // Notary needs to be Active/Unstaking\n status.verifyActiveUnstaking();\n isValidReceipt = IExecutionHub(destination).isValidReceipt(rcptPayload);\n if (!isValidReceipt) {\n emit InvalidReceipt(rcptPayload, rcptSignature);\n IAgentManager(agentManager).slashAgent(status.domain, notary, msg.sender);\n }\n }\n\n /// @inheritdoc IStatementInbox\n function verifyReceiptReport(bytes memory rcptPayload, bytes memory rrSignature)\n external\n returns (bool isValidReport)\n {\n // This will revert if payload is not a receipt\n Receipt rcpt = rcptPayload.castToReceipt();\n // This will revert if the report signer is not a known Guard\n (AgentStatus memory status, address guard) = _verifyReceiptReport(rcpt, rrSignature);\n // Guard needs to be Active/Unstaking\n status.verifyActiveUnstaking();\n // Report is valid IF AND ONLY IF the reported receipt in invalid\n isValidReport = !IExecutionHub(destination).isValidReceipt(rcptPayload);\n if (!isValidReport) {\n emit InvalidReceiptReport(rcptPayload, rrSignature);\n IAgentManager(agentManager).slashAgent(status.domain, guard, msg.sender);\n }\n }\n\n /// @inheritdoc IStatementInbox\n function verifyStateWithAttestation(\n uint8 stateIndex,\n bytes memory snapPayload,\n bytes memory attPayload,\n bytes memory attSignature\n ) external returns (bool isValidState) {\n // This will revert if payload is not an attestation\n Attestation att = attPayload.castToAttestation();\n // This will revert if the attestation signer is not a known Notary\n (AgentStatus memory status, address notary) = _verifyAttestation(att, attSignature);\n // Notary needs to be Active/Unstaking\n status.verifyActiveUnstaking();\n // This will revert if payload is not a snapshot\n Snapshot snapshot = snapPayload.castToSnapshot();\n if (snapshot.calculateRoot() != att.snapRoot()) revert IncorrectSnapshotRoot();\n // This will revert if state does not refer to this chain\n bytes memory statePayload = snapshot.state(stateIndex).unwrap().clone();\n isValidState = IStateHub(origin).isValidState(statePayload);\n if (!isValidState) {\n emit InvalidStateWithAttestation(stateIndex, statePayload, attPayload, attSignature);\n IAgentManager(agentManager).slashAgent(status.domain, notary, msg.sender);\n }\n }\n\n /// @inheritdoc IStatementInbox\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 // This will revert if payload is not an attestation\n Attestation att = attPayload.castToAttestation();\n // This will revert if the attestation signer is not a known Notary\n (AgentStatus memory status, address notary) = _verifyAttestation(att, attSignature);\n // Notary needs to be Active/Unstaking\n status.verifyActiveUnstaking();\n // This will revert if payload is not a state\n State state = statePayload.castToState();\n // This will revert if any of these is true:\n // - Attestation root is not equal to Merkle Root derived from State and Snapshot Proof.\n // - Snapshot Proof's first element does not match the State metadata.\n // - Snapshot Proof length exceeds Snapshot tree Height.\n // - State index is out of range.\n _verifySnapshotMerkle(att, stateIndex, state, snapProof);\n // This will revert if state does not refer to this chain\n isValidState = IStateHub(origin).isValidState(statePayload);\n if (!isValidState) {\n emit InvalidStateWithAttestation(stateIndex, statePayload, attPayload, attSignature);\n IAgentManager(agentManager).slashAgent(status.domain, notary, msg.sender);\n }\n }\n\n /// @inheritdoc IStatementInbox\n function verifyStateWithSnapshot(uint8 stateIndex, bytes memory snapPayload, bytes memory snapSignature)\n external\n returns (bool isValidState)\n {\n // This will revert if payload is not a snapshot\n Snapshot snapshot = snapPayload.castToSnapshot();\n // This will revert if the snapshot signer is not a known Guard/Notary\n (AgentStatus memory status, address agent) =\n _verifySnapshot({snapshot: snapshot, snapSignature: snapSignature, verifyNotary: false});\n // Agent needs to be Active/Unstaking\n status.verifyActiveUnstaking();\n // This will revert if state does not refer to this chain\n isValidState = IStateHub(origin).isValidState(snapshot.state(stateIndex).unwrap().clone());\n if (!isValidState) {\n emit InvalidStateWithSnapshot(stateIndex, snapPayload, snapSignature);\n IAgentManager(agentManager).slashAgent(status.domain, agent, msg.sender);\n }\n }\n\n /// @inheritdoc IStatementInbox\n function verifyStateReport(bytes memory statePayload, bytes memory srSignature)\n external\n returns (bool isValidReport)\n {\n // This will revert if payload is not a state\n State state = statePayload.castToState();\n // This will revert if the report signer is not a known Guard\n (AgentStatus memory status, address guard) = _verifyStateReport(state, srSignature);\n // Guard needs to be Active/Unstaking\n status.verifyActiveUnstaking();\n // Report is valid IF AND ONLY IF the reported state in invalid\n // This will revert if the reported state does not refer to this chain\n isValidReport = !IStateHub(origin).isValidState(statePayload);\n if (!isValidReport) {\n emit InvalidStateReport(statePayload, srSignature);\n IAgentManager(agentManager).slashAgent(status.domain, guard, msg.sender);\n }\n }\n\n // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════\n\n /// @inheritdoc IStatementInbox\n function getReportsAmount() external view returns (uint256) {\n return _storedReports.length;\n }\n\n /// @inheritdoc IStatementInbox\n function getGuardReport(uint256 index)\n external\n view\n returns (bytes memory statementPayload, bytes memory reportSignature)\n {\n if (index \u003e= _storedReports.length) revert IndexOutOfRange();\n StoredReport memory storedReport = _storedReports[index];\n statementPayload = storedReport.statementPayload;\n reportSignature = _storedSignatures[storedReport.sigIndex];\n }\n\n /// @inheritdoc IStatementInbox\n function getStoredSignature(uint256 index) external view returns (bytes memory) {\n return _storedSignatures[index];\n }\n\n // ══════════════════════════════════════════════ INTERNAL LOGIC ═══════════════════════════════════════════════════\n\n /// @dev Saves the statement reported by Guard as invalid and the Guard Report signature.\n function _saveReport(bytes memory statementPayload, bytes memory reportSignature) internal {\n uint256 sigIndex = _saveSignature(reportSignature);\n _storedReports.push(StoredReport(sigIndex, statementPayload));\n }\n\n /// @dev Saves the signature and returns its index.\n function _saveSignature(bytes memory signature) internal returns (uint256 sigIndex) {\n sigIndex = _storedSignatures.length;\n _storedSignatures.push(signature);\n }\n\n // ═══════════════════════════════════════════════ AGENT CHECKS ════════════════════════════════════════════════════\n\n /**\n * @dev Recovers a signer from a hashed message, and a EIP-191 signature for it.\n * Will revert, if the signer is not a known agent.\n * @dev Agent flag could be any of these: Active/Unstaking/Resting/Fraudulent/Slashed\n * Further checks need to be performed in a caller function.\n * @param hashedStatement Hash of the statement that was signed by an Agent\n * @param signature Agent signature for the hashed statement\n * @return status Struct representing agent status:\n * - flag Unknown/Active/Unstaking/Resting/Fraudulent/Slashed\n * - domain Domain where agent is/was active\n * - index Index of agent in the Agent Merkle Tree\n * @return agent Agent that signed the statement\n */\n function _recoverAgent(bytes32 hashedStatement, bytes memory signature)\n internal\n view\n returns (AgentStatus memory status, address agent)\n {\n bytes32 ethSignedMsg = ECDSA.toEthSignedMessageHash(hashedStatement);\n agent = ECDSA.recover(ethSignedMsg, signature);\n status = IAgentManager(agentManager).agentStatus(agent);\n // Discard signature of unknown agents.\n // Further flag checks are supposed to be performed in a caller function.\n status.verifyKnown();\n }\n\n /// @dev Verifies that Notary signature is active on local domain.\n function _verifyNotaryDomain(uint32 notaryDomain) internal view {\n // Notary needs to be from the local domain (if contract is not deployed on Synapse Chain).\n // Or Notary could be from any domain (if contract is deployed on Synapse Chain).\n if (notaryDomain != localDomain \u0026\u0026 localDomain != synapseDomain) revert IncorrectAgentDomain();\n }\n\n // ════════════════════════════════════════ ATTESTATION RELATED CHECKS ═════════════════════════════════════════════\n\n /**\n * @dev Internal function to verify the signed attestation payload.\n * Reverts if any of these is true:\n * - Attestation signer is not a known Notary.\n * @param att Typed memory view over attestation payload\n * @param attSignature Notary signature for the attestation\n * @return status Struct representing agent status, see {_recoverAgent}\n * @return notary Notary that signed the snapshot\n */\n function _verifyAttestation(Attestation att, bytes memory attSignature)\n internal\n view\n returns (AgentStatus memory status, address notary)\n {\n // This will revert if signer is not a known agent\n (status, notary) = _recoverAgent(att.hashValid(), attSignature);\n // Attestation signer needs to be a Notary, not a Guard\n if (status.domain == 0) revert AgentNotNotary();\n }\n\n /**\n * @dev Internal function to verify the signed attestation report payload.\n * Reverts if any of these is true:\n * - Report signer is not a known Guard.\n * @param att Typed memory view over attestation payload that Guard reports as invalid\n * @param arSignature Guard signature for the \"invalid attestation\" report\n * @return status Struct representing guard status, see {_recoverAgent}\n * @return guard Guard that signed the report\n */\n function _verifyAttestationReport(Attestation att, bytes memory arSignature)\n internal\n view\n returns (AgentStatus memory status, address guard)\n {\n // This will revert if signer is not a known agent\n (status, guard) = _recoverAgent(att.hashInvalid(), arSignature);\n // Report signer needs to be a Guard, not a Notary\n if (status.domain != 0) revert AgentNotGuard();\n }\n\n // ══════════════════════════════════════════ RECEIPT RELATED CHECKS ═══════════════════════════════════════════════\n\n /**\n * @dev Internal function to verify the signed receipt payload.\n * Reverts if any of these is true:\n * - Receipt signer is not a known Notary.\n * @param rcpt Typed memory view over receipt payload\n * @param rcptSignature Notary signature for the receipt\n * @return status Struct representing agent status, see {_recoverAgent}\n * @return notary Notary that signed the snapshot\n */\n function _verifyReceipt(Receipt rcpt, bytes memory rcptSignature)\n internal\n view\n returns (AgentStatus memory status, address notary)\n {\n // This will revert if signer is not a known agent\n (status, notary) = _recoverAgent(rcpt.hashValid(), rcptSignature);\n // Receipt signer needs to be a Notary, not a Guard\n if (status.domain == 0) revert AgentNotNotary();\n }\n\n /**\n * @dev Internal function to verify the signed receipt report payload.\n * Reverts if any of these is true:\n * - Report signer is not a known Guard.\n * @param rcpt Typed memory view over receipt payload that Guard reports as invalid\n * @param rrSignature Guard signature for the \"invalid receipt\" report\n * @return status Struct representing guard status, see {_recoverAgent}\n * @return guard Guard that signed the report\n */\n function _verifyReceiptReport(Receipt rcpt, bytes memory rrSignature)\n internal\n view\n returns (AgentStatus memory status, address guard)\n {\n // This will revert if signer is not a known agent\n (status, guard) = _recoverAgent(rcpt.hashInvalid(), rrSignature);\n // Report signer needs to be a Guard, not a Notary\n if (status.domain != 0) revert AgentNotGuard();\n }\n\n // ═══════════════════════════════════════ STATE/SNAPSHOT RELATED CHECKS ═══════════════════════════════════════════\n\n /**\n * @dev Internal function to verify the signed snapshot report payload.\n * Reverts if any of these is true:\n * - Report signer is not a known Guard.\n * @param state Typed memory view over state payload that Guard reports as invalid\n * @param srSignature Guard signature for the report\n * @return status Struct representing guard status, see {_recoverAgent}\n * @return guard Guard that signed the report\n */\n function _verifyStateReport(State state, bytes memory srSignature)\n internal\n view\n returns (AgentStatus memory status, address guard)\n {\n // This will revert if signer is not a known agent\n (status, guard) = _recoverAgent(state.hashInvalid(), srSignature);\n // Report signer needs to be a Guard, not a Notary\n if (status.domain != 0) revert AgentNotGuard();\n }\n\n /**\n * @dev Internal function to verify the signed snapshot payload.\n * Reverts if any of these is true:\n * - Snapshot signer is not a known Agent.\n * - Snapshot signer is not a Notary (if verifyNotary is true).\n * @param snapshot Typed memory view over snapshot payload\n * @param snapSignature Agent signature for the snapshot\n * @param verifyNotary If true, snapshot signer needs to be a Notary, not a Guard\n * @return status Struct representing agent status, see {_recoverAgent}\n * @return agent Agent that signed the snapshot\n */\n function _verifySnapshot(Snapshot snapshot, bytes memory snapSignature, bool verifyNotary)\n internal\n view\n returns (AgentStatus memory status, address agent)\n {\n // This will revert if signer is not a known agent\n (status, agent) = _recoverAgent(snapshot.hashValid(), snapSignature);\n // If requested, snapshot signer needs to be a Notary, not a Guard\n if (verifyNotary \u0026\u0026 status.domain == 0) revert AgentNotNotary();\n }\n\n // ═══════════════════════════════════════════ MERKLE RELATED CHECKS ═══════════════════════════════════════════════\n\n /**\n * @dev Internal function to verify that snapshot roots match.\n * Reverts if any of these is true:\n * - Attestation root is not equal to Merkle Root derived from State and Snapshot Proof.\n * - Snapshot Proof's first element does not match the State metadata.\n * - Snapshot Proof length exceeds Snapshot tree Height.\n * - State index is out of range.\n * @param att Typed memory view over Attestation\n * @param stateIndex Index of state in the snapshot\n * @param state Typed memory view over the provided state payload\n * @param snapProof Raw payload with snapshot data\n */\n function _verifySnapshotMerkle(Attestation att, uint8 stateIndex, State state, bytes32[] memory snapProof)\n internal\n pure\n {\n // Snapshot proof first element should match State metadata (aka \"right sub-leaf\")\n (, bytes32 rightSubLeaf) = state.subLeafs();\n if (snapProof[0] != rightSubLeaf) revert IncorrectSnapshotProof();\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(state.root(), state.origin(), snapProof, stateIndex);\n // Snapshot root should match the attestation root\n if (att.snapRoot() != snapshotRoot) revert IncorrectSnapshotRoot();\n }\n}\n\n// contracts/inbox/Inbox.sol\n\n// ══════════════════════════════ LIBRARY IMPORTS ══════════════════════════════\n\n// ═════════════════════════════ INTERNAL IMPORTS ══════════════════════════════\n\n/// @notice `Inbox` is the child of `StatementInbox` contract, that is used on Synapse Chain.\n/// In addition to the functionality of `StatementInbox`, it also:\n/// - Accepts Guard and Notary Snapshots and passes them to `Summit` contract.\n/// - Accepts Notary-signed Receipts and passes them to `Summit` contract.\n/// - Accepts Receipt Reports to initiate a dispute between Guard and Notary.\n/// - Verifies Attestations and Attestation Reports, and slashes the signer if they are invalid.\ncontract Inbox is StatementInbox, InboxEvents, InterfaceInbox {\n using AttestationLib for bytes;\n using ReceiptLib for bytes;\n using SnapshotLib for bytes;\n\n // Struct to get around stack too deep error. TODO: revisit this\n struct ReceiptInfo {\n AgentStatus rcptNotaryStatus;\n address notary;\n uint32 attNonce;\n AgentStatus attNotaryStatus;\n }\n\n // ══════════════════════════════════════════════════ STORAGE ══════════════════════════════════════════════════════\n\n // The address of the Summit contract.\n address public summit;\n\n // ═════════════════════════════════════════ CONSTRUCTOR \u0026 INITIALIZER ═════════════════════════════════════════════\n\n constructor(uint32 synapseDomain_) MessagingBase(\"0.0.3\", synapseDomain_) {\n if (localDomain != synapseDomain) revert MustBeSynapseDomain();\n }\n\n /// @notice Initializes `Inbox` contract:\n /// - Sets `msg.sender` as the owner of the contract\n /// - Sets `agentManager`, `origin`, `destination` and `summit` addresses\n function initialize(address agentManager_, address origin_, address destination_, address summit_)\n external\n initializer\n {\n __StatementInbox_init(agentManager_, origin_, destination_);\n summit = summit_;\n }\n\n // ══════════════════════════════════════════ SUBMIT AGENT STATEMENTS ══════════════════════════════════════════════\n\n /// @inheritdoc InterfaceInbox\n function submitSnapshot(bytes memory snapPayload, bytes memory snapSignature)\n external\n returns (bytes memory attPayload, bytes32 agentRoot_, uint256[] memory snapGas)\n {\n // This will revert if payload is not a snapshot\n Snapshot snapshot = snapPayload.castToSnapshot();\n // This will revert if the signer is not a known Guard/Notary\n (AgentStatus memory status, address agent) =\n _verifySnapshot({snapshot: snapshot, snapSignature: snapSignature, verifyNotary: false});\n // Check that Agent is active\n status.verifyActive();\n // Store Agent signature for the Snapshot\n uint256 sigIndex = _saveSignature(snapSignature);\n if (status.domain == 0) {\n // Guard that is in Dispute could still submit new snapshots, so we don't check that\n InterfaceSummit(summit).acceptGuardSnapshot({\n guardIndex: status.index,\n sigIndex: sigIndex,\n snapPayload: snapPayload\n });\n } else {\n // Get current agentRoot from AgentManager\n agentRoot_ = IAgentManager(agentManager).agentRoot();\n // This will revert if Notary is in Dispute\n attPayload = InterfaceSummit(summit).acceptNotarySnapshot({\n notaryIndex: status.index,\n sigIndex: sigIndex,\n agentRoot: agentRoot_,\n snapPayload: snapPayload\n });\n ChainGas[] memory snapGas_ = snapshot.snapGas();\n // Pass created attestation to Destination to enable executing messages coming to Synapse Chain\n InterfaceDestination(destination).acceptAttestation(\n status.index, type(uint256).max, attPayload, agentRoot_, snapGas_\n );\n // Use assembly to cast ChainGas[] to uint256[] without copying. Highest bits are left zeroed.\n // solhint-disable-next-line no-inline-assembly\n assembly {\n snapGas := snapGas_\n }\n }\n emit SnapshotAccepted(status.domain, agent, snapPayload, snapSignature);\n }\n\n /// @inheritdoc InterfaceInbox\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 // Struct to get around stack too deep error.\n ReceiptInfo memory info;\n // This will revert if payload is not a receipt\n Receipt rcpt = rcptPayload.castToReceipt();\n // This will revert if the receipt signer is not a known Notary\n (info.rcptNotaryStatus, info.notary) = _verifyReceipt(rcpt, rcptSignature);\n // Receipt Notary needs to be Active\n info.rcptNotaryStatus.verifyActive();\n info.attNonce = IExecutionHub(destination).getAttestationNonce(rcpt.snapshotRoot());\n if (info.attNonce == 0) revert IncorrectSnapshotRoot();\n // Attestation Notary domain needs to match the destination domain\n info.attNotaryStatus = IAgentManager(agentManager).agentStatus(rcpt.attNotary());\n if (info.attNotaryStatus.domain != rcpt.destination()) revert IncorrectAgentDomain();\n // Check that the correct tip values for the message were provided\n _verifyReceiptTips(rcpt.messageHash(), paddedTips, headerHash, bodyHash);\n // Store Notary signature for the Receipt\n uint256 sigIndex = _saveSignature(rcptSignature);\n // This will revert if Receipt Notary is in Dispute\n wasAccepted = InterfaceSummit(summit).acceptReceipt({\n rcptNotaryIndex: info.rcptNotaryStatus.index,\n attNotaryIndex: info.attNotaryStatus.index,\n sigIndex: sigIndex,\n attNonce: info.attNonce,\n paddedTips: paddedTips,\n rcptPayload: rcptPayload\n });\n if (wasAccepted) {\n emit ReceiptAccepted(info.rcptNotaryStatus.domain, info.notary, rcptPayload, rcptSignature);\n }\n }\n\n /// @inheritdoc InterfaceInbox\n function submitReceiptReport(bytes memory rcptPayload, bytes memory rcptSignature, bytes memory rrSignature)\n external\n returns (bool wasAccepted)\n {\n // This will revert if payload is not a receipt\n Receipt rcpt = rcptPayload.castToReceipt();\n // This will revert if the receipt signer is not a known Guard\n (AgentStatus memory guardStatus,) = _verifyReceiptReport(rcpt, rrSignature);\n // Guard needs to be Active\n guardStatus.verifyActive();\n // This will revert if report signer is not a known Notary\n (AgentStatus memory notaryStatus,) = _verifyReceipt(rcpt, rcptSignature);\n // Notary needs to be Active/Unstaking\n notaryStatus.verifyActiveUnstaking();\n _saveReport(rcptPayload, rrSignature);\n // This will revert if either actor is already in dispute\n IAgentManager(agentManager).openDispute(guardStatus.index, notaryStatus.index);\n return true;\n }\n\n /// @inheritdoc InterfaceInbox\n function passReceipt(uint32 attNotaryIndex, uint32 attNonce, uint256 paddedTips, bytes memory rcptPayload)\n external\n returns (bool wasAccepted)\n {\n // Only Destination can pass receipts\n if (msg.sender != destination) revert CallerNotDestination();\n return InterfaceSummit(summit).acceptReceipt({\n rcptNotaryIndex: attNotaryIndex,\n attNotaryIndex: attNotaryIndex,\n sigIndex: type(uint256).max,\n attNonce: attNonce,\n paddedTips: paddedTips,\n rcptPayload: rcptPayload\n });\n }\n\n // ══════════════════════════════════════════ VERIFY AGENT STATEMENTS ══════════════════════════════════════════════\n\n /// @inheritdoc InterfaceInbox\n function verifyAttestation(bytes memory attPayload, bytes memory attSignature)\n external\n returns (bool isValidAttestation)\n {\n // This will revert if payload is not an attestation\n Attestation att = attPayload.castToAttestation();\n // This will revert if the attestation signer is not a known Notary\n (AgentStatus memory status, address notary) = _verifyAttestation(att, attSignature);\n // Notary needs to be Active/Unstaking\n status.verifyActiveUnstaking();\n isValidAttestation = ISnapshotHub(summit).isValidAttestation(attPayload);\n if (!isValidAttestation) {\n emit InvalidAttestation(attPayload, attSignature);\n IAgentManager(agentManager).slashAgent(status.domain, notary, msg.sender);\n }\n }\n\n /// @inheritdoc InterfaceInbox\n function verifyAttestationReport(bytes memory attPayload, bytes memory arSignature)\n external\n returns (bool isValidReport)\n {\n // This will revert if payload is not an attestation\n Attestation att = attPayload.castToAttestation();\n // This will revert if the report signer is not a known Guard\n (AgentStatus memory status, address guard) = _verifyAttestationReport(att, arSignature);\n // Guard needs to be Active/Unstaking\n status.verifyActiveUnstaking();\n // Report is valid IF AND ONLY IF the reported attestation in invalid\n isValidReport = !ISnapshotHub(summit).isValidAttestation(attPayload);\n if (!isValidReport) {\n emit InvalidAttestationReport(attPayload, arSignature);\n IAgentManager(agentManager).slashAgent(status.domain, guard, msg.sender);\n }\n }\n\n // ══════════════════════════════════════════════ INTERNAL VIEWS ═══════════════════════════════════════════════════\n\n /// @dev Verifies that tips proof matches the message hash.\n function _verifyReceiptTips(bytes32 msgHash, uint256 paddedTips, bytes32 headerHash, bytes32 bodyHash)\n internal\n pure\n {\n Tips tips = TipsLib.wrapPadded(paddedTips);\n // full message leaf is (header, baseMessage), while base message leaf is (tips, remainingBody).\n if (MerkleMath.getParent(headerHash, MerkleMath.getParent(tips.leaf(), bodyHash)) != msgHash) {\n revert IncorrectTipsProof();\n }\n }\n}\n","language":"Solidity","languageVersion":"0.8.17","compilerVersion":"0.8.17","compilerOptions":"--combined-json bin,bin-runtime,srcmap,srcmap-runtime,abi,userdoc,devdoc,metadata,hashes --optimize --optimize-runs 10000 --allow-paths ., ./, ../","srcMap":"47478:12582:0:-:0;;;;;;;;;;;;;;;-1:-1:-1;;;47478:12582:0;;;;;;;;;;;;;;;;;","srcMapRuntime":"47478:12582:0:-:0;;;;;;;;","abiDefinition":[],"userDoc":{"kind":"user","methods":{},"version":1},"developerDoc":{"details":"Standard math utilities missing in the Solidity language.","kind":"dev","methods":{},"version":1},"metadata":"{\"compiler\":{\"version\":\"0.8.17+commit.8df45f5f\"},\"language\":\"Solidity\",\"output\":{\"abi\":[],\"devdoc\":{\"details\":\"Standard math utilities missing in the Solidity language.\",\"kind\":\"dev\",\"methods\":{},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"solidity/Inbox.sol\":\"Math\"},\"evmVersion\":\"london\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\"},\"optimizer\":{\"enabled\":true,\"runs\":10000},\"remappings\":[]},\"sources\":{\"solidity/Inbox.sol\":{\"keccak256\":\"0x9b516081a036814c0169e20e484d4a5499066b7a6f48fada952b5e844a1ca3e5\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://32bde393b3f24ef4307d9626d4143f337b3c0bd34e17bb969fd5a15221d96987\",\"dweb:/ipfs/QmTkt2XZRtgsbSpmsVQUM3c4ebETQoDVYbmEV9yheBghnr\"]}},\"version\":1}"},"hashes":{}},"solidity/Inbox.sol:MemViewLib":{"code":"0x60566037600b82828239805160001a607314602a57634e487b7160e01b600052600060045260246000fd5b30600052607381538281f3fe73000000000000000000000000000000000000000030146080604052600080fdfea26469706673582212206a026a22c4c57ac82b427bfebc6f7c6a71e72db199aee079d6bc0e8cdb4965eb64736f6c63430008110033","runtime-code":"0x73000000000000000000000000000000000000000030146080604052600080fdfea26469706673582212206a026a22c4c57ac82b427bfebc6f7c6a71e72db199aee079d6bc0e8cdb4965eb64736f6c63430008110033","info":{"source":"// SPDX-License-Identifier: MIT\npragma solidity =0.8.17 ^0.8.0 ^0.8.1 ^0.8.2;\n\n// contracts/events/InboxEvents.sol\n\nabstract contract InboxEvents {\n /**\n * @notice Emitted when a snapshot is accepted by the Summit contract.\n * @param domain Domain where the signed Agent is active (ZERO for Guards)\n * @param agent Agent who signed the snapshot\n * @param snapPayload Raw payload with snapshot data\n * @param snapSignature Agent signature for the snapshot\n */\n event SnapshotAccepted(uint32 indexed domain, address indexed agent, bytes snapPayload, bytes snapSignature);\n\n /**\n * @notice Emitted when a snapshot is accepted by the Summit contract.\n * @param domain Domain where the signed Notary is active\n * @param notary Notary who signed the attestation\n * @param rcptPayload Raw payload with receipt data\n * @param rcptSignature Notary signature for the receipt\n */\n event ReceiptAccepted(uint32 domain, address notary, bytes rcptPayload, bytes rcptSignature);\n\n /**\n * @notice Emitted when a proof of invalid attestation is submitted.\n * @param attPayload Raw payload with Attestation data\n * @param attSignature Notary signature for the attestation\n */\n event InvalidAttestation(bytes attPayload, bytes attSignature);\n\n /**\n * @notice Emitted when a proof of invalid attestation report is submitted.\n * @param arPayload Raw payload with report data\n * @param arSignature Guard signature for the report\n */\n event InvalidAttestationReport(bytes arPayload, bytes arSignature);\n}\n\n// contracts/events/StatementInboxEvents.sol\n\nabstract contract StatementInboxEvents {\n // ════════════════════════════════════════════ STATEMENT ACCEPTED ═════════════════════════════════════════════════\n\n /**\n * @notice Emitted when a snapshot is accepted by the Destination contract.\n * @param domain Domain where the signed Notary is active\n * @param notary Notary who signed the attestation\n * @param attPayload Raw payload with attestation data\n * @param attSignature Notary signature for the attestation\n */\n event AttestationAccepted(uint32 domain, address notary, bytes attPayload, bytes attSignature);\n\n // ═════════════════════════════════════════ INVALID STATEMENT PROVED ══════════════════════════════════════════════\n\n /**\n * @notice Emitted when a proof of invalid receipt statement is submitted.\n * @param rcptPayload Raw payload with the receipt statement\n * @param rcptSignature Notary signature for the receipt statement\n */\n event InvalidReceipt(bytes rcptPayload, bytes rcptSignature);\n\n /**\n * @notice Emitted when a proof of invalid receipt report is submitted.\n * @param rrPayload Raw payload with report data\n * @param rrSignature Guard signature for the report\n */\n event InvalidReceiptReport(bytes rrPayload, bytes rrSignature);\n\n /**\n * @notice Emitted when a proof of invalid state in the signed attestation is submitted.\n * @param stateIndex Index of invalid state in the snapshot\n * @param statePayload Raw payload with state data\n * @param attPayload Raw payload with Attestation data for snapshot\n * @param attSignature Notary signature for the attestation\n */\n event InvalidStateWithAttestation(uint8 stateIndex, bytes statePayload, bytes attPayload, bytes attSignature);\n\n /**\n * @notice Emitted when a proof of invalid state in the signed snapshot is submitted.\n * @param stateIndex Index of invalid state in the snapshot\n * @param snapPayload Raw payload with snapshot data\n * @param snapSignature Agent signature for the snapshot\n */\n event InvalidStateWithSnapshot(uint8 stateIndex, bytes snapPayload, bytes snapSignature);\n\n /**\n * @notice Emitted when a proof of invalid state report is submitted.\n * @param srPayload Raw payload with report data\n * @param srSignature Guard signature for the report\n */\n event InvalidStateReport(bytes srPayload, bytes srSignature);\n}\n\n// contracts/interfaces/ISnapshotHub.sol\n\ninterface ISnapshotHub {\n /**\n * @notice Check that a given attestation is valid: matches the historical attestation\n * derived from an accepted Notary snapshot.\n * @dev Will revert if any of these is true:\n * - Attestation payload is not properly formatted.\n * @param attPayload Raw payload with attestation data\n * @return isValid Whether the provided attestation is valid\n */\n function isValidAttestation(bytes memory attPayload) external view returns (bool isValid);\n\n /**\n * @notice Returns saved attestation with the given nonce.\n * @dev Reverts if attestation with given nonce hasn't been created yet.\n * @param attNonce Nonce for the attestation\n * @return attPayload Raw payload with formatted Attestation data\n * @return agentRoot Agent root hash used for the attestation\n * @return snapGas Snapshot gas data used for the attestation\n */\n function getAttestation(uint32 attNonce)\n external\n view\n returns (bytes memory attPayload, bytes32 agentRoot, uint256[] memory snapGas);\n\n /**\n * @notice Returns the state with the highest known nonce submitted by a given Agent.\n * @param origin Domain of origin chain\n * @param agent Agent address\n * @return statePayload Raw payload with agent's latest state for origin\n */\n function getLatestAgentState(uint32 origin, address agent) external view returns (bytes memory statePayload);\n\n /**\n * @notice Returns latest saved attestation for a Notary.\n * @param notary Notary address\n * @return attPayload Raw payload with formatted Attestation data\n * @return agentRoot Agent root hash used for the attestation\n * @return snapGas Snapshot gas data used for the attestation\n */\n function getLatestNotaryAttestation(address notary)\n external\n view\n returns (bytes memory attPayload, bytes32 agentRoot, uint256[] memory snapGas);\n\n /**\n * @notice Returns Guard snapshot from the list of all accepted Guard snapshots.\n * @dev Reverts if snapshot with given index hasn't been accepted yet.\n * @param index Snapshot index in the list of all Guard snapshots\n * @return snapPayload Raw payload with Guard snapshot\n * @return snapSignature Raw payload with Guard signature for snapshot\n */\n function getGuardSnapshot(uint256 index)\n external\n view\n returns (bytes memory snapPayload, bytes memory snapSignature);\n\n /**\n * @notice Returns Notary snapshot from the list of all accepted Guard snapshots.\n * @dev Reverts if snapshot with given index hasn't been accepted yet.\n * @param index Snapshot index in the list of all Notary snapshots\n * @return snapPayload Raw payload with Notary snapshot\n * @return snapSignature Raw payload with Notary signature for snapshot\n */\n function getNotarySnapshot(uint256 index)\n external\n view\n returns (bytes memory snapPayload, bytes memory snapSignature);\n\n /**\n * @notice Returns Notary snapshot that was used for creating a given attestation.\n * @dev Reverts if any of these is true:\n * - Attestation payload is not properly formatted.\n * - Attestation is invalid (doesn't have a matching Notary snapshot).\n * @param attPayload Raw payload with attestation data\n * @return snapPayload Raw payload with Notary snapshot\n * @return snapSignature Raw payload with Notary signature for snapshot\n */\n function getNotarySnapshot(bytes memory attPayload)\n external\n view\n returns (bytes memory snapPayload, bytes memory snapSignature);\n\n /**\n * @notice Returns proof of inclusion of (root, origin) fields of a given snapshot's state\n * into the Snapshot Merkle Tree for a given attestation.\n * @dev Reverts if any of these is true:\n * - Attestation with given nonce hasn't been created yet.\n * - State index is out of range of snapshot list.\n * @param attNonce Nonce for the attestation\n * @param stateIndex Index of state in the attestation's snapshot\n * @return snapProof The snapshot proof\n */\n function getSnapshotProof(uint32 attNonce, uint8 stateIndex) external view returns (bytes32[] memory snapProof);\n}\n\n// contracts/interfaces/IStateHub.sol\n\ninterface IStateHub {\n /**\n * @notice Check that a given state is valid: matches the historical state of Origin contract.\n * Note: any Agent including an invalid state in their snapshot will be slashed\n * upon providing the snapshot and agent signature for it to Origin contract.\n * @dev Will revert if any of these is true:\n * - State payload is not properly formatted.\n * @param statePayload Raw payload with state data\n * @return isValid Whether the provided state is valid\n */\n function isValidState(bytes memory statePayload) external view returns (bool isValid);\n\n /**\n * @notice Returns the amount of saved states so far.\n * @dev This includes the initial state of \"empty Origin Merkle Tree\".\n */\n function statesAmount() external view returns (uint256);\n\n /**\n * @notice Suggest the data (state after latest sent message) to sign for an Agent.\n * Note: signing the suggested state data will will never lead to slashing of the actor,\n * assuming they have confirmed that the block, which number is included in the data,\n * is not subject to reorganization (which is different for every observed chain).\n * @return statePayload Raw payload with the latest state data\n */\n function suggestLatestState() external view returns (bytes memory statePayload);\n\n /**\n * @notice Given the historical nonce, suggest the state data to sign for an Agent.\n * Note: signing the suggested state data will will never lead to slashing of the actor,\n * assuming they have confirmed that the block, which number is included in the data,\n * is not subject to reorganization (which is different for every observed chain).\n * @param nonce Historical nonce to form a state\n * @return statePayload Raw payload with historical state data\n */\n function suggestState(uint32 nonce) external view returns (bytes memory statePayload);\n}\n\n// contracts/interfaces/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/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// node_modules/@openzeppelin/contracts/utils/math/Math.sol\n\n// OpenZeppelin Contracts (last updated v4.9.0) (utils/math/Math.sol)\n\n/**\n * @dev Standard math utilities missing in the Solidity language.\n */\nlibrary Math {\n enum Rounding {\n Down, // Toward negative infinity\n Up, // Toward infinity\n Zero // Toward zero\n }\n\n /**\n * @dev Returns the largest of two numbers.\n */\n function max(uint256 a, uint256 b) internal pure returns (uint256) {\n return a \u003e b ? a : b;\n }\n\n /**\n * @dev Returns the smallest of two numbers.\n */\n function min(uint256 a, uint256 b) internal pure returns (uint256) {\n return a \u003c b ? a : b;\n }\n\n /**\n * @dev Returns the average of two numbers. The result is rounded towards\n * zero.\n */\n function average(uint256 a, uint256 b) internal pure returns (uint256) {\n // (a + b) / 2 can overflow.\n return (a \u0026 b) + (a ^ b) / 2;\n }\n\n /**\n * @dev Returns the ceiling of the division of two numbers.\n *\n * This differs from standard division with `/` in that it rounds up instead\n * of rounding down.\n */\n function ceilDiv(uint256 a, uint256 b) internal pure returns (uint256) {\n // (a + b - 1) / b can overflow on addition, so we distribute.\n return a == 0 ? 0 : (a - 1) / b + 1;\n }\n\n /**\n * @notice Calculates floor(x * y / denominator) with full precision. Throws if result overflows a uint256 or denominator == 0\n * @dev Original credit to Remco Bloemen under MIT license (https://xn--2-umb.com/21/muldiv)\n * with further edits by Uniswap Labs also under MIT license.\n */\n function mulDiv(uint256 x, uint256 y, uint256 denominator) internal pure returns (uint256 result) {\n unchecked {\n // 512-bit multiply [prod1 prod0] = x * y. Compute the product mod 2^256 and mod 2^256 - 1, then use\n // use the Chinese Remainder Theorem to reconstruct the 512 bit result. The result is stored in two 256\n // variables such that product = prod1 * 2^256 + prod0.\n uint256 prod0; // Least significant 256 bits of the product\n uint256 prod1; // Most significant 256 bits of the product\n assembly {\n let mm := mulmod(x, y, not(0))\n prod0 := mul(x, y)\n prod1 := sub(sub(mm, prod0), lt(mm, prod0))\n }\n\n // Handle non-overflow cases, 256 by 256 division.\n if (prod1 == 0) {\n // Solidity will revert if denominator == 0, unlike the div opcode on its own.\n // The surrounding unchecked block does not change this fact.\n // See https://docs.soliditylang.org/en/latest/control-structures.html#checked-or-unchecked-arithmetic.\n return prod0 / denominator;\n }\n\n // Make sure the result is less than 2^256. Also prevents denominator == 0.\n require(denominator \u003e prod1, \"Math: mulDiv overflow\");\n\n ///////////////////////////////////////////////\n // 512 by 256 division.\n ///////////////////////////////////////////////\n\n // Make division exact by subtracting the remainder from [prod1 prod0].\n uint256 remainder;\n assembly {\n // Compute remainder using mulmod.\n remainder := mulmod(x, y, denominator)\n\n // Subtract 256 bit number from 512 bit number.\n prod1 := sub(prod1, gt(remainder, prod0))\n prod0 := sub(prod0, remainder)\n }\n\n // Factor powers of two out of denominator and compute largest power of two divisor of denominator. Always \u003e= 1.\n // See https://cs.stackexchange.com/q/138556/92363.\n\n // Does not overflow because the denominator cannot be zero at this stage in the function.\n uint256 twos = denominator \u0026 (~denominator + 1);\n assembly {\n // Divide denominator by twos.\n denominator := div(denominator, twos)\n\n // Divide [prod1 prod0] by twos.\n prod0 := div(prod0, twos)\n\n // Flip twos such that it is 2^256 / twos. If twos is zero, then it becomes one.\n twos := add(div(sub(0, twos), twos), 1)\n }\n\n // Shift in bits from prod1 into prod0.\n prod0 |= prod1 * twos;\n\n // Invert denominator mod 2^256. Now that denominator is an odd number, it has an inverse modulo 2^256 such\n // that denominator * inv = 1 mod 2^256. Compute the inverse by starting with a seed that is correct for\n // four bits. That is, denominator * inv = 1 mod 2^4.\n uint256 inverse = (3 * denominator) ^ 2;\n\n // Use the Newton-Raphson iteration to improve the precision. Thanks to Hensel's lifting lemma, this also works\n // in modular arithmetic, doubling the correct bits in each step.\n inverse *= 2 - denominator * inverse; // inverse mod 2^8\n inverse *= 2 - denominator * inverse; // inverse mod 2^16\n inverse *= 2 - denominator * inverse; // inverse mod 2^32\n inverse *= 2 - denominator * inverse; // inverse mod 2^64\n inverse *= 2 - denominator * inverse; // inverse mod 2^128\n inverse *= 2 - denominator * inverse; // inverse mod 2^256\n\n // Because the division is now exact we can divide by multiplying with the modular inverse of denominator.\n // This will give us the correct result modulo 2^256. Since the preconditions guarantee that the outcome is\n // less than 2^256, this is the final result. We don't need to compute the high bits of the result and prod1\n // is no longer required.\n result = prod0 * inverse;\n return result;\n }\n }\n\n /**\n * @notice Calculates x * y / denominator with full precision, following the selected rounding direction.\n */\n function mulDiv(uint256 x, uint256 y, uint256 denominator, Rounding rounding) internal pure returns (uint256) {\n uint256 result = mulDiv(x, y, denominator);\n if (rounding == Rounding.Up \u0026\u0026 mulmod(x, y, denominator) \u003e 0) {\n result += 1;\n }\n return result;\n }\n\n /**\n * @dev Returns the square root of a number. If the number is not a perfect square, the value is rounded down.\n *\n * Inspired by Henry S. Warren, Jr.'s \"Hacker's Delight\" (Chapter 11).\n */\n function sqrt(uint256 a) internal pure returns (uint256) {\n if (a == 0) {\n return 0;\n }\n\n // For our first guess, we get the biggest power of 2 which is smaller than the square root of the target.\n //\n // We know that the \"msb\" (most significant bit) of our target number `a` is a power of 2 such that we have\n // `msb(a) \u003c= a \u003c 2*msb(a)`. This value can be written `msb(a)=2**k` with `k=log2(a)`.\n //\n // This can be rewritten `2**log2(a) \u003c= a \u003c 2**(log2(a) + 1)`\n // → `sqrt(2**k) \u003c= sqrt(a) \u003c sqrt(2**(k+1))`\n // → `2**(k/2) \u003c= sqrt(a) \u003c 2**((k+1)/2) \u003c= 2**(k/2 + 1)`\n //\n // Consequently, `2**(log2(a) / 2)` is a good first approximation of `sqrt(a)` with at least 1 correct bit.\n uint256 result = 1 \u003c\u003c (log2(a) \u003e\u003e 1);\n\n // At this point `result` is an estimation with one bit of precision. We know the true value is a uint128,\n // since it is the square root of a uint256. Newton's method converges quadratically (precision doubles at\n // every iteration). We thus need at most 7 iteration to turn our partial result with one bit of precision\n // into the expected uint128 result.\n unchecked {\n result = (result + a / result) \u003e\u003e 1;\n result = (result + a / result) \u003e\u003e 1;\n result = (result + a / result) \u003e\u003e 1;\n result = (result + a / result) \u003e\u003e 1;\n result = (result + a / result) \u003e\u003e 1;\n result = (result + a / result) \u003e\u003e 1;\n result = (result + a / result) \u003e\u003e 1;\n return min(result, a / result);\n }\n }\n\n /**\n * @notice Calculates sqrt(a), following the selected rounding direction.\n */\n function sqrt(uint256 a, Rounding rounding) internal pure returns (uint256) {\n unchecked {\n uint256 result = sqrt(a);\n return result + (rounding == Rounding.Up \u0026\u0026 result * result \u003c a ? 1 : 0);\n }\n }\n\n /**\n * @dev Return the log in base 2, rounded down, of a positive value.\n * Returns 0 if given 0.\n */\n function log2(uint256 value) internal pure returns (uint256) {\n uint256 result = 0;\n unchecked {\n if (value \u003e\u003e 128 \u003e 0) {\n value \u003e\u003e= 128;\n result += 128;\n }\n if (value \u003e\u003e 64 \u003e 0) {\n value \u003e\u003e= 64;\n result += 64;\n }\n if (value \u003e\u003e 32 \u003e 0) {\n value \u003e\u003e= 32;\n result += 32;\n }\n if (value \u003e\u003e 16 \u003e 0) {\n value \u003e\u003e= 16;\n result += 16;\n }\n if (value \u003e\u003e 8 \u003e 0) {\n value \u003e\u003e= 8;\n result += 8;\n }\n if (value \u003e\u003e 4 \u003e 0) {\n value \u003e\u003e= 4;\n result += 4;\n }\n if (value \u003e\u003e 2 \u003e 0) {\n value \u003e\u003e= 2;\n result += 2;\n }\n if (value \u003e\u003e 1 \u003e 0) {\n result += 1;\n }\n }\n return result;\n }\n\n /**\n * @dev Return the log in base 2, following the selected rounding direction, of a positive value.\n * Returns 0 if given 0.\n */\n function log2(uint256 value, Rounding rounding) internal pure returns (uint256) {\n unchecked {\n uint256 result = log2(value);\n return result + (rounding == Rounding.Up \u0026\u0026 1 \u003c\u003c result \u003c value ? 1 : 0);\n }\n }\n\n /**\n * @dev Return the log in base 10, rounded down, of a positive value.\n * Returns 0 if given 0.\n */\n function log10(uint256 value) internal pure returns (uint256) {\n uint256 result = 0;\n unchecked {\n if (value \u003e= 10 ** 64) {\n value /= 10 ** 64;\n result += 64;\n }\n if (value \u003e= 10 ** 32) {\n value /= 10 ** 32;\n result += 32;\n }\n if (value \u003e= 10 ** 16) {\n value /= 10 ** 16;\n result += 16;\n }\n if (value \u003e= 10 ** 8) {\n value /= 10 ** 8;\n result += 8;\n }\n if (value \u003e= 10 ** 4) {\n value /= 10 ** 4;\n result += 4;\n }\n if (value \u003e= 10 ** 2) {\n value /= 10 ** 2;\n result += 2;\n }\n if (value \u003e= 10 ** 1) {\n result += 1;\n }\n }\n return result;\n }\n\n /**\n * @dev Return the log in base 10, following the selected rounding direction, of a positive value.\n * Returns 0 if given 0.\n */\n function log10(uint256 value, Rounding rounding) internal pure returns (uint256) {\n unchecked {\n uint256 result = log10(value);\n return result + (rounding == Rounding.Up \u0026\u0026 10 ** result \u003c value ? 1 : 0);\n }\n }\n\n /**\n * @dev Return the log in base 256, rounded down, of a positive value.\n * Returns 0 if given 0.\n *\n * Adding one to the result gives the number of pairs of hex symbols needed to represent `value` as a hex string.\n */\n function log256(uint256 value) internal pure returns (uint256) {\n uint256 result = 0;\n unchecked {\n if (value \u003e\u003e 128 \u003e 0) {\n value \u003e\u003e= 128;\n result += 16;\n }\n if (value \u003e\u003e 64 \u003e 0) {\n value \u003e\u003e= 64;\n result += 8;\n }\n if (value \u003e\u003e 32 \u003e 0) {\n value \u003e\u003e= 32;\n result += 4;\n }\n if (value \u003e\u003e 16 \u003e 0) {\n value \u003e\u003e= 16;\n result += 2;\n }\n if (value \u003e\u003e 8 \u003e 0) {\n result += 1;\n }\n }\n return result;\n }\n\n /**\n * @dev Return the log in base 256, following the selected rounding direction, of a positive value.\n * Returns 0 if given 0.\n */\n function log256(uint256 value, Rounding rounding) internal pure returns (uint256) {\n unchecked {\n uint256 result = log256(value);\n return result + (rounding == Rounding.Up \u0026\u0026 1 \u003c\u003c (result \u003c\u003c 3) \u003c value ? 1 : 0);\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/utils/math/SignedMath.sol\n\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/math/SignedMath.sol)\n\n/**\n * @dev Standard signed math utilities missing in the Solidity language.\n */\nlibrary SignedMath {\n /**\n * @dev Returns the largest of two signed numbers.\n */\n function max(int256 a, int256 b) internal pure returns (int256) {\n return a \u003e b ? a : b;\n }\n\n /**\n * @dev Returns the smallest of two signed numbers.\n */\n function min(int256 a, int256 b) internal pure returns (int256) {\n return a \u003c b ? a : b;\n }\n\n /**\n * @dev Returns the average of two signed numbers without overflow.\n * The result is rounded towards zero.\n */\n function average(int256 a, int256 b) internal pure returns (int256) {\n // Formula from the book \"Hacker's Delight\"\n int256 x = (a \u0026 b) + ((a ^ b) \u003e\u003e 1);\n return x + (int256(uint256(x) \u003e\u003e 255) \u0026 (a ^ b));\n }\n\n /**\n * @dev Returns the absolute unsigned value of a signed value.\n */\n function abs(int256 n) internal pure returns (uint256) {\n unchecked {\n // must be unchecked in order to support `n = type(int256).min`\n return uint256(n \u003e= 0 ? n : -n);\n }\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// 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/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/InterfaceSummit.sol\n\ninterface InterfaceSummit {\n // ══════════════════════════════════════════ ACCEPT AGENT STATEMENTS ══════════════════════════════════════════════\n\n /**\n * @notice Accepts a receipt, which local `AgentManager` verified to have been signed by an active Notary.\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 * - Notary who signed the receipt is referenced as the \"Receipt Notary\".\n * - Notary who signed the attestation on destination chain is referenced as the \"Attestation Notary\".\n * \u003e Will revert if any of these is true:\n * \u003e - Called by anyone other than local `AgentManager`.\n * \u003e - Receipt body payload is not properly formatted.\n * \u003e - Receipt signer is in Dispute.\n * \u003e - Receipt's snapshot root is unknown.\n * @param rcptNotaryIndex Index of Receipt Notary in Agent Merkle Tree\n * @param attNotaryIndex Index of Attestation Notary in Agent Merkle Tree\n * @param sigIndex Index of stored Notary signature\n * @param attNonce Nonce of the attestation used for proving the executed message\n * @param paddedTips Padded encoded paid tips information\n * @param rcptPayload Raw payload with message execution receipt\n * @return wasAccepted Whether the receipt was accepted\n */\n function acceptReceipt(\n uint32 rcptNotaryIndex,\n uint32 attNotaryIndex,\n uint256 sigIndex,\n uint32 attNonce,\n uint256 paddedTips,\n bytes memory rcptPayload\n ) external returns (bool wasAccepted);\n\n /**\n * @notice Accepts a snapshot, which local `AgentManager` verified to have been signed by an active Guard.\n * \u003e Snapshot is a list of states for a set of Origin contracts residing on any of the chains.\n * All the states in the Guard-signed snapshot become available for Notary signing.\n * \u003e Will revert if any of these is true:\n * \u003e - Called by anyone other than local `AgentManager`.\n * \u003e - Snapshot payload is not properly formatted.\n * \u003e - Snapshot contains a state older then the Guard has previously submitted.\n * @param guardIndex Index of Guard in Agent Merkle Tree\n * @param sigIndex Index of stored Agent signature\n * @param snapPayload Raw payload with snapshot data\n */\n function acceptGuardSnapshot(uint32 guardIndex, uint256 sigIndex, bytes memory snapPayload) external;\n\n /**\n * @notice Accepts a snapshot, which local `AgentManager` verified to have been signed by an active Notary.\n * \u003e Snapshot is a list of states for a set of Origin contracts residing on any of the chains.\n * Snapshot Merkle Root is calculated and saved for valid snapshots, i.e.\n * snapshots which are only using states previously submitted by any of the Guards.\n * - Notary could use states singed by the same of different Guards 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 - Called by anyone other than local `AgentManager`.\n * \u003e - Snapshot payload is not properly formatted.\n * \u003e - Snapshot contains a state older then the Notary has previously submitted.\n * \u003e - Snapshot contains a state that no Guard has previously submitted.\n * @param notaryIndex Index of Notary in Agent Merkle Tree\n * @param sigIndex Index of stored Agent signature\n * @param agentRoot Current root of the Agent Merkle Tree\n * @param snapPayload Raw payload with snapshot data\n * @return attPayload Raw payload with data for attestation derived from Notary snapshot.\n */\n function acceptNotarySnapshot(uint32 notaryIndex, uint256 sigIndex, bytes32 agentRoot, bytes memory snapPayload)\n external\n returns (bytes memory attPayload);\n\n // ════════════════════════════════════════════════ TIPS LOGIC ═════════════════════════════════════════════════════\n\n /**\n * @notice Distributes tips using the first Receipt from the \"receipt quarantine queue\".\n * Possible scenarios:\n * - Receipt queue is empty =\u003e does nothing\n * - Receipt optimistic period is not over =\u003e does nothing\n * - Either of Notaries present in Receipt was slashed =\u003e receipt is deleted from the queue\n * - Either of Notaries present in Receipt in Dispute =\u003e receipt is moved to the end of queue\n * - None of the above =\u003e receipt tips are distributed\n * @dev Returned value makes it possible to do the following: `while (distributeTips()) {}`\n * @return queuePopped Whether the first element was popped from the queue\n */\n function distributeTips() external returns (bool queuePopped);\n\n /**\n * @notice Withdraws locked base message tips from requested domain Origin to the recipient.\n * This is done by a call to a local Origin contract, or by a manager message to the remote chain.\n * @dev This will revert, if the pending balance of origin tips (earned-claimed) is lower than requested.\n * @param origin Domain of chain to withdraw tips on\n * @param amount Amount of tips to withdraw\n */\n function withdrawTips(uint32 origin, uint256 amount) external;\n\n // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════\n\n /**\n * @notice Returns earned and claimed tips for the actor.\n * Note: Tips for address(0) belong to the Treasury.\n * @param actor Address of the actor\n * @param origin Domain where the tips were initially paid\n * @return earned Total amount of origin tips the actor has earned so far\n * @return claimed Total amount of origin tips the actor has claimed so far\n */\n function actorTips(address actor, uint32 origin) external view returns (uint128 earned, uint128 claimed);\n\n /**\n * @notice Returns the amount of receipts in the \"Receipt Quarantine Queue\".\n */\n function receiptQueueLength() external view returns (uint256);\n\n /**\n * @notice Returns the state with the highest known nonce\n * submitted by any of the currently active Guards.\n * @param origin Domain of origin chain\n * @return statePayload Raw payload with latest active Guard state for origin\n */\n function getLatestState(uint32 origin) external view returns (bytes memory statePayload);\n}\n\n// node_modules/@openzeppelin/contracts/utils/Strings.sol\n\n// OpenZeppelin Contracts (last updated v4.9.0) (utils/Strings.sol)\n\n/**\n * @dev String operations.\n */\nlibrary Strings {\n bytes16 private constant _SYMBOLS = \"0123456789abcdef\";\n uint8 private constant _ADDRESS_LENGTH = 20;\n\n /**\n * @dev Converts a `uint256` to its ASCII `string` decimal representation.\n */\n function toString(uint256 value) internal pure returns (string memory) {\n unchecked {\n uint256 length = Math.log10(value) + 1;\n string memory buffer = new string(length);\n uint256 ptr;\n /// @solidity memory-safe-assembly\n assembly {\n ptr := add(buffer, add(32, length))\n }\n while (true) {\n ptr--;\n /// @solidity memory-safe-assembly\n assembly {\n mstore8(ptr, byte(mod(value, 10), _SYMBOLS))\n }\n value /= 10;\n if (value == 0) break;\n }\n return buffer;\n }\n }\n\n /**\n * @dev Converts a `int256` to its ASCII `string` decimal representation.\n */\n function toString(int256 value) internal pure returns (string memory) {\n return string(abi.encodePacked(value \u003c 0 ? \"-\" : \"\", toString(SignedMath.abs(value))));\n }\n\n /**\n * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation.\n */\n function toHexString(uint256 value) internal pure returns (string memory) {\n unchecked {\n return toHexString(value, Math.log256(value) + 1);\n }\n }\n\n /**\n * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length.\n */\n function toHexString(uint256 value, uint256 length) internal pure returns (string memory) {\n bytes memory buffer = new bytes(2 * length + 2);\n buffer[0] = \"0\";\n buffer[1] = \"x\";\n for (uint256 i = 2 * length + 1; i \u003e 1; --i) {\n buffer[i] = _SYMBOLS[value \u0026 0xf];\n value \u003e\u003e= 4;\n }\n require(value == 0, \"Strings: hex length insufficient\");\n return string(buffer);\n }\n\n /**\n * @dev Converts an `address` with fixed length of 20 bytes to its not checksummed ASCII `string` hexadecimal representation.\n */\n function toHexString(address addr) internal pure returns (string memory) {\n return toHexString(uint256(uint160(addr)), _ADDRESS_LENGTH);\n }\n\n /**\n * @dev Returns true if the two strings are equal.\n */\n function equal(string memory a, string memory b) internal pure returns (bool) {\n return keccak256(bytes(a)) == keccak256(bytes(b));\n }\n}\n\n// node_modules/@openzeppelin/contracts-upgradeable/utils/ContextUpgradeable.sol\n\n// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)\n\n/**\n * @dev Provides information about the current execution context, including the\n * sender of the transaction and its data. While these are generally available\n * via msg.sender and msg.data, they should not be accessed in such a direct\n * manner, since when dealing with meta-transactions the account sending and\n * paying for execution may not be the actual sender (as far as an application\n * is concerned).\n *\n * This contract is only required for intermediate, library-like contracts.\n */\nabstract contract ContextUpgradeable is Initializable {\n function __Context_init() internal onlyInitializing {\n }\n\n function __Context_init_unchained() internal onlyInitializing {\n }\n function _msgSender() internal view virtual returns (address) {\n return msg.sender;\n }\n\n function _msgData() internal view virtual returns (bytes calldata) {\n return msg.data;\n }\n\n /**\n * @dev This empty reserved space is put in place to allow future versions to add new\n * variables without shifting down storage in the inheritance chain.\n * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\n */\n uint256[50] private __gap;\n}\n\n// contracts/libs/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/utils/cryptography/ECDSA.sol\n\n// OpenZeppelin Contracts (last updated v4.9.0) (utils/cryptography/ECDSA.sol)\n\n/**\n * @dev Elliptic Curve Digital Signature Algorithm (ECDSA) operations.\n *\n * These functions can be used to verify that a message was signed by the holder\n * of the private keys of a given address.\n */\nlibrary ECDSA {\n enum RecoverError {\n NoError,\n InvalidSignature,\n InvalidSignatureLength,\n InvalidSignatureS,\n InvalidSignatureV // Deprecated in v4.8\n }\n\n function _throwError(RecoverError error) private pure {\n if (error == RecoverError.NoError) {\n return; // no error: do nothing\n } else if (error == RecoverError.InvalidSignature) {\n revert(\"ECDSA: invalid signature\");\n } else if (error == RecoverError.InvalidSignatureLength) {\n revert(\"ECDSA: invalid signature length\");\n } else if (error == RecoverError.InvalidSignatureS) {\n revert(\"ECDSA: invalid signature 's' value\");\n }\n }\n\n /**\n * @dev Returns the address that signed a hashed message (`hash`) with\n * `signature` or error string. This address can then be used for verification purposes.\n *\n * The `ecrecover` EVM opcode allows for malleable (non-unique) signatures:\n * this function rejects them by requiring the `s` value to be in the lower\n * half order, and the `v` value to be either 27 or 28.\n *\n * IMPORTANT: `hash` _must_ be the result of a hash operation for the\n * verification to be secure: it is possible to craft signatures that\n * recover to arbitrary addresses for non-hashed data. A safe way to ensure\n * this is by receiving a hash of the original message (which may otherwise\n * be too long), and then calling {toEthSignedMessageHash} on it.\n *\n * Documentation for signature generation:\n * - with https://web3js.readthedocs.io/en/v1.3.4/web3-eth-accounts.html#sign[Web3.js]\n * - with https://docs.ethers.io/v5/api/signer/#Signer-signMessage[ethers]\n *\n * _Available since v4.3._\n */\n function tryRecover(bytes32 hash, bytes memory signature) internal pure returns (address, RecoverError) {\n if (signature.length == 65) {\n bytes32 r;\n bytes32 s;\n uint8 v;\n // ecrecover takes the signature parameters, and the only way to get them\n // currently is to use assembly.\n /// @solidity memory-safe-assembly\n assembly {\n r := mload(add(signature, 0x20))\n s := mload(add(signature, 0x40))\n v := byte(0, mload(add(signature, 0x60)))\n }\n return tryRecover(hash, v, r, s);\n } else {\n return (address(0), RecoverError.InvalidSignatureLength);\n }\n }\n\n /**\n * @dev Returns the address that signed a hashed message (`hash`) with\n * `signature`. This address can then be used for verification purposes.\n *\n * The `ecrecover` EVM opcode allows for malleable (non-unique) signatures:\n * this function rejects them by requiring the `s` value to be in the lower\n * half order, and the `v` value to be either 27 or 28.\n *\n * IMPORTANT: `hash` _must_ be the result of a hash operation for the\n * verification to be secure: it is possible to craft signatures that\n * recover to arbitrary addresses for non-hashed data. A safe way to ensure\n * this is by receiving a hash of the original message (which may otherwise\n * be too long), and then calling {toEthSignedMessageHash} on it.\n */\n function recover(bytes32 hash, bytes memory signature) internal pure returns (address) {\n (address recovered, RecoverError error) = tryRecover(hash, signature);\n _throwError(error);\n return recovered;\n }\n\n /**\n * @dev Overload of {ECDSA-tryRecover} that receives the `r` and `vs` short-signature fields separately.\n *\n * See https://eips.ethereum.org/EIPS/eip-2098[EIP-2098 short signatures]\n *\n * _Available since v4.3._\n */\n function tryRecover(bytes32 hash, bytes32 r, bytes32 vs) internal pure returns (address, RecoverError) {\n bytes32 s = vs \u0026 bytes32(0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff);\n uint8 v = uint8((uint256(vs) \u003e\u003e 255) + 27);\n return tryRecover(hash, v, r, s);\n }\n\n /**\n * @dev Overload of {ECDSA-recover} that receives the `r and `vs` short-signature fields separately.\n *\n * _Available since v4.2._\n */\n function recover(bytes32 hash, bytes32 r, bytes32 vs) internal pure returns (address) {\n (address recovered, RecoverError error) = tryRecover(hash, r, vs);\n _throwError(error);\n return recovered;\n }\n\n /**\n * @dev Overload of {ECDSA-tryRecover} that receives the `v`,\n * `r` and `s` signature fields separately.\n *\n * _Available since v4.3._\n */\n function tryRecover(bytes32 hash, uint8 v, bytes32 r, bytes32 s) internal pure returns (address, RecoverError) {\n // EIP-2 still allows signature malleability for ecrecover(). Remove this possibility and make the signature\n // unique. Appendix F in the Ethereum Yellow paper (https://ethereum.github.io/yellowpaper/paper.pdf), defines\n // the valid range for s in (301): 0 \u003c s \u003c secp256k1n ÷ 2 + 1, and for v in (302): v ∈ {27, 28}. Most\n // signatures from current libraries generate a unique signature with an s-value in the lower half order.\n //\n // If your library generates malleable signatures, such as s-values in the upper range, calculate a new s-value\n // with 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141 - s1 and flip v from 27 to 28 or\n // vice versa. If your library also generates signatures with 0/1 for v instead 27/28, add 27 to v to accept\n // these malleable signatures as well.\n if (uint256(s) \u003e 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0) {\n return (address(0), RecoverError.InvalidSignatureS);\n }\n\n // If the signature is valid (and not malleable), return the signer address\n address signer = ecrecover(hash, v, r, s);\n if (signer == address(0)) {\n return (address(0), RecoverError.InvalidSignature);\n }\n\n return (signer, RecoverError.NoError);\n }\n\n /**\n * @dev Overload of {ECDSA-recover} that receives the `v`,\n * `r` and `s` signature fields separately.\n */\n function recover(bytes32 hash, uint8 v, bytes32 r, bytes32 s) internal pure returns (address) {\n (address recovered, RecoverError error) = tryRecover(hash, v, r, s);\n _throwError(error);\n return recovered;\n }\n\n /**\n * @dev Returns an Ethereum Signed Message, created from a `hash`. This\n * produces hash corresponding to the one signed with the\n * https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`]\n * JSON-RPC method as part of EIP-191.\n *\n * See {recover}.\n */\n function toEthSignedMessageHash(bytes32 hash) internal pure returns (bytes32 message) {\n // 32 is the length in bytes of hash,\n // enforced by the type signature above\n /// @solidity memory-safe-assembly\n assembly {\n mstore(0x00, \"\\x19Ethereum Signed Message:\\n32\")\n mstore(0x1c, hash)\n message := keccak256(0x00, 0x3c)\n }\n }\n\n /**\n * @dev Returns an Ethereum Signed Message, created from `s`. This\n * produces hash corresponding to the one signed with the\n * https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`]\n * JSON-RPC method as part of EIP-191.\n *\n * See {recover}.\n */\n function toEthSignedMessageHash(bytes memory s) internal pure returns (bytes32) {\n return keccak256(abi.encodePacked(\"\\x19Ethereum Signed Message:\\n\", Strings.toString(s.length), s));\n }\n\n /**\n * @dev Returns an Ethereum Signed Typed Data, created from a\n * `domainSeparator` and a `structHash`. This produces hash corresponding\n * to the one signed with the\n * https://eips.ethereum.org/EIPS/eip-712[`eth_signTypedData`]\n * JSON-RPC method as part of EIP-712.\n *\n * See {recover}.\n */\n function toTypedDataHash(bytes32 domainSeparator, bytes32 structHash) internal pure returns (bytes32 data) {\n /// @solidity memory-safe-assembly\n assembly {\n let ptr := mload(0x40)\n mstore(ptr, \"\\x19\\x01\")\n mstore(add(ptr, 0x02), domainSeparator)\n mstore(add(ptr, 0x22), structHash)\n data := keccak256(ptr, 0x42)\n }\n }\n\n /**\n * @dev Returns an Ethereum Signed Data with intended validator, created from a\n * `validator` and `data` according to the version 0 of EIP-191.\n *\n * See {recover}.\n */\n function toDataWithIntendedValidatorHash(address validator, bytes memory data) internal pure returns (bytes32) {\n return keccak256(abi.encodePacked(\"\\x19\\x00\", validator, data));\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/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/inbox/StatementInbox.sol\n\n// ══════════════════════════════ LIBRARY IMPORTS ══════════════════════════════\n\n// ═════════════════════════════ INTERNAL IMPORTS ══════════════════════════════\n\n// ═════════════════════════════ EXTERNAL IMPORTS ══════════════════════════════\n\n/// @notice `StatementInbox` is the entry point for all agent-signed statements. It verifies the\n/// agent signatures, and passes the unsigned statements to the contract to consume it via `acceptX` functions. Is is\n/// also used to verify the agent-signed statements and initiate the agent slashing, should the statement be invalid.\n/// `StatementInbox` is responsible for the following:\n/// - Accepting State and Receipt Reports to initiate a dispute between Guard and Notary.\n/// - Storing all the Guard Reports with the Guard signature leading to a dispute.\n/// - Verifying State/State Reports referencing the local chain and slashing the signer if statement is invalid.\n/// - Verifying Receipt/Receipt Reports referencing the local chain and slashing the signer if statement is invalid.\nabstract contract StatementInbox is MessagingBase, StatementInboxEvents, IStatementInbox {\n using AttestationLib for bytes;\n using ReceiptLib for bytes;\n using StateLib for bytes;\n using SnapshotLib for bytes;\n\n struct StoredReport {\n uint256 sigIndex;\n bytes statementPayload;\n }\n\n // ══════════════════════════════════════════════════ STORAGE ══════════════════════════════════════════════════════\n\n address public agentManager;\n address public origin;\n address public destination;\n\n // TODO: optimize this\n bytes[] internal _storedSignatures;\n StoredReport[] internal _storedReports;\n\n /// @dev gap for upgrade safety\n uint256[45] private __GAP; // solhint-disable-line var-name-mixedcase\n\n // ════════════════════════════════════════════════ INITIALIZER ════════════════════════════════════════════════════\n\n /// @dev Initializes the contract:\n /// - Sets up `msg.sender` as the owner of the contract.\n /// - Sets up `agentManager`, `origin`, and `destination`.\n // solhint-disable-next-line func-name-mixedcase\n function __StatementInbox_init(address agentManager_, address origin_, address destination_)\n internal\n onlyInitializing\n {\n agentManager = agentManager_;\n origin = origin_;\n destination = destination_;\n __Ownable2Step_init();\n }\n\n // ══════════════════════════════════════════ SUBMIT AGENT STATEMENTS ══════════════════════════════════════════════\n\n /// @inheritdoc IStatementInbox\n // solhint-disable-next-line ordering\n function submitStateReportWithSnapshot(\n uint8 stateIndex,\n bytes memory srSignature,\n bytes memory snapPayload,\n bytes memory snapSignature\n ) external returns (bool wasAccepted) {\n // This will revert if payload is not a snapshot\n Snapshot snapshot = snapPayload.castToSnapshot();\n // This will revert if the snapshot signer is not a known Notary\n (AgentStatus memory notaryStatus,) =\n _verifySnapshot({snapshot: snapshot, snapSignature: snapSignature, verifyNotary: true});\n // Notary needs to be Active/Unstaking\n notaryStatus.verifyActiveUnstaking();\n // Check if Notary is active on this chain\n _verifyNotaryDomain(notaryStatus.domain);\n // This will revert if state index is out of range\n State state = snapshot.state(stateIndex);\n // This will revert if the report signer is not an known Guard\n (AgentStatus memory guardStatus,) = _verifyStateReport(state, srSignature);\n // Check that Guard is active\n guardStatus.verifyActive();\n _saveReport(state.unwrap().clone(), srSignature);\n // This will revert if either actor is already in dispute\n IAgentManager(agentManager).openDispute(guardStatus.index, notaryStatus.index);\n return true;\n }\n\n /// @inheritdoc IStatementInbox\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 // This will revert if payload is not a snapshot\n Snapshot snapshot = snapPayload.castToSnapshot();\n // This will revert if state index is out of range\n State state = snapshot.state(stateIndex);\n // This will revert if the report signer is not an known Guard\n (AgentStatus memory guardStatus,) = _verifyStateReport(state, srSignature);\n // Check that Guard is active\n guardStatus.verifyActive();\n // This will revert if payload is not an attestation\n Attestation att = attPayload.castToAttestation();\n // This will revert if signer is not an known Notary\n (AgentStatus memory notaryStatus,) = _verifyAttestation(att, attSignature);\n // Notary needs to be Active/Unstaking\n notaryStatus.verifyActiveUnstaking();\n // Check if Notary is active on this chain\n _verifyNotaryDomain(notaryStatus.domain);\n if (snapshot.calculateRoot() != att.snapRoot()) revert IncorrectSnapshotRoot();\n _saveReport(state.unwrap().clone(), srSignature);\n // This will revert if either actor is already in dispute\n IAgentManager(agentManager).openDispute(guardStatus.index, notaryStatus.index);\n return true;\n }\n\n /// @inheritdoc IStatementInbox\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 // This will revert if payload is not a state\n State state = statePayload.castToState();\n // This will revert if the report signer is not an known Guard\n (AgentStatus memory guardStatus,) = _verifyStateReport(state, srSignature);\n // Check that Guard is active\n guardStatus.verifyActive();\n // This will revert if payload is not an attestation\n Attestation att = attPayload.castToAttestation();\n // This will revert if signer is not a known Notary\n (AgentStatus memory notaryStatus,) = _verifyAttestation(att, attSignature);\n // Notary needs to be Active/Unstaking\n notaryStatus.verifyActiveUnstaking();\n // Check if Notary is active on this chain\n _verifyNotaryDomain(notaryStatus.domain);\n // This will revert if any of these is true:\n // - Attestation root is not equal to Merkle Root derived from State and Snapshot Proof.\n // - Snapshot Proof's first element does not match the State metadata.\n // - Snapshot Proof length exceeds Snapshot tree Height.\n // - State index is out of range.\n _verifySnapshotMerkle(att, stateIndex, state, snapProof);\n _saveReport(statePayload, srSignature);\n // This will revert if either actor is already in dispute\n IAgentManager(agentManager).openDispute(guardStatus.index, notaryStatus.index);\n return true;\n }\n\n // ══════════════════════════════════════════ VERIFY AGENT STATEMENTS ══════════════════════════════════════════════\n\n /// @inheritdoc IStatementInbox\n function verifyReceipt(bytes memory rcptPayload, bytes memory rcptSignature)\n external\n returns (bool isValidReceipt)\n {\n // This will revert if payload is not a receipt\n Receipt rcpt = rcptPayload.castToReceipt();\n // This will revert if the attestation signer is not a known Notary\n (AgentStatus memory status, address notary) = _verifyReceipt(rcpt, rcptSignature);\n // Notary needs to be Active/Unstaking\n status.verifyActiveUnstaking();\n isValidReceipt = IExecutionHub(destination).isValidReceipt(rcptPayload);\n if (!isValidReceipt) {\n emit InvalidReceipt(rcptPayload, rcptSignature);\n IAgentManager(agentManager).slashAgent(status.domain, notary, msg.sender);\n }\n }\n\n /// @inheritdoc IStatementInbox\n function verifyReceiptReport(bytes memory rcptPayload, bytes memory rrSignature)\n external\n returns (bool isValidReport)\n {\n // This will revert if payload is not a receipt\n Receipt rcpt = rcptPayload.castToReceipt();\n // This will revert if the report signer is not a known Guard\n (AgentStatus memory status, address guard) = _verifyReceiptReport(rcpt, rrSignature);\n // Guard needs to be Active/Unstaking\n status.verifyActiveUnstaking();\n // Report is valid IF AND ONLY IF the reported receipt in invalid\n isValidReport = !IExecutionHub(destination).isValidReceipt(rcptPayload);\n if (!isValidReport) {\n emit InvalidReceiptReport(rcptPayload, rrSignature);\n IAgentManager(agentManager).slashAgent(status.domain, guard, msg.sender);\n }\n }\n\n /// @inheritdoc IStatementInbox\n function verifyStateWithAttestation(\n uint8 stateIndex,\n bytes memory snapPayload,\n bytes memory attPayload,\n bytes memory attSignature\n ) external returns (bool isValidState) {\n // This will revert if payload is not an attestation\n Attestation att = attPayload.castToAttestation();\n // This will revert if the attestation signer is not a known Notary\n (AgentStatus memory status, address notary) = _verifyAttestation(att, attSignature);\n // Notary needs to be Active/Unstaking\n status.verifyActiveUnstaking();\n // This will revert if payload is not a snapshot\n Snapshot snapshot = snapPayload.castToSnapshot();\n if (snapshot.calculateRoot() != att.snapRoot()) revert IncorrectSnapshotRoot();\n // This will revert if state does not refer to this chain\n bytes memory statePayload = snapshot.state(stateIndex).unwrap().clone();\n isValidState = IStateHub(origin).isValidState(statePayload);\n if (!isValidState) {\n emit InvalidStateWithAttestation(stateIndex, statePayload, attPayload, attSignature);\n IAgentManager(agentManager).slashAgent(status.domain, notary, msg.sender);\n }\n }\n\n /// @inheritdoc IStatementInbox\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 // This will revert if payload is not an attestation\n Attestation att = attPayload.castToAttestation();\n // This will revert if the attestation signer is not a known Notary\n (AgentStatus memory status, address notary) = _verifyAttestation(att, attSignature);\n // Notary needs to be Active/Unstaking\n status.verifyActiveUnstaking();\n // This will revert if payload is not a state\n State state = statePayload.castToState();\n // This will revert if any of these is true:\n // - Attestation root is not equal to Merkle Root derived from State and Snapshot Proof.\n // - Snapshot Proof's first element does not match the State metadata.\n // - Snapshot Proof length exceeds Snapshot tree Height.\n // - State index is out of range.\n _verifySnapshotMerkle(att, stateIndex, state, snapProof);\n // This will revert if state does not refer to this chain\n isValidState = IStateHub(origin).isValidState(statePayload);\n if (!isValidState) {\n emit InvalidStateWithAttestation(stateIndex, statePayload, attPayload, attSignature);\n IAgentManager(agentManager).slashAgent(status.domain, notary, msg.sender);\n }\n }\n\n /// @inheritdoc IStatementInbox\n function verifyStateWithSnapshot(uint8 stateIndex, bytes memory snapPayload, bytes memory snapSignature)\n external\n returns (bool isValidState)\n {\n // This will revert if payload is not a snapshot\n Snapshot snapshot = snapPayload.castToSnapshot();\n // This will revert if the snapshot signer is not a known Guard/Notary\n (AgentStatus memory status, address agent) =\n _verifySnapshot({snapshot: snapshot, snapSignature: snapSignature, verifyNotary: false});\n // Agent needs to be Active/Unstaking\n status.verifyActiveUnstaking();\n // This will revert if state does not refer to this chain\n isValidState = IStateHub(origin).isValidState(snapshot.state(stateIndex).unwrap().clone());\n if (!isValidState) {\n emit InvalidStateWithSnapshot(stateIndex, snapPayload, snapSignature);\n IAgentManager(agentManager).slashAgent(status.domain, agent, msg.sender);\n }\n }\n\n /// @inheritdoc IStatementInbox\n function verifyStateReport(bytes memory statePayload, bytes memory srSignature)\n external\n returns (bool isValidReport)\n {\n // This will revert if payload is not a state\n State state = statePayload.castToState();\n // This will revert if the report signer is not a known Guard\n (AgentStatus memory status, address guard) = _verifyStateReport(state, srSignature);\n // Guard needs to be Active/Unstaking\n status.verifyActiveUnstaking();\n // Report is valid IF AND ONLY IF the reported state in invalid\n // This will revert if the reported state does not refer to this chain\n isValidReport = !IStateHub(origin).isValidState(statePayload);\n if (!isValidReport) {\n emit InvalidStateReport(statePayload, srSignature);\n IAgentManager(agentManager).slashAgent(status.domain, guard, msg.sender);\n }\n }\n\n // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════\n\n /// @inheritdoc IStatementInbox\n function getReportsAmount() external view returns (uint256) {\n return _storedReports.length;\n }\n\n /// @inheritdoc IStatementInbox\n function getGuardReport(uint256 index)\n external\n view\n returns (bytes memory statementPayload, bytes memory reportSignature)\n {\n if (index \u003e= _storedReports.length) revert IndexOutOfRange();\n StoredReport memory storedReport = _storedReports[index];\n statementPayload = storedReport.statementPayload;\n reportSignature = _storedSignatures[storedReport.sigIndex];\n }\n\n /// @inheritdoc IStatementInbox\n function getStoredSignature(uint256 index) external view returns (bytes memory) {\n return _storedSignatures[index];\n }\n\n // ══════════════════════════════════════════════ INTERNAL LOGIC ═══════════════════════════════════════════════════\n\n /// @dev Saves the statement reported by Guard as invalid and the Guard Report signature.\n function _saveReport(bytes memory statementPayload, bytes memory reportSignature) internal {\n uint256 sigIndex = _saveSignature(reportSignature);\n _storedReports.push(StoredReport(sigIndex, statementPayload));\n }\n\n /// @dev Saves the signature and returns its index.\n function _saveSignature(bytes memory signature) internal returns (uint256 sigIndex) {\n sigIndex = _storedSignatures.length;\n _storedSignatures.push(signature);\n }\n\n // ═══════════════════════════════════════════════ AGENT CHECKS ════════════════════════════════════════════════════\n\n /**\n * @dev Recovers a signer from a hashed message, and a EIP-191 signature for it.\n * Will revert, if the signer is not a known agent.\n * @dev Agent flag could be any of these: Active/Unstaking/Resting/Fraudulent/Slashed\n * Further checks need to be performed in a caller function.\n * @param hashedStatement Hash of the statement that was signed by an Agent\n * @param signature Agent signature for the hashed statement\n * @return status Struct representing agent status:\n * - flag Unknown/Active/Unstaking/Resting/Fraudulent/Slashed\n * - domain Domain where agent is/was active\n * - index Index of agent in the Agent Merkle Tree\n * @return agent Agent that signed the statement\n */\n function _recoverAgent(bytes32 hashedStatement, bytes memory signature)\n internal\n view\n returns (AgentStatus memory status, address agent)\n {\n bytes32 ethSignedMsg = ECDSA.toEthSignedMessageHash(hashedStatement);\n agent = ECDSA.recover(ethSignedMsg, signature);\n status = IAgentManager(agentManager).agentStatus(agent);\n // Discard signature of unknown agents.\n // Further flag checks are supposed to be performed in a caller function.\n status.verifyKnown();\n }\n\n /// @dev Verifies that Notary signature is active on local domain.\n function _verifyNotaryDomain(uint32 notaryDomain) internal view {\n // Notary needs to be from the local domain (if contract is not deployed on Synapse Chain).\n // Or Notary could be from any domain (if contract is deployed on Synapse Chain).\n if (notaryDomain != localDomain \u0026\u0026 localDomain != synapseDomain) revert IncorrectAgentDomain();\n }\n\n // ════════════════════════════════════════ ATTESTATION RELATED CHECKS ═════════════════════════════════════════════\n\n /**\n * @dev Internal function to verify the signed attestation payload.\n * Reverts if any of these is true:\n * - Attestation signer is not a known Notary.\n * @param att Typed memory view over attestation payload\n * @param attSignature Notary signature for the attestation\n * @return status Struct representing agent status, see {_recoverAgent}\n * @return notary Notary that signed the snapshot\n */\n function _verifyAttestation(Attestation att, bytes memory attSignature)\n internal\n view\n returns (AgentStatus memory status, address notary)\n {\n // This will revert if signer is not a known agent\n (status, notary) = _recoverAgent(att.hashValid(), attSignature);\n // Attestation signer needs to be a Notary, not a Guard\n if (status.domain == 0) revert AgentNotNotary();\n }\n\n /**\n * @dev Internal function to verify the signed attestation report payload.\n * Reverts if any of these is true:\n * - Report signer is not a known Guard.\n * @param att Typed memory view over attestation payload that Guard reports as invalid\n * @param arSignature Guard signature for the \"invalid attestation\" report\n * @return status Struct representing guard status, see {_recoverAgent}\n * @return guard Guard that signed the report\n */\n function _verifyAttestationReport(Attestation att, bytes memory arSignature)\n internal\n view\n returns (AgentStatus memory status, address guard)\n {\n // This will revert if signer is not a known agent\n (status, guard) = _recoverAgent(att.hashInvalid(), arSignature);\n // Report signer needs to be a Guard, not a Notary\n if (status.domain != 0) revert AgentNotGuard();\n }\n\n // ══════════════════════════════════════════ RECEIPT RELATED CHECKS ═══════════════════════════════════════════════\n\n /**\n * @dev Internal function to verify the signed receipt payload.\n * Reverts if any of these is true:\n * - Receipt signer is not a known Notary.\n * @param rcpt Typed memory view over receipt payload\n * @param rcptSignature Notary signature for the receipt\n * @return status Struct representing agent status, see {_recoverAgent}\n * @return notary Notary that signed the snapshot\n */\n function _verifyReceipt(Receipt rcpt, bytes memory rcptSignature)\n internal\n view\n returns (AgentStatus memory status, address notary)\n {\n // This will revert if signer is not a known agent\n (status, notary) = _recoverAgent(rcpt.hashValid(), rcptSignature);\n // Receipt signer needs to be a Notary, not a Guard\n if (status.domain == 0) revert AgentNotNotary();\n }\n\n /**\n * @dev Internal function to verify the signed receipt report payload.\n * Reverts if any of these is true:\n * - Report signer is not a known Guard.\n * @param rcpt Typed memory view over receipt payload that Guard reports as invalid\n * @param rrSignature Guard signature for the \"invalid receipt\" report\n * @return status Struct representing guard status, see {_recoverAgent}\n * @return guard Guard that signed the report\n */\n function _verifyReceiptReport(Receipt rcpt, bytes memory rrSignature)\n internal\n view\n returns (AgentStatus memory status, address guard)\n {\n // This will revert if signer is not a known agent\n (status, guard) = _recoverAgent(rcpt.hashInvalid(), rrSignature);\n // Report signer needs to be a Guard, not a Notary\n if (status.domain != 0) revert AgentNotGuard();\n }\n\n // ═══════════════════════════════════════ STATE/SNAPSHOT RELATED CHECKS ═══════════════════════════════════════════\n\n /**\n * @dev Internal function to verify the signed snapshot report payload.\n * Reverts if any of these is true:\n * - Report signer is not a known Guard.\n * @param state Typed memory view over state payload that Guard reports as invalid\n * @param srSignature Guard signature for the report\n * @return status Struct representing guard status, see {_recoverAgent}\n * @return guard Guard that signed the report\n */\n function _verifyStateReport(State state, bytes memory srSignature)\n internal\n view\n returns (AgentStatus memory status, address guard)\n {\n // This will revert if signer is not a known agent\n (status, guard) = _recoverAgent(state.hashInvalid(), srSignature);\n // Report signer needs to be a Guard, not a Notary\n if (status.domain != 0) revert AgentNotGuard();\n }\n\n /**\n * @dev Internal function to verify the signed snapshot payload.\n * Reverts if any of these is true:\n * - Snapshot signer is not a known Agent.\n * - Snapshot signer is not a Notary (if verifyNotary is true).\n * @param snapshot Typed memory view over snapshot payload\n * @param snapSignature Agent signature for the snapshot\n * @param verifyNotary If true, snapshot signer needs to be a Notary, not a Guard\n * @return status Struct representing agent status, see {_recoverAgent}\n * @return agent Agent that signed the snapshot\n */\n function _verifySnapshot(Snapshot snapshot, bytes memory snapSignature, bool verifyNotary)\n internal\n view\n returns (AgentStatus memory status, address agent)\n {\n // This will revert if signer is not a known agent\n (status, agent) = _recoverAgent(snapshot.hashValid(), snapSignature);\n // If requested, snapshot signer needs to be a Notary, not a Guard\n if (verifyNotary \u0026\u0026 status.domain == 0) revert AgentNotNotary();\n }\n\n // ═══════════════════════════════════════════ MERKLE RELATED CHECKS ═══════════════════════════════════════════════\n\n /**\n * @dev Internal function to verify that snapshot roots match.\n * Reverts if any of these is true:\n * - Attestation root is not equal to Merkle Root derived from State and Snapshot Proof.\n * - Snapshot Proof's first element does not match the State metadata.\n * - Snapshot Proof length exceeds Snapshot tree Height.\n * - State index is out of range.\n * @param att Typed memory view over Attestation\n * @param stateIndex Index of state in the snapshot\n * @param state Typed memory view over the provided state payload\n * @param snapProof Raw payload with snapshot data\n */\n function _verifySnapshotMerkle(Attestation att, uint8 stateIndex, State state, bytes32[] memory snapProof)\n internal\n pure\n {\n // Snapshot proof first element should match State metadata (aka \"right sub-leaf\")\n (, bytes32 rightSubLeaf) = state.subLeafs();\n if (snapProof[0] != rightSubLeaf) revert IncorrectSnapshotProof();\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(state.root(), state.origin(), snapProof, stateIndex);\n // Snapshot root should match the attestation root\n if (att.snapRoot() != snapshotRoot) revert IncorrectSnapshotRoot();\n }\n}\n\n// contracts/inbox/Inbox.sol\n\n// ══════════════════════════════ LIBRARY IMPORTS ══════════════════════════════\n\n// ═════════════════════════════ INTERNAL IMPORTS ══════════════════════════════\n\n/// @notice `Inbox` is the child of `StatementInbox` contract, that is used on Synapse Chain.\n/// In addition to the functionality of `StatementInbox`, it also:\n/// - Accepts Guard and Notary Snapshots and passes them to `Summit` contract.\n/// - Accepts Notary-signed Receipts and passes them to `Summit` contract.\n/// - Accepts Receipt Reports to initiate a dispute between Guard and Notary.\n/// - Verifies Attestations and Attestation Reports, and slashes the signer if they are invalid.\ncontract Inbox is StatementInbox, InboxEvents, InterfaceInbox {\n using AttestationLib for bytes;\n using ReceiptLib for bytes;\n using SnapshotLib for bytes;\n\n // Struct to get around stack too deep error. TODO: revisit this\n struct ReceiptInfo {\n AgentStatus rcptNotaryStatus;\n address notary;\n uint32 attNonce;\n AgentStatus attNotaryStatus;\n }\n\n // ══════════════════════════════════════════════════ STORAGE ══════════════════════════════════════════════════════\n\n // The address of the Summit contract.\n address public summit;\n\n // ═════════════════════════════════════════ CONSTRUCTOR \u0026 INITIALIZER ═════════════════════════════════════════════\n\n constructor(uint32 synapseDomain_) MessagingBase(\"0.0.3\", synapseDomain_) {\n if (localDomain != synapseDomain) revert MustBeSynapseDomain();\n }\n\n /// @notice Initializes `Inbox` contract:\n /// - Sets `msg.sender` as the owner of the contract\n /// - Sets `agentManager`, `origin`, `destination` and `summit` addresses\n function initialize(address agentManager_, address origin_, address destination_, address summit_)\n external\n initializer\n {\n __StatementInbox_init(agentManager_, origin_, destination_);\n summit = summit_;\n }\n\n // ══════════════════════════════════════════ SUBMIT AGENT STATEMENTS ══════════════════════════════════════════════\n\n /// @inheritdoc InterfaceInbox\n function submitSnapshot(bytes memory snapPayload, bytes memory snapSignature)\n external\n returns (bytes memory attPayload, bytes32 agentRoot_, uint256[] memory snapGas)\n {\n // This will revert if payload is not a snapshot\n Snapshot snapshot = snapPayload.castToSnapshot();\n // This will revert if the signer is not a known Guard/Notary\n (AgentStatus memory status, address agent) =\n _verifySnapshot({snapshot: snapshot, snapSignature: snapSignature, verifyNotary: false});\n // Check that Agent is active\n status.verifyActive();\n // Store Agent signature for the Snapshot\n uint256 sigIndex = _saveSignature(snapSignature);\n if (status.domain == 0) {\n // Guard that is in Dispute could still submit new snapshots, so we don't check that\n InterfaceSummit(summit).acceptGuardSnapshot({\n guardIndex: status.index,\n sigIndex: sigIndex,\n snapPayload: snapPayload\n });\n } else {\n // Get current agentRoot from AgentManager\n agentRoot_ = IAgentManager(agentManager).agentRoot();\n // This will revert if Notary is in Dispute\n attPayload = InterfaceSummit(summit).acceptNotarySnapshot({\n notaryIndex: status.index,\n sigIndex: sigIndex,\n agentRoot: agentRoot_,\n snapPayload: snapPayload\n });\n ChainGas[] memory snapGas_ = snapshot.snapGas();\n // Pass created attestation to Destination to enable executing messages coming to Synapse Chain\n InterfaceDestination(destination).acceptAttestation(\n status.index, type(uint256).max, attPayload, agentRoot_, snapGas_\n );\n // Use assembly to cast ChainGas[] to uint256[] without copying. Highest bits are left zeroed.\n // solhint-disable-next-line no-inline-assembly\n assembly {\n snapGas := snapGas_\n }\n }\n emit SnapshotAccepted(status.domain, agent, snapPayload, snapSignature);\n }\n\n /// @inheritdoc InterfaceInbox\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 // Struct to get around stack too deep error.\n ReceiptInfo memory info;\n // This will revert if payload is not a receipt\n Receipt rcpt = rcptPayload.castToReceipt();\n // This will revert if the receipt signer is not a known Notary\n (info.rcptNotaryStatus, info.notary) = _verifyReceipt(rcpt, rcptSignature);\n // Receipt Notary needs to be Active\n info.rcptNotaryStatus.verifyActive();\n info.attNonce = IExecutionHub(destination).getAttestationNonce(rcpt.snapshotRoot());\n if (info.attNonce == 0) revert IncorrectSnapshotRoot();\n // Attestation Notary domain needs to match the destination domain\n info.attNotaryStatus = IAgentManager(agentManager).agentStatus(rcpt.attNotary());\n if (info.attNotaryStatus.domain != rcpt.destination()) revert IncorrectAgentDomain();\n // Check that the correct tip values for the message were provided\n _verifyReceiptTips(rcpt.messageHash(), paddedTips, headerHash, bodyHash);\n // Store Notary signature for the Receipt\n uint256 sigIndex = _saveSignature(rcptSignature);\n // This will revert if Receipt Notary is in Dispute\n wasAccepted = InterfaceSummit(summit).acceptReceipt({\n rcptNotaryIndex: info.rcptNotaryStatus.index,\n attNotaryIndex: info.attNotaryStatus.index,\n sigIndex: sigIndex,\n attNonce: info.attNonce,\n paddedTips: paddedTips,\n rcptPayload: rcptPayload\n });\n if (wasAccepted) {\n emit ReceiptAccepted(info.rcptNotaryStatus.domain, info.notary, rcptPayload, rcptSignature);\n }\n }\n\n /// @inheritdoc InterfaceInbox\n function submitReceiptReport(bytes memory rcptPayload, bytes memory rcptSignature, bytes memory rrSignature)\n external\n returns (bool wasAccepted)\n {\n // This will revert if payload is not a receipt\n Receipt rcpt = rcptPayload.castToReceipt();\n // This will revert if the receipt signer is not a known Guard\n (AgentStatus memory guardStatus,) = _verifyReceiptReport(rcpt, rrSignature);\n // Guard needs to be Active\n guardStatus.verifyActive();\n // This will revert if report signer is not a known Notary\n (AgentStatus memory notaryStatus,) = _verifyReceipt(rcpt, rcptSignature);\n // Notary needs to be Active/Unstaking\n notaryStatus.verifyActiveUnstaking();\n _saveReport(rcptPayload, rrSignature);\n // This will revert if either actor is already in dispute\n IAgentManager(agentManager).openDispute(guardStatus.index, notaryStatus.index);\n return true;\n }\n\n /// @inheritdoc InterfaceInbox\n function passReceipt(uint32 attNotaryIndex, uint32 attNonce, uint256 paddedTips, bytes memory rcptPayload)\n external\n returns (bool wasAccepted)\n {\n // Only Destination can pass receipts\n if (msg.sender != destination) revert CallerNotDestination();\n return InterfaceSummit(summit).acceptReceipt({\n rcptNotaryIndex: attNotaryIndex,\n attNotaryIndex: attNotaryIndex,\n sigIndex: type(uint256).max,\n attNonce: attNonce,\n paddedTips: paddedTips,\n rcptPayload: rcptPayload\n });\n }\n\n // ══════════════════════════════════════════ VERIFY AGENT STATEMENTS ══════════════════════════════════════════════\n\n /// @inheritdoc InterfaceInbox\n function verifyAttestation(bytes memory attPayload, bytes memory attSignature)\n external\n returns (bool isValidAttestation)\n {\n // This will revert if payload is not an attestation\n Attestation att = attPayload.castToAttestation();\n // This will revert if the attestation signer is not a known Notary\n (AgentStatus memory status, address notary) = _verifyAttestation(att, attSignature);\n // Notary needs to be Active/Unstaking\n status.verifyActiveUnstaking();\n isValidAttestation = ISnapshotHub(summit).isValidAttestation(attPayload);\n if (!isValidAttestation) {\n emit InvalidAttestation(attPayload, attSignature);\n IAgentManager(agentManager).slashAgent(status.domain, notary, msg.sender);\n }\n }\n\n /// @inheritdoc InterfaceInbox\n function verifyAttestationReport(bytes memory attPayload, bytes memory arSignature)\n external\n returns (bool isValidReport)\n {\n // This will revert if payload is not an attestation\n Attestation att = attPayload.castToAttestation();\n // This will revert if the report signer is not a known Guard\n (AgentStatus memory status, address guard) = _verifyAttestationReport(att, arSignature);\n // Guard needs to be Active/Unstaking\n status.verifyActiveUnstaking();\n // Report is valid IF AND ONLY IF the reported attestation in invalid\n isValidReport = !ISnapshotHub(summit).isValidAttestation(attPayload);\n if (!isValidReport) {\n emit InvalidAttestationReport(attPayload, arSignature);\n IAgentManager(agentManager).slashAgent(status.domain, guard, msg.sender);\n }\n }\n\n // ══════════════════════════════════════════════ INTERNAL VIEWS ═══════════════════════════════════════════════════\n\n /// @dev Verifies that tips proof matches the message hash.\n function _verifyReceiptTips(bytes32 msgHash, uint256 paddedTips, bytes32 headerHash, bytes32 bodyHash)\n internal\n pure\n {\n Tips tips = TipsLib.wrapPadded(paddedTips);\n // full message leaf is (header, baseMessage), while base message leaf is (tips, remainingBody).\n if (MerkleMath.getParent(headerHash, MerkleMath.getParent(tips.leaf(), bodyHash)) != msgHash) {\n revert IncorrectTipsProof();\n }\n }\n}\n","language":"Solidity","languageVersion":"0.8.17","compilerVersion":"0.8.17","compilerOptions":"--combined-json bin,bin-runtime,srcmap,srcmap-runtime,abi,userdoc,devdoc,metadata,hashes --optimize --optimize-runs 10000 --allow-paths ., ./, ../","srcMap":"116438:19162:0:-:0;;;;;;;;;;;;;;;-1:-1:-1;;;116438:19162:0;;;;;;;;;;;;;;;;;","srcMapRuntime":"116438: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/Inbox.sol\":\"MemViewLib\"},\"evmVersion\":\"london\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\"},\"optimizer\":{\"enabled\":true,\"runs\":10000},\"remappings\":[]},\"sources\":{\"solidity/Inbox.sol\":{\"keccak256\":\"0x9b516081a036814c0169e20e484d4a5499066b7a6f48fada952b5e844a1ca3e5\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://32bde393b3f24ef4307d9626d4143f337b3c0bd34e17bb969fd5a15221d96987\",\"dweb:/ipfs/QmTkt2XZRtgsbSpmsVQUM3c4ebETQoDVYbmEV9yheBghnr\"]}},\"version\":1}"},"hashes":{}},"solidity/Inbox.sol:MerkleMath":{"code":"0x60566037600b82828239805160001a607314602a57634e487b7160e01b600052600060045260246000fd5b30600052607381538281f3fe73000000000000000000000000000000000000000030146080604052600080fdfea2646970667358221220a3431d064e5236768803f20292c0f8b85806268a40f5e3b189ae3a775787799764736f6c63430008110033","runtime-code":"0x73000000000000000000000000000000000000000030146080604052600080fdfea2646970667358221220a3431d064e5236768803f20292c0f8b85806268a40f5e3b189ae3a775787799764736f6c63430008110033","info":{"source":"// SPDX-License-Identifier: MIT\npragma solidity =0.8.17 ^0.8.0 ^0.8.1 ^0.8.2;\n\n// contracts/events/InboxEvents.sol\n\nabstract contract InboxEvents {\n /**\n * @notice Emitted when a snapshot is accepted by the Summit contract.\n * @param domain Domain where the signed Agent is active (ZERO for Guards)\n * @param agent Agent who signed the snapshot\n * @param snapPayload Raw payload with snapshot data\n * @param snapSignature Agent signature for the snapshot\n */\n event SnapshotAccepted(uint32 indexed domain, address indexed agent, bytes snapPayload, bytes snapSignature);\n\n /**\n * @notice Emitted when a snapshot is accepted by the Summit contract.\n * @param domain Domain where the signed Notary is active\n * @param notary Notary who signed the attestation\n * @param rcptPayload Raw payload with receipt data\n * @param rcptSignature Notary signature for the receipt\n */\n event ReceiptAccepted(uint32 domain, address notary, bytes rcptPayload, bytes rcptSignature);\n\n /**\n * @notice Emitted when a proof of invalid attestation is submitted.\n * @param attPayload Raw payload with Attestation data\n * @param attSignature Notary signature for the attestation\n */\n event InvalidAttestation(bytes attPayload, bytes attSignature);\n\n /**\n * @notice Emitted when a proof of invalid attestation report is submitted.\n * @param arPayload Raw payload with report data\n * @param arSignature Guard signature for the report\n */\n event InvalidAttestationReport(bytes arPayload, bytes arSignature);\n}\n\n// contracts/events/StatementInboxEvents.sol\n\nabstract contract StatementInboxEvents {\n // ════════════════════════════════════════════ STATEMENT ACCEPTED ═════════════════════════════════════════════════\n\n /**\n * @notice Emitted when a snapshot is accepted by the Destination contract.\n * @param domain Domain where the signed Notary is active\n * @param notary Notary who signed the attestation\n * @param attPayload Raw payload with attestation data\n * @param attSignature Notary signature for the attestation\n */\n event AttestationAccepted(uint32 domain, address notary, bytes attPayload, bytes attSignature);\n\n // ═════════════════════════════════════════ INVALID STATEMENT PROVED ══════════════════════════════════════════════\n\n /**\n * @notice Emitted when a proof of invalid receipt statement is submitted.\n * @param rcptPayload Raw payload with the receipt statement\n * @param rcptSignature Notary signature for the receipt statement\n */\n event InvalidReceipt(bytes rcptPayload, bytes rcptSignature);\n\n /**\n * @notice Emitted when a proof of invalid receipt report is submitted.\n * @param rrPayload Raw payload with report data\n * @param rrSignature Guard signature for the report\n */\n event InvalidReceiptReport(bytes rrPayload, bytes rrSignature);\n\n /**\n * @notice Emitted when a proof of invalid state in the signed attestation is submitted.\n * @param stateIndex Index of invalid state in the snapshot\n * @param statePayload Raw payload with state data\n * @param attPayload Raw payload with Attestation data for snapshot\n * @param attSignature Notary signature for the attestation\n */\n event InvalidStateWithAttestation(uint8 stateIndex, bytes statePayload, bytes attPayload, bytes attSignature);\n\n /**\n * @notice Emitted when a proof of invalid state in the signed snapshot is submitted.\n * @param stateIndex Index of invalid state in the snapshot\n * @param snapPayload Raw payload with snapshot data\n * @param snapSignature Agent signature for the snapshot\n */\n event InvalidStateWithSnapshot(uint8 stateIndex, bytes snapPayload, bytes snapSignature);\n\n /**\n * @notice Emitted when a proof of invalid state report is submitted.\n * @param srPayload Raw payload with report data\n * @param srSignature Guard signature for the report\n */\n event InvalidStateReport(bytes srPayload, bytes srSignature);\n}\n\n// contracts/interfaces/ISnapshotHub.sol\n\ninterface ISnapshotHub {\n /**\n * @notice Check that a given attestation is valid: matches the historical attestation\n * derived from an accepted Notary snapshot.\n * @dev Will revert if any of these is true:\n * - Attestation payload is not properly formatted.\n * @param attPayload Raw payload with attestation data\n * @return isValid Whether the provided attestation is valid\n */\n function isValidAttestation(bytes memory attPayload) external view returns (bool isValid);\n\n /**\n * @notice Returns saved attestation with the given nonce.\n * @dev Reverts if attestation with given nonce hasn't been created yet.\n * @param attNonce Nonce for the attestation\n * @return attPayload Raw payload with formatted Attestation data\n * @return agentRoot Agent root hash used for the attestation\n * @return snapGas Snapshot gas data used for the attestation\n */\n function getAttestation(uint32 attNonce)\n external\n view\n returns (bytes memory attPayload, bytes32 agentRoot, uint256[] memory snapGas);\n\n /**\n * @notice Returns the state with the highest known nonce submitted by a given Agent.\n * @param origin Domain of origin chain\n * @param agent Agent address\n * @return statePayload Raw payload with agent's latest state for origin\n */\n function getLatestAgentState(uint32 origin, address agent) external view returns (bytes memory statePayload);\n\n /**\n * @notice Returns latest saved attestation for a Notary.\n * @param notary Notary address\n * @return attPayload Raw payload with formatted Attestation data\n * @return agentRoot Agent root hash used for the attestation\n * @return snapGas Snapshot gas data used for the attestation\n */\n function getLatestNotaryAttestation(address notary)\n external\n view\n returns (bytes memory attPayload, bytes32 agentRoot, uint256[] memory snapGas);\n\n /**\n * @notice Returns Guard snapshot from the list of all accepted Guard snapshots.\n * @dev Reverts if snapshot with given index hasn't been accepted yet.\n * @param index Snapshot index in the list of all Guard snapshots\n * @return snapPayload Raw payload with Guard snapshot\n * @return snapSignature Raw payload with Guard signature for snapshot\n */\n function getGuardSnapshot(uint256 index)\n external\n view\n returns (bytes memory snapPayload, bytes memory snapSignature);\n\n /**\n * @notice Returns Notary snapshot from the list of all accepted Guard snapshots.\n * @dev Reverts if snapshot with given index hasn't been accepted yet.\n * @param index Snapshot index in the list of all Notary snapshots\n * @return snapPayload Raw payload with Notary snapshot\n * @return snapSignature Raw payload with Notary signature for snapshot\n */\n function getNotarySnapshot(uint256 index)\n external\n view\n returns (bytes memory snapPayload, bytes memory snapSignature);\n\n /**\n * @notice Returns Notary snapshot that was used for creating a given attestation.\n * @dev Reverts if any of these is true:\n * - Attestation payload is not properly formatted.\n * - Attestation is invalid (doesn't have a matching Notary snapshot).\n * @param attPayload Raw payload with attestation data\n * @return snapPayload Raw payload with Notary snapshot\n * @return snapSignature Raw payload with Notary signature for snapshot\n */\n function getNotarySnapshot(bytes memory attPayload)\n external\n view\n returns (bytes memory snapPayload, bytes memory snapSignature);\n\n /**\n * @notice Returns proof of inclusion of (root, origin) fields of a given snapshot's state\n * into the Snapshot Merkle Tree for a given attestation.\n * @dev Reverts if any of these is true:\n * - Attestation with given nonce hasn't been created yet.\n * - State index is out of range of snapshot list.\n * @param attNonce Nonce for the attestation\n * @param stateIndex Index of state in the attestation's snapshot\n * @return snapProof The snapshot proof\n */\n function getSnapshotProof(uint32 attNonce, uint8 stateIndex) external view returns (bytes32[] memory snapProof);\n}\n\n// contracts/interfaces/IStateHub.sol\n\ninterface IStateHub {\n /**\n * @notice Check that a given state is valid: matches the historical state of Origin contract.\n * Note: any Agent including an invalid state in their snapshot will be slashed\n * upon providing the snapshot and agent signature for it to Origin contract.\n * @dev Will revert if any of these is true:\n * - State payload is not properly formatted.\n * @param statePayload Raw payload with state data\n * @return isValid Whether the provided state is valid\n */\n function isValidState(bytes memory statePayload) external view returns (bool isValid);\n\n /**\n * @notice Returns the amount of saved states so far.\n * @dev This includes the initial state of \"empty Origin Merkle Tree\".\n */\n function statesAmount() external view returns (uint256);\n\n /**\n * @notice Suggest the data (state after latest sent message) to sign for an Agent.\n * Note: signing the suggested state data will will never lead to slashing of the actor,\n * assuming they have confirmed that the block, which number is included in the data,\n * is not subject to reorganization (which is different for every observed chain).\n * @return statePayload Raw payload with the latest state data\n */\n function suggestLatestState() external view returns (bytes memory statePayload);\n\n /**\n * @notice Given the historical nonce, suggest the state data to sign for an Agent.\n * Note: signing the suggested state data will will never lead to slashing of the actor,\n * assuming they have confirmed that the block, which number is included in the data,\n * is not subject to reorganization (which is different for every observed chain).\n * @param nonce Historical nonce to form a state\n * @return statePayload Raw payload with historical state data\n */\n function suggestState(uint32 nonce) external view returns (bytes memory statePayload);\n}\n\n// contracts/interfaces/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/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// node_modules/@openzeppelin/contracts/utils/math/Math.sol\n\n// OpenZeppelin Contracts (last updated v4.9.0) (utils/math/Math.sol)\n\n/**\n * @dev Standard math utilities missing in the Solidity language.\n */\nlibrary Math {\n enum Rounding {\n Down, // Toward negative infinity\n Up, // Toward infinity\n Zero // Toward zero\n }\n\n /**\n * @dev Returns the largest of two numbers.\n */\n function max(uint256 a, uint256 b) internal pure returns (uint256) {\n return a \u003e b ? a : b;\n }\n\n /**\n * @dev Returns the smallest of two numbers.\n */\n function min(uint256 a, uint256 b) internal pure returns (uint256) {\n return a \u003c b ? a : b;\n }\n\n /**\n * @dev Returns the average of two numbers. The result is rounded towards\n * zero.\n */\n function average(uint256 a, uint256 b) internal pure returns (uint256) {\n // (a + b) / 2 can overflow.\n return (a \u0026 b) + (a ^ b) / 2;\n }\n\n /**\n * @dev Returns the ceiling of the division of two numbers.\n *\n * This differs from standard division with `/` in that it rounds up instead\n * of rounding down.\n */\n function ceilDiv(uint256 a, uint256 b) internal pure returns (uint256) {\n // (a + b - 1) / b can overflow on addition, so we distribute.\n return a == 0 ? 0 : (a - 1) / b + 1;\n }\n\n /**\n * @notice Calculates floor(x * y / denominator) with full precision. Throws if result overflows a uint256 or denominator == 0\n * @dev Original credit to Remco Bloemen under MIT license (https://xn--2-umb.com/21/muldiv)\n * with further edits by Uniswap Labs also under MIT license.\n */\n function mulDiv(uint256 x, uint256 y, uint256 denominator) internal pure returns (uint256 result) {\n unchecked {\n // 512-bit multiply [prod1 prod0] = x * y. Compute the product mod 2^256 and mod 2^256 - 1, then use\n // use the Chinese Remainder Theorem to reconstruct the 512 bit result. The result is stored in two 256\n // variables such that product = prod1 * 2^256 + prod0.\n uint256 prod0; // Least significant 256 bits of the product\n uint256 prod1; // Most significant 256 bits of the product\n assembly {\n let mm := mulmod(x, y, not(0))\n prod0 := mul(x, y)\n prod1 := sub(sub(mm, prod0), lt(mm, prod0))\n }\n\n // Handle non-overflow cases, 256 by 256 division.\n if (prod1 == 0) {\n // Solidity will revert if denominator == 0, unlike the div opcode on its own.\n // The surrounding unchecked block does not change this fact.\n // See https://docs.soliditylang.org/en/latest/control-structures.html#checked-or-unchecked-arithmetic.\n return prod0 / denominator;\n }\n\n // Make sure the result is less than 2^256. Also prevents denominator == 0.\n require(denominator \u003e prod1, \"Math: mulDiv overflow\");\n\n ///////////////////////////////////////////////\n // 512 by 256 division.\n ///////////////////////////////////////////////\n\n // Make division exact by subtracting the remainder from [prod1 prod0].\n uint256 remainder;\n assembly {\n // Compute remainder using mulmod.\n remainder := mulmod(x, y, denominator)\n\n // Subtract 256 bit number from 512 bit number.\n prod1 := sub(prod1, gt(remainder, prod0))\n prod0 := sub(prod0, remainder)\n }\n\n // Factor powers of two out of denominator and compute largest power of two divisor of denominator. Always \u003e= 1.\n // See https://cs.stackexchange.com/q/138556/92363.\n\n // Does not overflow because the denominator cannot be zero at this stage in the function.\n uint256 twos = denominator \u0026 (~denominator + 1);\n assembly {\n // Divide denominator by twos.\n denominator := div(denominator, twos)\n\n // Divide [prod1 prod0] by twos.\n prod0 := div(prod0, twos)\n\n // Flip twos such that it is 2^256 / twos. If twos is zero, then it becomes one.\n twos := add(div(sub(0, twos), twos), 1)\n }\n\n // Shift in bits from prod1 into prod0.\n prod0 |= prod1 * twos;\n\n // Invert denominator mod 2^256. Now that denominator is an odd number, it has an inverse modulo 2^256 such\n // that denominator * inv = 1 mod 2^256. Compute the inverse by starting with a seed that is correct for\n // four bits. That is, denominator * inv = 1 mod 2^4.\n uint256 inverse = (3 * denominator) ^ 2;\n\n // Use the Newton-Raphson iteration to improve the precision. Thanks to Hensel's lifting lemma, this also works\n // in modular arithmetic, doubling the correct bits in each step.\n inverse *= 2 - denominator * inverse; // inverse mod 2^8\n inverse *= 2 - denominator * inverse; // inverse mod 2^16\n inverse *= 2 - denominator * inverse; // inverse mod 2^32\n inverse *= 2 - denominator * inverse; // inverse mod 2^64\n inverse *= 2 - denominator * inverse; // inverse mod 2^128\n inverse *= 2 - denominator * inverse; // inverse mod 2^256\n\n // Because the division is now exact we can divide by multiplying with the modular inverse of denominator.\n // This will give us the correct result modulo 2^256. Since the preconditions guarantee that the outcome is\n // less than 2^256, this is the final result. We don't need to compute the high bits of the result and prod1\n // is no longer required.\n result = prod0 * inverse;\n return result;\n }\n }\n\n /**\n * @notice Calculates x * y / denominator with full precision, following the selected rounding direction.\n */\n function mulDiv(uint256 x, uint256 y, uint256 denominator, Rounding rounding) internal pure returns (uint256) {\n uint256 result = mulDiv(x, y, denominator);\n if (rounding == Rounding.Up \u0026\u0026 mulmod(x, y, denominator) \u003e 0) {\n result += 1;\n }\n return result;\n }\n\n /**\n * @dev Returns the square root of a number. If the number is not a perfect square, the value is rounded down.\n *\n * Inspired by Henry S. Warren, Jr.'s \"Hacker's Delight\" (Chapter 11).\n */\n function sqrt(uint256 a) internal pure returns (uint256) {\n if (a == 0) {\n return 0;\n }\n\n // For our first guess, we get the biggest power of 2 which is smaller than the square root of the target.\n //\n // We know that the \"msb\" (most significant bit) of our target number `a` is a power of 2 such that we have\n // `msb(a) \u003c= a \u003c 2*msb(a)`. This value can be written `msb(a)=2**k` with `k=log2(a)`.\n //\n // This can be rewritten `2**log2(a) \u003c= a \u003c 2**(log2(a) + 1)`\n // → `sqrt(2**k) \u003c= sqrt(a) \u003c sqrt(2**(k+1))`\n // → `2**(k/2) \u003c= sqrt(a) \u003c 2**((k+1)/2) \u003c= 2**(k/2 + 1)`\n //\n // Consequently, `2**(log2(a) / 2)` is a good first approximation of `sqrt(a)` with at least 1 correct bit.\n uint256 result = 1 \u003c\u003c (log2(a) \u003e\u003e 1);\n\n // At this point `result` is an estimation with one bit of precision. We know the true value is a uint128,\n // since it is the square root of a uint256. Newton's method converges quadratically (precision doubles at\n // every iteration). We thus need at most 7 iteration to turn our partial result with one bit of precision\n // into the expected uint128 result.\n unchecked {\n result = (result + a / result) \u003e\u003e 1;\n result = (result + a / result) \u003e\u003e 1;\n result = (result + a / result) \u003e\u003e 1;\n result = (result + a / result) \u003e\u003e 1;\n result = (result + a / result) \u003e\u003e 1;\n result = (result + a / result) \u003e\u003e 1;\n result = (result + a / result) \u003e\u003e 1;\n return min(result, a / result);\n }\n }\n\n /**\n * @notice Calculates sqrt(a), following the selected rounding direction.\n */\n function sqrt(uint256 a, Rounding rounding) internal pure returns (uint256) {\n unchecked {\n uint256 result = sqrt(a);\n return result + (rounding == Rounding.Up \u0026\u0026 result * result \u003c a ? 1 : 0);\n }\n }\n\n /**\n * @dev Return the log in base 2, rounded down, of a positive value.\n * Returns 0 if given 0.\n */\n function log2(uint256 value) internal pure returns (uint256) {\n uint256 result = 0;\n unchecked {\n if (value \u003e\u003e 128 \u003e 0) {\n value \u003e\u003e= 128;\n result += 128;\n }\n if (value \u003e\u003e 64 \u003e 0) {\n value \u003e\u003e= 64;\n result += 64;\n }\n if (value \u003e\u003e 32 \u003e 0) {\n value \u003e\u003e= 32;\n result += 32;\n }\n if (value \u003e\u003e 16 \u003e 0) {\n value \u003e\u003e= 16;\n result += 16;\n }\n if (value \u003e\u003e 8 \u003e 0) {\n value \u003e\u003e= 8;\n result += 8;\n }\n if (value \u003e\u003e 4 \u003e 0) {\n value \u003e\u003e= 4;\n result += 4;\n }\n if (value \u003e\u003e 2 \u003e 0) {\n value \u003e\u003e= 2;\n result += 2;\n }\n if (value \u003e\u003e 1 \u003e 0) {\n result += 1;\n }\n }\n return result;\n }\n\n /**\n * @dev Return the log in base 2, following the selected rounding direction, of a positive value.\n * Returns 0 if given 0.\n */\n function log2(uint256 value, Rounding rounding) internal pure returns (uint256) {\n unchecked {\n uint256 result = log2(value);\n return result + (rounding == Rounding.Up \u0026\u0026 1 \u003c\u003c result \u003c value ? 1 : 0);\n }\n }\n\n /**\n * @dev Return the log in base 10, rounded down, of a positive value.\n * Returns 0 if given 0.\n */\n function log10(uint256 value) internal pure returns (uint256) {\n uint256 result = 0;\n unchecked {\n if (value \u003e= 10 ** 64) {\n value /= 10 ** 64;\n result += 64;\n }\n if (value \u003e= 10 ** 32) {\n value /= 10 ** 32;\n result += 32;\n }\n if (value \u003e= 10 ** 16) {\n value /= 10 ** 16;\n result += 16;\n }\n if (value \u003e= 10 ** 8) {\n value /= 10 ** 8;\n result += 8;\n }\n if (value \u003e= 10 ** 4) {\n value /= 10 ** 4;\n result += 4;\n }\n if (value \u003e= 10 ** 2) {\n value /= 10 ** 2;\n result += 2;\n }\n if (value \u003e= 10 ** 1) {\n result += 1;\n }\n }\n return result;\n }\n\n /**\n * @dev Return the log in base 10, following the selected rounding direction, of a positive value.\n * Returns 0 if given 0.\n */\n function log10(uint256 value, Rounding rounding) internal pure returns (uint256) {\n unchecked {\n uint256 result = log10(value);\n return result + (rounding == Rounding.Up \u0026\u0026 10 ** result \u003c value ? 1 : 0);\n }\n }\n\n /**\n * @dev Return the log in base 256, rounded down, of a positive value.\n * Returns 0 if given 0.\n *\n * Adding one to the result gives the number of pairs of hex symbols needed to represent `value` as a hex string.\n */\n function log256(uint256 value) internal pure returns (uint256) {\n uint256 result = 0;\n unchecked {\n if (value \u003e\u003e 128 \u003e 0) {\n value \u003e\u003e= 128;\n result += 16;\n }\n if (value \u003e\u003e 64 \u003e 0) {\n value \u003e\u003e= 64;\n result += 8;\n }\n if (value \u003e\u003e 32 \u003e 0) {\n value \u003e\u003e= 32;\n result += 4;\n }\n if (value \u003e\u003e 16 \u003e 0) {\n value \u003e\u003e= 16;\n result += 2;\n }\n if (value \u003e\u003e 8 \u003e 0) {\n result += 1;\n }\n }\n return result;\n }\n\n /**\n * @dev Return the log in base 256, following the selected rounding direction, of a positive value.\n * Returns 0 if given 0.\n */\n function log256(uint256 value, Rounding rounding) internal pure returns (uint256) {\n unchecked {\n uint256 result = log256(value);\n return result + (rounding == Rounding.Up \u0026\u0026 1 \u003c\u003c (result \u003c\u003c 3) \u003c value ? 1 : 0);\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/utils/math/SignedMath.sol\n\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/math/SignedMath.sol)\n\n/**\n * @dev Standard signed math utilities missing in the Solidity language.\n */\nlibrary SignedMath {\n /**\n * @dev Returns the largest of two signed numbers.\n */\n function max(int256 a, int256 b) internal pure returns (int256) {\n return a \u003e b ? a : b;\n }\n\n /**\n * @dev Returns the smallest of two signed numbers.\n */\n function min(int256 a, int256 b) internal pure returns (int256) {\n return a \u003c b ? a : b;\n }\n\n /**\n * @dev Returns the average of two signed numbers without overflow.\n * The result is rounded towards zero.\n */\n function average(int256 a, int256 b) internal pure returns (int256) {\n // Formula from the book \"Hacker's Delight\"\n int256 x = (a \u0026 b) + ((a ^ b) \u003e\u003e 1);\n return x + (int256(uint256(x) \u003e\u003e 255) \u0026 (a ^ b));\n }\n\n /**\n * @dev Returns the absolute unsigned value of a signed value.\n */\n function abs(int256 n) internal pure returns (uint256) {\n unchecked {\n // must be unchecked in order to support `n = type(int256).min`\n return uint256(n \u003e= 0 ? n : -n);\n }\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// 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/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/InterfaceSummit.sol\n\ninterface InterfaceSummit {\n // ══════════════════════════════════════════ ACCEPT AGENT STATEMENTS ══════════════════════════════════════════════\n\n /**\n * @notice Accepts a receipt, which local `AgentManager` verified to have been signed by an active Notary.\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 * - Notary who signed the receipt is referenced as the \"Receipt Notary\".\n * - Notary who signed the attestation on destination chain is referenced as the \"Attestation Notary\".\n * \u003e Will revert if any of these is true:\n * \u003e - Called by anyone other than local `AgentManager`.\n * \u003e - Receipt body payload is not properly formatted.\n * \u003e - Receipt signer is in Dispute.\n * \u003e - Receipt's snapshot root is unknown.\n * @param rcptNotaryIndex Index of Receipt Notary in Agent Merkle Tree\n * @param attNotaryIndex Index of Attestation Notary in Agent Merkle Tree\n * @param sigIndex Index of stored Notary signature\n * @param attNonce Nonce of the attestation used for proving the executed message\n * @param paddedTips Padded encoded paid tips information\n * @param rcptPayload Raw payload with message execution receipt\n * @return wasAccepted Whether the receipt was accepted\n */\n function acceptReceipt(\n uint32 rcptNotaryIndex,\n uint32 attNotaryIndex,\n uint256 sigIndex,\n uint32 attNonce,\n uint256 paddedTips,\n bytes memory rcptPayload\n ) external returns (bool wasAccepted);\n\n /**\n * @notice Accepts a snapshot, which local `AgentManager` verified to have been signed by an active Guard.\n * \u003e Snapshot is a list of states for a set of Origin contracts residing on any of the chains.\n * All the states in the Guard-signed snapshot become available for Notary signing.\n * \u003e Will revert if any of these is true:\n * \u003e - Called by anyone other than local `AgentManager`.\n * \u003e - Snapshot payload is not properly formatted.\n * \u003e - Snapshot contains a state older then the Guard has previously submitted.\n * @param guardIndex Index of Guard in Agent Merkle Tree\n * @param sigIndex Index of stored Agent signature\n * @param snapPayload Raw payload with snapshot data\n */\n function acceptGuardSnapshot(uint32 guardIndex, uint256 sigIndex, bytes memory snapPayload) external;\n\n /**\n * @notice Accepts a snapshot, which local `AgentManager` verified to have been signed by an active Notary.\n * \u003e Snapshot is a list of states for a set of Origin contracts residing on any of the chains.\n * Snapshot Merkle Root is calculated and saved for valid snapshots, i.e.\n * snapshots which are only using states previously submitted by any of the Guards.\n * - Notary could use states singed by the same of different Guards 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 - Called by anyone other than local `AgentManager`.\n * \u003e - Snapshot payload is not properly formatted.\n * \u003e - Snapshot contains a state older then the Notary has previously submitted.\n * \u003e - Snapshot contains a state that no Guard has previously submitted.\n * @param notaryIndex Index of Notary in Agent Merkle Tree\n * @param sigIndex Index of stored Agent signature\n * @param agentRoot Current root of the Agent Merkle Tree\n * @param snapPayload Raw payload with snapshot data\n * @return attPayload Raw payload with data for attestation derived from Notary snapshot.\n */\n function acceptNotarySnapshot(uint32 notaryIndex, uint256 sigIndex, bytes32 agentRoot, bytes memory snapPayload)\n external\n returns (bytes memory attPayload);\n\n // ════════════════════════════════════════════════ TIPS LOGIC ═════════════════════════════════════════════════════\n\n /**\n * @notice Distributes tips using the first Receipt from the \"receipt quarantine queue\".\n * Possible scenarios:\n * - Receipt queue is empty =\u003e does nothing\n * - Receipt optimistic period is not over =\u003e does nothing\n * - Either of Notaries present in Receipt was slashed =\u003e receipt is deleted from the queue\n * - Either of Notaries present in Receipt in Dispute =\u003e receipt is moved to the end of queue\n * - None of the above =\u003e receipt tips are distributed\n * @dev Returned value makes it possible to do the following: `while (distributeTips()) {}`\n * @return queuePopped Whether the first element was popped from the queue\n */\n function distributeTips() external returns (bool queuePopped);\n\n /**\n * @notice Withdraws locked base message tips from requested domain Origin to the recipient.\n * This is done by a call to a local Origin contract, or by a manager message to the remote chain.\n * @dev This will revert, if the pending balance of origin tips (earned-claimed) is lower than requested.\n * @param origin Domain of chain to withdraw tips on\n * @param amount Amount of tips to withdraw\n */\n function withdrawTips(uint32 origin, uint256 amount) external;\n\n // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════\n\n /**\n * @notice Returns earned and claimed tips for the actor.\n * Note: Tips for address(0) belong to the Treasury.\n * @param actor Address of the actor\n * @param origin Domain where the tips were initially paid\n * @return earned Total amount of origin tips the actor has earned so far\n * @return claimed Total amount of origin tips the actor has claimed so far\n */\n function actorTips(address actor, uint32 origin) external view returns (uint128 earned, uint128 claimed);\n\n /**\n * @notice Returns the amount of receipts in the \"Receipt Quarantine Queue\".\n */\n function receiptQueueLength() external view returns (uint256);\n\n /**\n * @notice Returns the state with the highest known nonce\n * submitted by any of the currently active Guards.\n * @param origin Domain of origin chain\n * @return statePayload Raw payload with latest active Guard state for origin\n */\n function getLatestState(uint32 origin) external view returns (bytes memory statePayload);\n}\n\n// node_modules/@openzeppelin/contracts/utils/Strings.sol\n\n// OpenZeppelin Contracts (last updated v4.9.0) (utils/Strings.sol)\n\n/**\n * @dev String operations.\n */\nlibrary Strings {\n bytes16 private constant _SYMBOLS = \"0123456789abcdef\";\n uint8 private constant _ADDRESS_LENGTH = 20;\n\n /**\n * @dev Converts a `uint256` to its ASCII `string` decimal representation.\n */\n function toString(uint256 value) internal pure returns (string memory) {\n unchecked {\n uint256 length = Math.log10(value) + 1;\n string memory buffer = new string(length);\n uint256 ptr;\n /// @solidity memory-safe-assembly\n assembly {\n ptr := add(buffer, add(32, length))\n }\n while (true) {\n ptr--;\n /// @solidity memory-safe-assembly\n assembly {\n mstore8(ptr, byte(mod(value, 10), _SYMBOLS))\n }\n value /= 10;\n if (value == 0) break;\n }\n return buffer;\n }\n }\n\n /**\n * @dev Converts a `int256` to its ASCII `string` decimal representation.\n */\n function toString(int256 value) internal pure returns (string memory) {\n return string(abi.encodePacked(value \u003c 0 ? \"-\" : \"\", toString(SignedMath.abs(value))));\n }\n\n /**\n * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation.\n */\n function toHexString(uint256 value) internal pure returns (string memory) {\n unchecked {\n return toHexString(value, Math.log256(value) + 1);\n }\n }\n\n /**\n * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length.\n */\n function toHexString(uint256 value, uint256 length) internal pure returns (string memory) {\n bytes memory buffer = new bytes(2 * length + 2);\n buffer[0] = \"0\";\n buffer[1] = \"x\";\n for (uint256 i = 2 * length + 1; i \u003e 1; --i) {\n buffer[i] = _SYMBOLS[value \u0026 0xf];\n value \u003e\u003e= 4;\n }\n require(value == 0, \"Strings: hex length insufficient\");\n return string(buffer);\n }\n\n /**\n * @dev Converts an `address` with fixed length of 20 bytes to its not checksummed ASCII `string` hexadecimal representation.\n */\n function toHexString(address addr) internal pure returns (string memory) {\n return toHexString(uint256(uint160(addr)), _ADDRESS_LENGTH);\n }\n\n /**\n * @dev Returns true if the two strings are equal.\n */\n function equal(string memory a, string memory b) internal pure returns (bool) {\n return keccak256(bytes(a)) == keccak256(bytes(b));\n }\n}\n\n// node_modules/@openzeppelin/contracts-upgradeable/utils/ContextUpgradeable.sol\n\n// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)\n\n/**\n * @dev Provides information about the current execution context, including the\n * sender of the transaction and its data. While these are generally available\n * via msg.sender and msg.data, they should not be accessed in such a direct\n * manner, since when dealing with meta-transactions the account sending and\n * paying for execution may not be the actual sender (as far as an application\n * is concerned).\n *\n * This contract is only required for intermediate, library-like contracts.\n */\nabstract contract ContextUpgradeable is Initializable {\n function __Context_init() internal onlyInitializing {\n }\n\n function __Context_init_unchained() internal onlyInitializing {\n }\n function _msgSender() internal view virtual returns (address) {\n return msg.sender;\n }\n\n function _msgData() internal view virtual returns (bytes calldata) {\n return msg.data;\n }\n\n /**\n * @dev This empty reserved space is put in place to allow future versions to add new\n * variables without shifting down storage in the inheritance chain.\n * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\n */\n uint256[50] private __gap;\n}\n\n// contracts/libs/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/utils/cryptography/ECDSA.sol\n\n// OpenZeppelin Contracts (last updated v4.9.0) (utils/cryptography/ECDSA.sol)\n\n/**\n * @dev Elliptic Curve Digital Signature Algorithm (ECDSA) operations.\n *\n * These functions can be used to verify that a message was signed by the holder\n * of the private keys of a given address.\n */\nlibrary ECDSA {\n enum RecoverError {\n NoError,\n InvalidSignature,\n InvalidSignatureLength,\n InvalidSignatureS,\n InvalidSignatureV // Deprecated in v4.8\n }\n\n function _throwError(RecoverError error) private pure {\n if (error == RecoverError.NoError) {\n return; // no error: do nothing\n } else if (error == RecoverError.InvalidSignature) {\n revert(\"ECDSA: invalid signature\");\n } else if (error == RecoverError.InvalidSignatureLength) {\n revert(\"ECDSA: invalid signature length\");\n } else if (error == RecoverError.InvalidSignatureS) {\n revert(\"ECDSA: invalid signature 's' value\");\n }\n }\n\n /**\n * @dev Returns the address that signed a hashed message (`hash`) with\n * `signature` or error string. This address can then be used for verification purposes.\n *\n * The `ecrecover` EVM opcode allows for malleable (non-unique) signatures:\n * this function rejects them by requiring the `s` value to be in the lower\n * half order, and the `v` value to be either 27 or 28.\n *\n * IMPORTANT: `hash` _must_ be the result of a hash operation for the\n * verification to be secure: it is possible to craft signatures that\n * recover to arbitrary addresses for non-hashed data. A safe way to ensure\n * this is by receiving a hash of the original message (which may otherwise\n * be too long), and then calling {toEthSignedMessageHash} on it.\n *\n * Documentation for signature generation:\n * - with https://web3js.readthedocs.io/en/v1.3.4/web3-eth-accounts.html#sign[Web3.js]\n * - with https://docs.ethers.io/v5/api/signer/#Signer-signMessage[ethers]\n *\n * _Available since v4.3._\n */\n function tryRecover(bytes32 hash, bytes memory signature) internal pure returns (address, RecoverError) {\n if (signature.length == 65) {\n bytes32 r;\n bytes32 s;\n uint8 v;\n // ecrecover takes the signature parameters, and the only way to get them\n // currently is to use assembly.\n /// @solidity memory-safe-assembly\n assembly {\n r := mload(add(signature, 0x20))\n s := mload(add(signature, 0x40))\n v := byte(0, mload(add(signature, 0x60)))\n }\n return tryRecover(hash, v, r, s);\n } else {\n return (address(0), RecoverError.InvalidSignatureLength);\n }\n }\n\n /**\n * @dev Returns the address that signed a hashed message (`hash`) with\n * `signature`. This address can then be used for verification purposes.\n *\n * The `ecrecover` EVM opcode allows for malleable (non-unique) signatures:\n * this function rejects them by requiring the `s` value to be in the lower\n * half order, and the `v` value to be either 27 or 28.\n *\n * IMPORTANT: `hash` _must_ be the result of a hash operation for the\n * verification to be secure: it is possible to craft signatures that\n * recover to arbitrary addresses for non-hashed data. A safe way to ensure\n * this is by receiving a hash of the original message (which may otherwise\n * be too long), and then calling {toEthSignedMessageHash} on it.\n */\n function recover(bytes32 hash, bytes memory signature) internal pure returns (address) {\n (address recovered, RecoverError error) = tryRecover(hash, signature);\n _throwError(error);\n return recovered;\n }\n\n /**\n * @dev Overload of {ECDSA-tryRecover} that receives the `r` and `vs` short-signature fields separately.\n *\n * See https://eips.ethereum.org/EIPS/eip-2098[EIP-2098 short signatures]\n *\n * _Available since v4.3._\n */\n function tryRecover(bytes32 hash, bytes32 r, bytes32 vs) internal pure returns (address, RecoverError) {\n bytes32 s = vs \u0026 bytes32(0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff);\n uint8 v = uint8((uint256(vs) \u003e\u003e 255) + 27);\n return tryRecover(hash, v, r, s);\n }\n\n /**\n * @dev Overload of {ECDSA-recover} that receives the `r and `vs` short-signature fields separately.\n *\n * _Available since v4.2._\n */\n function recover(bytes32 hash, bytes32 r, bytes32 vs) internal pure returns (address) {\n (address recovered, RecoverError error) = tryRecover(hash, r, vs);\n _throwError(error);\n return recovered;\n }\n\n /**\n * @dev Overload of {ECDSA-tryRecover} that receives the `v`,\n * `r` and `s` signature fields separately.\n *\n * _Available since v4.3._\n */\n function tryRecover(bytes32 hash, uint8 v, bytes32 r, bytes32 s) internal pure returns (address, RecoverError) {\n // EIP-2 still allows signature malleability for ecrecover(). Remove this possibility and make the signature\n // unique. Appendix F in the Ethereum Yellow paper (https://ethereum.github.io/yellowpaper/paper.pdf), defines\n // the valid range for s in (301): 0 \u003c s \u003c secp256k1n ÷ 2 + 1, and for v in (302): v ∈ {27, 28}. Most\n // signatures from current libraries generate a unique signature with an s-value in the lower half order.\n //\n // If your library generates malleable signatures, such as s-values in the upper range, calculate a new s-value\n // with 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141 - s1 and flip v from 27 to 28 or\n // vice versa. If your library also generates signatures with 0/1 for v instead 27/28, add 27 to v to accept\n // these malleable signatures as well.\n if (uint256(s) \u003e 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0) {\n return (address(0), RecoverError.InvalidSignatureS);\n }\n\n // If the signature is valid (and not malleable), return the signer address\n address signer = ecrecover(hash, v, r, s);\n if (signer == address(0)) {\n return (address(0), RecoverError.InvalidSignature);\n }\n\n return (signer, RecoverError.NoError);\n }\n\n /**\n * @dev Overload of {ECDSA-recover} that receives the `v`,\n * `r` and `s` signature fields separately.\n */\n function recover(bytes32 hash, uint8 v, bytes32 r, bytes32 s) internal pure returns (address) {\n (address recovered, RecoverError error) = tryRecover(hash, v, r, s);\n _throwError(error);\n return recovered;\n }\n\n /**\n * @dev Returns an Ethereum Signed Message, created from a `hash`. This\n * produces hash corresponding to the one signed with the\n * https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`]\n * JSON-RPC method as part of EIP-191.\n *\n * See {recover}.\n */\n function toEthSignedMessageHash(bytes32 hash) internal pure returns (bytes32 message) {\n // 32 is the length in bytes of hash,\n // enforced by the type signature above\n /// @solidity memory-safe-assembly\n assembly {\n mstore(0x00, \"\\x19Ethereum Signed Message:\\n32\")\n mstore(0x1c, hash)\n message := keccak256(0x00, 0x3c)\n }\n }\n\n /**\n * @dev Returns an Ethereum Signed Message, created from `s`. This\n * produces hash corresponding to the one signed with the\n * https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`]\n * JSON-RPC method as part of EIP-191.\n *\n * See {recover}.\n */\n function toEthSignedMessageHash(bytes memory s) internal pure returns (bytes32) {\n return keccak256(abi.encodePacked(\"\\x19Ethereum Signed Message:\\n\", Strings.toString(s.length), s));\n }\n\n /**\n * @dev Returns an Ethereum Signed Typed Data, created from a\n * `domainSeparator` and a `structHash`. This produces hash corresponding\n * to the one signed with the\n * https://eips.ethereum.org/EIPS/eip-712[`eth_signTypedData`]\n * JSON-RPC method as part of EIP-712.\n *\n * See {recover}.\n */\n function toTypedDataHash(bytes32 domainSeparator, bytes32 structHash) internal pure returns (bytes32 data) {\n /// @solidity memory-safe-assembly\n assembly {\n let ptr := mload(0x40)\n mstore(ptr, \"\\x19\\x01\")\n mstore(add(ptr, 0x02), domainSeparator)\n mstore(add(ptr, 0x22), structHash)\n data := keccak256(ptr, 0x42)\n }\n }\n\n /**\n * @dev Returns an Ethereum Signed Data with intended validator, created from a\n * `validator` and `data` according to the version 0 of EIP-191.\n *\n * See {recover}.\n */\n function toDataWithIntendedValidatorHash(address validator, bytes memory data) internal pure returns (bytes32) {\n return keccak256(abi.encodePacked(\"\\x19\\x00\", validator, data));\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/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/inbox/StatementInbox.sol\n\n// ══════════════════════════════ LIBRARY IMPORTS ══════════════════════════════\n\n// ═════════════════════════════ INTERNAL IMPORTS ══════════════════════════════\n\n// ═════════════════════════════ EXTERNAL IMPORTS ══════════════════════════════\n\n/// @notice `StatementInbox` is the entry point for all agent-signed statements. It verifies the\n/// agent signatures, and passes the unsigned statements to the contract to consume it via `acceptX` functions. Is is\n/// also used to verify the agent-signed statements and initiate the agent slashing, should the statement be invalid.\n/// `StatementInbox` is responsible for the following:\n/// - Accepting State and Receipt Reports to initiate a dispute between Guard and Notary.\n/// - Storing all the Guard Reports with the Guard signature leading to a dispute.\n/// - Verifying State/State Reports referencing the local chain and slashing the signer if statement is invalid.\n/// - Verifying Receipt/Receipt Reports referencing the local chain and slashing the signer if statement is invalid.\nabstract contract StatementInbox is MessagingBase, StatementInboxEvents, IStatementInbox {\n using AttestationLib for bytes;\n using ReceiptLib for bytes;\n using StateLib for bytes;\n using SnapshotLib for bytes;\n\n struct StoredReport {\n uint256 sigIndex;\n bytes statementPayload;\n }\n\n // ══════════════════════════════════════════════════ STORAGE ══════════════════════════════════════════════════════\n\n address public agentManager;\n address public origin;\n address public destination;\n\n // TODO: optimize this\n bytes[] internal _storedSignatures;\n StoredReport[] internal _storedReports;\n\n /// @dev gap for upgrade safety\n uint256[45] private __GAP; // solhint-disable-line var-name-mixedcase\n\n // ════════════════════════════════════════════════ INITIALIZER ════════════════════════════════════════════════════\n\n /// @dev Initializes the contract:\n /// - Sets up `msg.sender` as the owner of the contract.\n /// - Sets up `agentManager`, `origin`, and `destination`.\n // solhint-disable-next-line func-name-mixedcase\n function __StatementInbox_init(address agentManager_, address origin_, address destination_)\n internal\n onlyInitializing\n {\n agentManager = agentManager_;\n origin = origin_;\n destination = destination_;\n __Ownable2Step_init();\n }\n\n // ══════════════════════════════════════════ SUBMIT AGENT STATEMENTS ══════════════════════════════════════════════\n\n /// @inheritdoc IStatementInbox\n // solhint-disable-next-line ordering\n function submitStateReportWithSnapshot(\n uint8 stateIndex,\n bytes memory srSignature,\n bytes memory snapPayload,\n bytes memory snapSignature\n ) external returns (bool wasAccepted) {\n // This will revert if payload is not a snapshot\n Snapshot snapshot = snapPayload.castToSnapshot();\n // This will revert if the snapshot signer is not a known Notary\n (AgentStatus memory notaryStatus,) =\n _verifySnapshot({snapshot: snapshot, snapSignature: snapSignature, verifyNotary: true});\n // Notary needs to be Active/Unstaking\n notaryStatus.verifyActiveUnstaking();\n // Check if Notary is active on this chain\n _verifyNotaryDomain(notaryStatus.domain);\n // This will revert if state index is out of range\n State state = snapshot.state(stateIndex);\n // This will revert if the report signer is not an known Guard\n (AgentStatus memory guardStatus,) = _verifyStateReport(state, srSignature);\n // Check that Guard is active\n guardStatus.verifyActive();\n _saveReport(state.unwrap().clone(), srSignature);\n // This will revert if either actor is already in dispute\n IAgentManager(agentManager).openDispute(guardStatus.index, notaryStatus.index);\n return true;\n }\n\n /// @inheritdoc IStatementInbox\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 // This will revert if payload is not a snapshot\n Snapshot snapshot = snapPayload.castToSnapshot();\n // This will revert if state index is out of range\n State state = snapshot.state(stateIndex);\n // This will revert if the report signer is not an known Guard\n (AgentStatus memory guardStatus,) = _verifyStateReport(state, srSignature);\n // Check that Guard is active\n guardStatus.verifyActive();\n // This will revert if payload is not an attestation\n Attestation att = attPayload.castToAttestation();\n // This will revert if signer is not an known Notary\n (AgentStatus memory notaryStatus,) = _verifyAttestation(att, attSignature);\n // Notary needs to be Active/Unstaking\n notaryStatus.verifyActiveUnstaking();\n // Check if Notary is active on this chain\n _verifyNotaryDomain(notaryStatus.domain);\n if (snapshot.calculateRoot() != att.snapRoot()) revert IncorrectSnapshotRoot();\n _saveReport(state.unwrap().clone(), srSignature);\n // This will revert if either actor is already in dispute\n IAgentManager(agentManager).openDispute(guardStatus.index, notaryStatus.index);\n return true;\n }\n\n /// @inheritdoc IStatementInbox\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 // This will revert if payload is not a state\n State state = statePayload.castToState();\n // This will revert if the report signer is not an known Guard\n (AgentStatus memory guardStatus,) = _verifyStateReport(state, srSignature);\n // Check that Guard is active\n guardStatus.verifyActive();\n // This will revert if payload is not an attestation\n Attestation att = attPayload.castToAttestation();\n // This will revert if signer is not a known Notary\n (AgentStatus memory notaryStatus,) = _verifyAttestation(att, attSignature);\n // Notary needs to be Active/Unstaking\n notaryStatus.verifyActiveUnstaking();\n // Check if Notary is active on this chain\n _verifyNotaryDomain(notaryStatus.domain);\n // This will revert if any of these is true:\n // - Attestation root is not equal to Merkle Root derived from State and Snapshot Proof.\n // - Snapshot Proof's first element does not match the State metadata.\n // - Snapshot Proof length exceeds Snapshot tree Height.\n // - State index is out of range.\n _verifySnapshotMerkle(att, stateIndex, state, snapProof);\n _saveReport(statePayload, srSignature);\n // This will revert if either actor is already in dispute\n IAgentManager(agentManager).openDispute(guardStatus.index, notaryStatus.index);\n return true;\n }\n\n // ══════════════════════════════════════════ VERIFY AGENT STATEMENTS ══════════════════════════════════════════════\n\n /// @inheritdoc IStatementInbox\n function verifyReceipt(bytes memory rcptPayload, bytes memory rcptSignature)\n external\n returns (bool isValidReceipt)\n {\n // This will revert if payload is not a receipt\n Receipt rcpt = rcptPayload.castToReceipt();\n // This will revert if the attestation signer is not a known Notary\n (AgentStatus memory status, address notary) = _verifyReceipt(rcpt, rcptSignature);\n // Notary needs to be Active/Unstaking\n status.verifyActiveUnstaking();\n isValidReceipt = IExecutionHub(destination).isValidReceipt(rcptPayload);\n if (!isValidReceipt) {\n emit InvalidReceipt(rcptPayload, rcptSignature);\n IAgentManager(agentManager).slashAgent(status.domain, notary, msg.sender);\n }\n }\n\n /// @inheritdoc IStatementInbox\n function verifyReceiptReport(bytes memory rcptPayload, bytes memory rrSignature)\n external\n returns (bool isValidReport)\n {\n // This will revert if payload is not a receipt\n Receipt rcpt = rcptPayload.castToReceipt();\n // This will revert if the report signer is not a known Guard\n (AgentStatus memory status, address guard) = _verifyReceiptReport(rcpt, rrSignature);\n // Guard needs to be Active/Unstaking\n status.verifyActiveUnstaking();\n // Report is valid IF AND ONLY IF the reported receipt in invalid\n isValidReport = !IExecutionHub(destination).isValidReceipt(rcptPayload);\n if (!isValidReport) {\n emit InvalidReceiptReport(rcptPayload, rrSignature);\n IAgentManager(agentManager).slashAgent(status.domain, guard, msg.sender);\n }\n }\n\n /// @inheritdoc IStatementInbox\n function verifyStateWithAttestation(\n uint8 stateIndex,\n bytes memory snapPayload,\n bytes memory attPayload,\n bytes memory attSignature\n ) external returns (bool isValidState) {\n // This will revert if payload is not an attestation\n Attestation att = attPayload.castToAttestation();\n // This will revert if the attestation signer is not a known Notary\n (AgentStatus memory status, address notary) = _verifyAttestation(att, attSignature);\n // Notary needs to be Active/Unstaking\n status.verifyActiveUnstaking();\n // This will revert if payload is not a snapshot\n Snapshot snapshot = snapPayload.castToSnapshot();\n if (snapshot.calculateRoot() != att.snapRoot()) revert IncorrectSnapshotRoot();\n // This will revert if state does not refer to this chain\n bytes memory statePayload = snapshot.state(stateIndex).unwrap().clone();\n isValidState = IStateHub(origin).isValidState(statePayload);\n if (!isValidState) {\n emit InvalidStateWithAttestation(stateIndex, statePayload, attPayload, attSignature);\n IAgentManager(agentManager).slashAgent(status.domain, notary, msg.sender);\n }\n }\n\n /// @inheritdoc IStatementInbox\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 // This will revert if payload is not an attestation\n Attestation att = attPayload.castToAttestation();\n // This will revert if the attestation signer is not a known Notary\n (AgentStatus memory status, address notary) = _verifyAttestation(att, attSignature);\n // Notary needs to be Active/Unstaking\n status.verifyActiveUnstaking();\n // This will revert if payload is not a state\n State state = statePayload.castToState();\n // This will revert if any of these is true:\n // - Attestation root is not equal to Merkle Root derived from State and Snapshot Proof.\n // - Snapshot Proof's first element does not match the State metadata.\n // - Snapshot Proof length exceeds Snapshot tree Height.\n // - State index is out of range.\n _verifySnapshotMerkle(att, stateIndex, state, snapProof);\n // This will revert if state does not refer to this chain\n isValidState = IStateHub(origin).isValidState(statePayload);\n if (!isValidState) {\n emit InvalidStateWithAttestation(stateIndex, statePayload, attPayload, attSignature);\n IAgentManager(agentManager).slashAgent(status.domain, notary, msg.sender);\n }\n }\n\n /// @inheritdoc IStatementInbox\n function verifyStateWithSnapshot(uint8 stateIndex, bytes memory snapPayload, bytes memory snapSignature)\n external\n returns (bool isValidState)\n {\n // This will revert if payload is not a snapshot\n Snapshot snapshot = snapPayload.castToSnapshot();\n // This will revert if the snapshot signer is not a known Guard/Notary\n (AgentStatus memory status, address agent) =\n _verifySnapshot({snapshot: snapshot, snapSignature: snapSignature, verifyNotary: false});\n // Agent needs to be Active/Unstaking\n status.verifyActiveUnstaking();\n // This will revert if state does not refer to this chain\n isValidState = IStateHub(origin).isValidState(snapshot.state(stateIndex).unwrap().clone());\n if (!isValidState) {\n emit InvalidStateWithSnapshot(stateIndex, snapPayload, snapSignature);\n IAgentManager(agentManager).slashAgent(status.domain, agent, msg.sender);\n }\n }\n\n /// @inheritdoc IStatementInbox\n function verifyStateReport(bytes memory statePayload, bytes memory srSignature)\n external\n returns (bool isValidReport)\n {\n // This will revert if payload is not a state\n State state = statePayload.castToState();\n // This will revert if the report signer is not a known Guard\n (AgentStatus memory status, address guard) = _verifyStateReport(state, srSignature);\n // Guard needs to be Active/Unstaking\n status.verifyActiveUnstaking();\n // Report is valid IF AND ONLY IF the reported state in invalid\n // This will revert if the reported state does not refer to this chain\n isValidReport = !IStateHub(origin).isValidState(statePayload);\n if (!isValidReport) {\n emit InvalidStateReport(statePayload, srSignature);\n IAgentManager(agentManager).slashAgent(status.domain, guard, msg.sender);\n }\n }\n\n // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════\n\n /// @inheritdoc IStatementInbox\n function getReportsAmount() external view returns (uint256) {\n return _storedReports.length;\n }\n\n /// @inheritdoc IStatementInbox\n function getGuardReport(uint256 index)\n external\n view\n returns (bytes memory statementPayload, bytes memory reportSignature)\n {\n if (index \u003e= _storedReports.length) revert IndexOutOfRange();\n StoredReport memory storedReport = _storedReports[index];\n statementPayload = storedReport.statementPayload;\n reportSignature = _storedSignatures[storedReport.sigIndex];\n }\n\n /// @inheritdoc IStatementInbox\n function getStoredSignature(uint256 index) external view returns (bytes memory) {\n return _storedSignatures[index];\n }\n\n // ══════════════════════════════════════════════ INTERNAL LOGIC ═══════════════════════════════════════════════════\n\n /// @dev Saves the statement reported by Guard as invalid and the Guard Report signature.\n function _saveReport(bytes memory statementPayload, bytes memory reportSignature) internal {\n uint256 sigIndex = _saveSignature(reportSignature);\n _storedReports.push(StoredReport(sigIndex, statementPayload));\n }\n\n /// @dev Saves the signature and returns its index.\n function _saveSignature(bytes memory signature) internal returns (uint256 sigIndex) {\n sigIndex = _storedSignatures.length;\n _storedSignatures.push(signature);\n }\n\n // ═══════════════════════════════════════════════ AGENT CHECKS ════════════════════════════════════════════════════\n\n /**\n * @dev Recovers a signer from a hashed message, and a EIP-191 signature for it.\n * Will revert, if the signer is not a known agent.\n * @dev Agent flag could be any of these: Active/Unstaking/Resting/Fraudulent/Slashed\n * Further checks need to be performed in a caller function.\n * @param hashedStatement Hash of the statement that was signed by an Agent\n * @param signature Agent signature for the hashed statement\n * @return status Struct representing agent status:\n * - flag Unknown/Active/Unstaking/Resting/Fraudulent/Slashed\n * - domain Domain where agent is/was active\n * - index Index of agent in the Agent Merkle Tree\n * @return agent Agent that signed the statement\n */\n function _recoverAgent(bytes32 hashedStatement, bytes memory signature)\n internal\n view\n returns (AgentStatus memory status, address agent)\n {\n bytes32 ethSignedMsg = ECDSA.toEthSignedMessageHash(hashedStatement);\n agent = ECDSA.recover(ethSignedMsg, signature);\n status = IAgentManager(agentManager).agentStatus(agent);\n // Discard signature of unknown agents.\n // Further flag checks are supposed to be performed in a caller function.\n status.verifyKnown();\n }\n\n /// @dev Verifies that Notary signature is active on local domain.\n function _verifyNotaryDomain(uint32 notaryDomain) internal view {\n // Notary needs to be from the local domain (if contract is not deployed on Synapse Chain).\n // Or Notary could be from any domain (if contract is deployed on Synapse Chain).\n if (notaryDomain != localDomain \u0026\u0026 localDomain != synapseDomain) revert IncorrectAgentDomain();\n }\n\n // ════════════════════════════════════════ ATTESTATION RELATED CHECKS ═════════════════════════════════════════════\n\n /**\n * @dev Internal function to verify the signed attestation payload.\n * Reverts if any of these is true:\n * - Attestation signer is not a known Notary.\n * @param att Typed memory view over attestation payload\n * @param attSignature Notary signature for the attestation\n * @return status Struct representing agent status, see {_recoverAgent}\n * @return notary Notary that signed the snapshot\n */\n function _verifyAttestation(Attestation att, bytes memory attSignature)\n internal\n view\n returns (AgentStatus memory status, address notary)\n {\n // This will revert if signer is not a known agent\n (status, notary) = _recoverAgent(att.hashValid(), attSignature);\n // Attestation signer needs to be a Notary, not a Guard\n if (status.domain == 0) revert AgentNotNotary();\n }\n\n /**\n * @dev Internal function to verify the signed attestation report payload.\n * Reverts if any of these is true:\n * - Report signer is not a known Guard.\n * @param att Typed memory view over attestation payload that Guard reports as invalid\n * @param arSignature Guard signature for the \"invalid attestation\" report\n * @return status Struct representing guard status, see {_recoverAgent}\n * @return guard Guard that signed the report\n */\n function _verifyAttestationReport(Attestation att, bytes memory arSignature)\n internal\n view\n returns (AgentStatus memory status, address guard)\n {\n // This will revert if signer is not a known agent\n (status, guard) = _recoverAgent(att.hashInvalid(), arSignature);\n // Report signer needs to be a Guard, not a Notary\n if (status.domain != 0) revert AgentNotGuard();\n }\n\n // ══════════════════════════════════════════ RECEIPT RELATED CHECKS ═══════════════════════════════════════════════\n\n /**\n * @dev Internal function to verify the signed receipt payload.\n * Reverts if any of these is true:\n * - Receipt signer is not a known Notary.\n * @param rcpt Typed memory view over receipt payload\n * @param rcptSignature Notary signature for the receipt\n * @return status Struct representing agent status, see {_recoverAgent}\n * @return notary Notary that signed the snapshot\n */\n function _verifyReceipt(Receipt rcpt, bytes memory rcptSignature)\n internal\n view\n returns (AgentStatus memory status, address notary)\n {\n // This will revert if signer is not a known agent\n (status, notary) = _recoverAgent(rcpt.hashValid(), rcptSignature);\n // Receipt signer needs to be a Notary, not a Guard\n if (status.domain == 0) revert AgentNotNotary();\n }\n\n /**\n * @dev Internal function to verify the signed receipt report payload.\n * Reverts if any of these is true:\n * - Report signer is not a known Guard.\n * @param rcpt Typed memory view over receipt payload that Guard reports as invalid\n * @param rrSignature Guard signature for the \"invalid receipt\" report\n * @return status Struct representing guard status, see {_recoverAgent}\n * @return guard Guard that signed the report\n */\n function _verifyReceiptReport(Receipt rcpt, bytes memory rrSignature)\n internal\n view\n returns (AgentStatus memory status, address guard)\n {\n // This will revert if signer is not a known agent\n (status, guard) = _recoverAgent(rcpt.hashInvalid(), rrSignature);\n // Report signer needs to be a Guard, not a Notary\n if (status.domain != 0) revert AgentNotGuard();\n }\n\n // ═══════════════════════════════════════ STATE/SNAPSHOT RELATED CHECKS ═══════════════════════════════════════════\n\n /**\n * @dev Internal function to verify the signed snapshot report payload.\n * Reverts if any of these is true:\n * - Report signer is not a known Guard.\n * @param state Typed memory view over state payload that Guard reports as invalid\n * @param srSignature Guard signature for the report\n * @return status Struct representing guard status, see {_recoverAgent}\n * @return guard Guard that signed the report\n */\n function _verifyStateReport(State state, bytes memory srSignature)\n internal\n view\n returns (AgentStatus memory status, address guard)\n {\n // This will revert if signer is not a known agent\n (status, guard) = _recoverAgent(state.hashInvalid(), srSignature);\n // Report signer needs to be a Guard, not a Notary\n if (status.domain != 0) revert AgentNotGuard();\n }\n\n /**\n * @dev Internal function to verify the signed snapshot payload.\n * Reverts if any of these is true:\n * - Snapshot signer is not a known Agent.\n * - Snapshot signer is not a Notary (if verifyNotary is true).\n * @param snapshot Typed memory view over snapshot payload\n * @param snapSignature Agent signature for the snapshot\n * @param verifyNotary If true, snapshot signer needs to be a Notary, not a Guard\n * @return status Struct representing agent status, see {_recoverAgent}\n * @return agent Agent that signed the snapshot\n */\n function _verifySnapshot(Snapshot snapshot, bytes memory snapSignature, bool verifyNotary)\n internal\n view\n returns (AgentStatus memory status, address agent)\n {\n // This will revert if signer is not a known agent\n (status, agent) = _recoverAgent(snapshot.hashValid(), snapSignature);\n // If requested, snapshot signer needs to be a Notary, not a Guard\n if (verifyNotary \u0026\u0026 status.domain == 0) revert AgentNotNotary();\n }\n\n // ═══════════════════════════════════════════ MERKLE RELATED CHECKS ═══════════════════════════════════════════════\n\n /**\n * @dev Internal function to verify that snapshot roots match.\n * Reverts if any of these is true:\n * - Attestation root is not equal to Merkle Root derived from State and Snapshot Proof.\n * - Snapshot Proof's first element does not match the State metadata.\n * - Snapshot Proof length exceeds Snapshot tree Height.\n * - State index is out of range.\n * @param att Typed memory view over Attestation\n * @param stateIndex Index of state in the snapshot\n * @param state Typed memory view over the provided state payload\n * @param snapProof Raw payload with snapshot data\n */\n function _verifySnapshotMerkle(Attestation att, uint8 stateIndex, State state, bytes32[] memory snapProof)\n internal\n pure\n {\n // Snapshot proof first element should match State metadata (aka \"right sub-leaf\")\n (, bytes32 rightSubLeaf) = state.subLeafs();\n if (snapProof[0] != rightSubLeaf) revert IncorrectSnapshotProof();\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(state.root(), state.origin(), snapProof, stateIndex);\n // Snapshot root should match the attestation root\n if (att.snapRoot() != snapshotRoot) revert IncorrectSnapshotRoot();\n }\n}\n\n// contracts/inbox/Inbox.sol\n\n// ══════════════════════════════ LIBRARY IMPORTS ══════════════════════════════\n\n// ═════════════════════════════ INTERNAL IMPORTS ══════════════════════════════\n\n/// @notice `Inbox` is the child of `StatementInbox` contract, that is used on Synapse Chain.\n/// In addition to the functionality of `StatementInbox`, it also:\n/// - Accepts Guard and Notary Snapshots and passes them to `Summit` contract.\n/// - Accepts Notary-signed Receipts and passes them to `Summit` contract.\n/// - Accepts Receipt Reports to initiate a dispute between Guard and Notary.\n/// - Verifies Attestations and Attestation Reports, and slashes the signer if they are invalid.\ncontract Inbox is StatementInbox, InboxEvents, InterfaceInbox {\n using AttestationLib for bytes;\n using ReceiptLib for bytes;\n using SnapshotLib for bytes;\n\n // Struct to get around stack too deep error. TODO: revisit this\n struct ReceiptInfo {\n AgentStatus rcptNotaryStatus;\n address notary;\n uint32 attNonce;\n AgentStatus attNotaryStatus;\n }\n\n // ══════════════════════════════════════════════════ STORAGE ══════════════════════════════════════════════════════\n\n // The address of the Summit contract.\n address public summit;\n\n // ═════════════════════════════════════════ CONSTRUCTOR \u0026 INITIALIZER ═════════════════════════════════════════════\n\n constructor(uint32 synapseDomain_) MessagingBase(\"0.0.3\", synapseDomain_) {\n if (localDomain != synapseDomain) revert MustBeSynapseDomain();\n }\n\n /// @notice Initializes `Inbox` contract:\n /// - Sets `msg.sender` as the owner of the contract\n /// - Sets `agentManager`, `origin`, `destination` and `summit` addresses\n function initialize(address agentManager_, address origin_, address destination_, address summit_)\n external\n initializer\n {\n __StatementInbox_init(agentManager_, origin_, destination_);\n summit = summit_;\n }\n\n // ══════════════════════════════════════════ SUBMIT AGENT STATEMENTS ══════════════════════════════════════════════\n\n /// @inheritdoc InterfaceInbox\n function submitSnapshot(bytes memory snapPayload, bytes memory snapSignature)\n external\n returns (bytes memory attPayload, bytes32 agentRoot_, uint256[] memory snapGas)\n {\n // This will revert if payload is not a snapshot\n Snapshot snapshot = snapPayload.castToSnapshot();\n // This will revert if the signer is not a known Guard/Notary\n (AgentStatus memory status, address agent) =\n _verifySnapshot({snapshot: snapshot, snapSignature: snapSignature, verifyNotary: false});\n // Check that Agent is active\n status.verifyActive();\n // Store Agent signature for the Snapshot\n uint256 sigIndex = _saveSignature(snapSignature);\n if (status.domain == 0) {\n // Guard that is in Dispute could still submit new snapshots, so we don't check that\n InterfaceSummit(summit).acceptGuardSnapshot({\n guardIndex: status.index,\n sigIndex: sigIndex,\n snapPayload: snapPayload\n });\n } else {\n // Get current agentRoot from AgentManager\n agentRoot_ = IAgentManager(agentManager).agentRoot();\n // This will revert if Notary is in Dispute\n attPayload = InterfaceSummit(summit).acceptNotarySnapshot({\n notaryIndex: status.index,\n sigIndex: sigIndex,\n agentRoot: agentRoot_,\n snapPayload: snapPayload\n });\n ChainGas[] memory snapGas_ = snapshot.snapGas();\n // Pass created attestation to Destination to enable executing messages coming to Synapse Chain\n InterfaceDestination(destination).acceptAttestation(\n status.index, type(uint256).max, attPayload, agentRoot_, snapGas_\n );\n // Use assembly to cast ChainGas[] to uint256[] without copying. Highest bits are left zeroed.\n // solhint-disable-next-line no-inline-assembly\n assembly {\n snapGas := snapGas_\n }\n }\n emit SnapshotAccepted(status.domain, agent, snapPayload, snapSignature);\n }\n\n /// @inheritdoc InterfaceInbox\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 // Struct to get around stack too deep error.\n ReceiptInfo memory info;\n // This will revert if payload is not a receipt\n Receipt rcpt = rcptPayload.castToReceipt();\n // This will revert if the receipt signer is not a known Notary\n (info.rcptNotaryStatus, info.notary) = _verifyReceipt(rcpt, rcptSignature);\n // Receipt Notary needs to be Active\n info.rcptNotaryStatus.verifyActive();\n info.attNonce = IExecutionHub(destination).getAttestationNonce(rcpt.snapshotRoot());\n if (info.attNonce == 0) revert IncorrectSnapshotRoot();\n // Attestation Notary domain needs to match the destination domain\n info.attNotaryStatus = IAgentManager(agentManager).agentStatus(rcpt.attNotary());\n if (info.attNotaryStatus.domain != rcpt.destination()) revert IncorrectAgentDomain();\n // Check that the correct tip values for the message were provided\n _verifyReceiptTips(rcpt.messageHash(), paddedTips, headerHash, bodyHash);\n // Store Notary signature for the Receipt\n uint256 sigIndex = _saveSignature(rcptSignature);\n // This will revert if Receipt Notary is in Dispute\n wasAccepted = InterfaceSummit(summit).acceptReceipt({\n rcptNotaryIndex: info.rcptNotaryStatus.index,\n attNotaryIndex: info.attNotaryStatus.index,\n sigIndex: sigIndex,\n attNonce: info.attNonce,\n paddedTips: paddedTips,\n rcptPayload: rcptPayload\n });\n if (wasAccepted) {\n emit ReceiptAccepted(info.rcptNotaryStatus.domain, info.notary, rcptPayload, rcptSignature);\n }\n }\n\n /// @inheritdoc InterfaceInbox\n function submitReceiptReport(bytes memory rcptPayload, bytes memory rcptSignature, bytes memory rrSignature)\n external\n returns (bool wasAccepted)\n {\n // This will revert if payload is not a receipt\n Receipt rcpt = rcptPayload.castToReceipt();\n // This will revert if the receipt signer is not a known Guard\n (AgentStatus memory guardStatus,) = _verifyReceiptReport(rcpt, rrSignature);\n // Guard needs to be Active\n guardStatus.verifyActive();\n // This will revert if report signer is not a known Notary\n (AgentStatus memory notaryStatus,) = _verifyReceipt(rcpt, rcptSignature);\n // Notary needs to be Active/Unstaking\n notaryStatus.verifyActiveUnstaking();\n _saveReport(rcptPayload, rrSignature);\n // This will revert if either actor is already in dispute\n IAgentManager(agentManager).openDispute(guardStatus.index, notaryStatus.index);\n return true;\n }\n\n /// @inheritdoc InterfaceInbox\n function passReceipt(uint32 attNotaryIndex, uint32 attNonce, uint256 paddedTips, bytes memory rcptPayload)\n external\n returns (bool wasAccepted)\n {\n // Only Destination can pass receipts\n if (msg.sender != destination) revert CallerNotDestination();\n return InterfaceSummit(summit).acceptReceipt({\n rcptNotaryIndex: attNotaryIndex,\n attNotaryIndex: attNotaryIndex,\n sigIndex: type(uint256).max,\n attNonce: attNonce,\n paddedTips: paddedTips,\n rcptPayload: rcptPayload\n });\n }\n\n // ══════════════════════════════════════════ VERIFY AGENT STATEMENTS ══════════════════════════════════════════════\n\n /// @inheritdoc InterfaceInbox\n function verifyAttestation(bytes memory attPayload, bytes memory attSignature)\n external\n returns (bool isValidAttestation)\n {\n // This will revert if payload is not an attestation\n Attestation att = attPayload.castToAttestation();\n // This will revert if the attestation signer is not a known Notary\n (AgentStatus memory status, address notary) = _verifyAttestation(att, attSignature);\n // Notary needs to be Active/Unstaking\n status.verifyActiveUnstaking();\n isValidAttestation = ISnapshotHub(summit).isValidAttestation(attPayload);\n if (!isValidAttestation) {\n emit InvalidAttestation(attPayload, attSignature);\n IAgentManager(agentManager).slashAgent(status.domain, notary, msg.sender);\n }\n }\n\n /// @inheritdoc InterfaceInbox\n function verifyAttestationReport(bytes memory attPayload, bytes memory arSignature)\n external\n returns (bool isValidReport)\n {\n // This will revert if payload is not an attestation\n Attestation att = attPayload.castToAttestation();\n // This will revert if the report signer is not a known Guard\n (AgentStatus memory status, address guard) = _verifyAttestationReport(att, arSignature);\n // Guard needs to be Active/Unstaking\n status.verifyActiveUnstaking();\n // Report is valid IF AND ONLY IF the reported attestation in invalid\n isValidReport = !ISnapshotHub(summit).isValidAttestation(attPayload);\n if (!isValidReport) {\n emit InvalidAttestationReport(attPayload, arSignature);\n IAgentManager(agentManager).slashAgent(status.domain, guard, msg.sender);\n }\n }\n\n // ══════════════════════════════════════════════ INTERNAL VIEWS ═══════════════════════════════════════════════════\n\n /// @dev Verifies that tips proof matches the message hash.\n function _verifyReceiptTips(bytes32 msgHash, uint256 paddedTips, bytes32 headerHash, bytes32 bodyHash)\n internal\n pure\n {\n Tips tips = TipsLib.wrapPadded(paddedTips);\n // full message leaf is (header, baseMessage), while base message leaf is (tips, remainingBody).\n if (MerkleMath.getParent(headerHash, MerkleMath.getParent(tips.leaf(), bodyHash)) != msgHash) {\n revert IncorrectTipsProof();\n }\n }\n}\n","language":"Solidity","languageVersion":"0.8.17","compilerVersion":"0.8.17","compilerOptions":"--combined-json bin,bin-runtime,srcmap,srcmap-runtime,abi,userdoc,devdoc,metadata,hashes --optimize --optimize-runs 10000 --allow-paths ., ./, ../","srcMap":"135643:9845:0:-:0;;;;;;;;;;;;;;;-1:-1:-1;;;135643:9845:0;;;;;;;;;;;;;;;;;","srcMapRuntime":"135643: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/Inbox.sol\":\"MerkleMath\"},\"evmVersion\":\"london\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\"},\"optimizer\":{\"enabled\":true,\"runs\":10000},\"remappings\":[]},\"sources\":{\"solidity/Inbox.sol\":{\"keccak256\":\"0x9b516081a036814c0169e20e484d4a5499066b7a6f48fada952b5e844a1ca3e5\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://32bde393b3f24ef4307d9626d4143f337b3c0bd34e17bb969fd5a15221d96987\",\"dweb:/ipfs/QmTkt2XZRtgsbSpmsVQUM3c4ebETQoDVYbmEV9yheBghnr\"]}},\"version\":1}"},"hashes":{}},"solidity/Inbox.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/InboxEvents.sol\n\nabstract contract InboxEvents {\n /**\n * @notice Emitted when a snapshot is accepted by the Summit contract.\n * @param domain Domain where the signed Agent is active (ZERO for Guards)\n * @param agent Agent who signed the snapshot\n * @param snapPayload Raw payload with snapshot data\n * @param snapSignature Agent signature for the snapshot\n */\n event SnapshotAccepted(uint32 indexed domain, address indexed agent, bytes snapPayload, bytes snapSignature);\n\n /**\n * @notice Emitted when a snapshot is accepted by the Summit contract.\n * @param domain Domain where the signed Notary is active\n * @param notary Notary who signed the attestation\n * @param rcptPayload Raw payload with receipt data\n * @param rcptSignature Notary signature for the receipt\n */\n event ReceiptAccepted(uint32 domain, address notary, bytes rcptPayload, bytes rcptSignature);\n\n /**\n * @notice Emitted when a proof of invalid attestation is submitted.\n * @param attPayload Raw payload with Attestation data\n * @param attSignature Notary signature for the attestation\n */\n event InvalidAttestation(bytes attPayload, bytes attSignature);\n\n /**\n * @notice Emitted when a proof of invalid attestation report is submitted.\n * @param arPayload Raw payload with report data\n * @param arSignature Guard signature for the report\n */\n event InvalidAttestationReport(bytes arPayload, bytes arSignature);\n}\n\n// contracts/events/StatementInboxEvents.sol\n\nabstract contract StatementInboxEvents {\n // ════════════════════════════════════════════ STATEMENT ACCEPTED ═════════════════════════════════════════════════\n\n /**\n * @notice Emitted when a snapshot is accepted by the Destination contract.\n * @param domain Domain where the signed Notary is active\n * @param notary Notary who signed the attestation\n * @param attPayload Raw payload with attestation data\n * @param attSignature Notary signature for the attestation\n */\n event AttestationAccepted(uint32 domain, address notary, bytes attPayload, bytes attSignature);\n\n // ═════════════════════════════════════════ INVALID STATEMENT PROVED ══════════════════════════════════════════════\n\n /**\n * @notice Emitted when a proof of invalid receipt statement is submitted.\n * @param rcptPayload Raw payload with the receipt statement\n * @param rcptSignature Notary signature for the receipt statement\n */\n event InvalidReceipt(bytes rcptPayload, bytes rcptSignature);\n\n /**\n * @notice Emitted when a proof of invalid receipt report is submitted.\n * @param rrPayload Raw payload with report data\n * @param rrSignature Guard signature for the report\n */\n event InvalidReceiptReport(bytes rrPayload, bytes rrSignature);\n\n /**\n * @notice Emitted when a proof of invalid state in the signed attestation is submitted.\n * @param stateIndex Index of invalid state in the snapshot\n * @param statePayload Raw payload with state data\n * @param attPayload Raw payload with Attestation data for snapshot\n * @param attSignature Notary signature for the attestation\n */\n event InvalidStateWithAttestation(uint8 stateIndex, bytes statePayload, bytes attPayload, bytes attSignature);\n\n /**\n * @notice Emitted when a proof of invalid state in the signed snapshot is submitted.\n * @param stateIndex Index of invalid state in the snapshot\n * @param snapPayload Raw payload with snapshot data\n * @param snapSignature Agent signature for the snapshot\n */\n event InvalidStateWithSnapshot(uint8 stateIndex, bytes snapPayload, bytes snapSignature);\n\n /**\n * @notice Emitted when a proof of invalid state report is submitted.\n * @param srPayload Raw payload with report data\n * @param srSignature Guard signature for the report\n */\n event InvalidStateReport(bytes srPayload, bytes srSignature);\n}\n\n// contracts/interfaces/ISnapshotHub.sol\n\ninterface ISnapshotHub {\n /**\n * @notice Check that a given attestation is valid: matches the historical attestation\n * derived from an accepted Notary snapshot.\n * @dev Will revert if any of these is true:\n * - Attestation payload is not properly formatted.\n * @param attPayload Raw payload with attestation data\n * @return isValid Whether the provided attestation is valid\n */\n function isValidAttestation(bytes memory attPayload) external view returns (bool isValid);\n\n /**\n * @notice Returns saved attestation with the given nonce.\n * @dev Reverts if attestation with given nonce hasn't been created yet.\n * @param attNonce Nonce for the attestation\n * @return attPayload Raw payload with formatted Attestation data\n * @return agentRoot Agent root hash used for the attestation\n * @return snapGas Snapshot gas data used for the attestation\n */\n function getAttestation(uint32 attNonce)\n external\n view\n returns (bytes memory attPayload, bytes32 agentRoot, uint256[] memory snapGas);\n\n /**\n * @notice Returns the state with the highest known nonce submitted by a given Agent.\n * @param origin Domain of origin chain\n * @param agent Agent address\n * @return statePayload Raw payload with agent's latest state for origin\n */\n function getLatestAgentState(uint32 origin, address agent) external view returns (bytes memory statePayload);\n\n /**\n * @notice Returns latest saved attestation for a Notary.\n * @param notary Notary address\n * @return attPayload Raw payload with formatted Attestation data\n * @return agentRoot Agent root hash used for the attestation\n * @return snapGas Snapshot gas data used for the attestation\n */\n function getLatestNotaryAttestation(address notary)\n external\n view\n returns (bytes memory attPayload, bytes32 agentRoot, uint256[] memory snapGas);\n\n /**\n * @notice Returns Guard snapshot from the list of all accepted Guard snapshots.\n * @dev Reverts if snapshot with given index hasn't been accepted yet.\n * @param index Snapshot index in the list of all Guard snapshots\n * @return snapPayload Raw payload with Guard snapshot\n * @return snapSignature Raw payload with Guard signature for snapshot\n */\n function getGuardSnapshot(uint256 index)\n external\n view\n returns (bytes memory snapPayload, bytes memory snapSignature);\n\n /**\n * @notice Returns Notary snapshot from the list of all accepted Guard snapshots.\n * @dev Reverts if snapshot with given index hasn't been accepted yet.\n * @param index Snapshot index in the list of all Notary snapshots\n * @return snapPayload Raw payload with Notary snapshot\n * @return snapSignature Raw payload with Notary signature for snapshot\n */\n function getNotarySnapshot(uint256 index)\n external\n view\n returns (bytes memory snapPayload, bytes memory snapSignature);\n\n /**\n * @notice Returns Notary snapshot that was used for creating a given attestation.\n * @dev Reverts if any of these is true:\n * - Attestation payload is not properly formatted.\n * - Attestation is invalid (doesn't have a matching Notary snapshot).\n * @param attPayload Raw payload with attestation data\n * @return snapPayload Raw payload with Notary snapshot\n * @return snapSignature Raw payload with Notary signature for snapshot\n */\n function getNotarySnapshot(bytes memory attPayload)\n external\n view\n returns (bytes memory snapPayload, bytes memory snapSignature);\n\n /**\n * @notice Returns proof of inclusion of (root, origin) fields of a given snapshot's state\n * into the Snapshot Merkle Tree for a given attestation.\n * @dev Reverts if any of these is true:\n * - Attestation with given nonce hasn't been created yet.\n * - State index is out of range of snapshot list.\n * @param attNonce Nonce for the attestation\n * @param stateIndex Index of state in the attestation's snapshot\n * @return snapProof The snapshot proof\n */\n function getSnapshotProof(uint32 attNonce, uint8 stateIndex) external view returns (bytes32[] memory snapProof);\n}\n\n// contracts/interfaces/IStateHub.sol\n\ninterface IStateHub {\n /**\n * @notice Check that a given state is valid: matches the historical state of Origin contract.\n * Note: any Agent including an invalid state in their snapshot will be slashed\n * upon providing the snapshot and agent signature for it to Origin contract.\n * @dev Will revert if any of these is true:\n * - State payload is not properly formatted.\n * @param statePayload Raw payload with state data\n * @return isValid Whether the provided state is valid\n */\n function isValidState(bytes memory statePayload) external view returns (bool isValid);\n\n /**\n * @notice Returns the amount of saved states so far.\n * @dev This includes the initial state of \"empty Origin Merkle Tree\".\n */\n function statesAmount() external view returns (uint256);\n\n /**\n * @notice Suggest the data (state after latest sent message) to sign for an Agent.\n * Note: signing the suggested state data will will never lead to slashing of the actor,\n * assuming they have confirmed that the block, which number is included in the data,\n * is not subject to reorganization (which is different for every observed chain).\n * @return statePayload Raw payload with the latest state data\n */\n function suggestLatestState() external view returns (bytes memory statePayload);\n\n /**\n * @notice Given the historical nonce, suggest the state data to sign for an Agent.\n * Note: signing the suggested state data will will never lead to slashing of the actor,\n * assuming they have confirmed that the block, which number is included in the data,\n * is not subject to reorganization (which is different for every observed chain).\n * @param nonce Historical nonce to form a state\n * @return statePayload Raw payload with historical state data\n */\n function suggestState(uint32 nonce) external view returns (bytes memory statePayload);\n}\n\n// contracts/interfaces/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/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// node_modules/@openzeppelin/contracts/utils/math/Math.sol\n\n// OpenZeppelin Contracts (last updated v4.9.0) (utils/math/Math.sol)\n\n/**\n * @dev Standard math utilities missing in the Solidity language.\n */\nlibrary Math {\n enum Rounding {\n Down, // Toward negative infinity\n Up, // Toward infinity\n Zero // Toward zero\n }\n\n /**\n * @dev Returns the largest of two numbers.\n */\n function max(uint256 a, uint256 b) internal pure returns (uint256) {\n return a \u003e b ? a : b;\n }\n\n /**\n * @dev Returns the smallest of two numbers.\n */\n function min(uint256 a, uint256 b) internal pure returns (uint256) {\n return a \u003c b ? a : b;\n }\n\n /**\n * @dev Returns the average of two numbers. The result is rounded towards\n * zero.\n */\n function average(uint256 a, uint256 b) internal pure returns (uint256) {\n // (a + b) / 2 can overflow.\n return (a \u0026 b) + (a ^ b) / 2;\n }\n\n /**\n * @dev Returns the ceiling of the division of two numbers.\n *\n * This differs from standard division with `/` in that it rounds up instead\n * of rounding down.\n */\n function ceilDiv(uint256 a, uint256 b) internal pure returns (uint256) {\n // (a + b - 1) / b can overflow on addition, so we distribute.\n return a == 0 ? 0 : (a - 1) / b + 1;\n }\n\n /**\n * @notice Calculates floor(x * y / denominator) with full precision. Throws if result overflows a uint256 or denominator == 0\n * @dev Original credit to Remco Bloemen under MIT license (https://xn--2-umb.com/21/muldiv)\n * with further edits by Uniswap Labs also under MIT license.\n */\n function mulDiv(uint256 x, uint256 y, uint256 denominator) internal pure returns (uint256 result) {\n unchecked {\n // 512-bit multiply [prod1 prod0] = x * y. Compute the product mod 2^256 and mod 2^256 - 1, then use\n // use the Chinese Remainder Theorem to reconstruct the 512 bit result. The result is stored in two 256\n // variables such that product = prod1 * 2^256 + prod0.\n uint256 prod0; // Least significant 256 bits of the product\n uint256 prod1; // Most significant 256 bits of the product\n assembly {\n let mm := mulmod(x, y, not(0))\n prod0 := mul(x, y)\n prod1 := sub(sub(mm, prod0), lt(mm, prod0))\n }\n\n // Handle non-overflow cases, 256 by 256 division.\n if (prod1 == 0) {\n // Solidity will revert if denominator == 0, unlike the div opcode on its own.\n // The surrounding unchecked block does not change this fact.\n // See https://docs.soliditylang.org/en/latest/control-structures.html#checked-or-unchecked-arithmetic.\n return prod0 / denominator;\n }\n\n // Make sure the result is less than 2^256. Also prevents denominator == 0.\n require(denominator \u003e prod1, \"Math: mulDiv overflow\");\n\n ///////////////////////////////////////////////\n // 512 by 256 division.\n ///////////////////////////////////////////////\n\n // Make division exact by subtracting the remainder from [prod1 prod0].\n uint256 remainder;\n assembly {\n // Compute remainder using mulmod.\n remainder := mulmod(x, y, denominator)\n\n // Subtract 256 bit number from 512 bit number.\n prod1 := sub(prod1, gt(remainder, prod0))\n prod0 := sub(prod0, remainder)\n }\n\n // Factor powers of two out of denominator and compute largest power of two divisor of denominator. Always \u003e= 1.\n // See https://cs.stackexchange.com/q/138556/92363.\n\n // Does not overflow because the denominator cannot be zero at this stage in the function.\n uint256 twos = denominator \u0026 (~denominator + 1);\n assembly {\n // Divide denominator by twos.\n denominator := div(denominator, twos)\n\n // Divide [prod1 prod0] by twos.\n prod0 := div(prod0, twos)\n\n // Flip twos such that it is 2^256 / twos. If twos is zero, then it becomes one.\n twos := add(div(sub(0, twos), twos), 1)\n }\n\n // Shift in bits from prod1 into prod0.\n prod0 |= prod1 * twos;\n\n // Invert denominator mod 2^256. Now that denominator is an odd number, it has an inverse modulo 2^256 such\n // that denominator * inv = 1 mod 2^256. Compute the inverse by starting with a seed that is correct for\n // four bits. That is, denominator * inv = 1 mod 2^4.\n uint256 inverse = (3 * denominator) ^ 2;\n\n // Use the Newton-Raphson iteration to improve the precision. Thanks to Hensel's lifting lemma, this also works\n // in modular arithmetic, doubling the correct bits in each step.\n inverse *= 2 - denominator * inverse; // inverse mod 2^8\n inverse *= 2 - denominator * inverse; // inverse mod 2^16\n inverse *= 2 - denominator * inverse; // inverse mod 2^32\n inverse *= 2 - denominator * inverse; // inverse mod 2^64\n inverse *= 2 - denominator * inverse; // inverse mod 2^128\n inverse *= 2 - denominator * inverse; // inverse mod 2^256\n\n // Because the division is now exact we can divide by multiplying with the modular inverse of denominator.\n // This will give us the correct result modulo 2^256. Since the preconditions guarantee that the outcome is\n // less than 2^256, this is the final result. We don't need to compute the high bits of the result and prod1\n // is no longer required.\n result = prod0 * inverse;\n return result;\n }\n }\n\n /**\n * @notice Calculates x * y / denominator with full precision, following the selected rounding direction.\n */\n function mulDiv(uint256 x, uint256 y, uint256 denominator, Rounding rounding) internal pure returns (uint256) {\n uint256 result = mulDiv(x, y, denominator);\n if (rounding == Rounding.Up \u0026\u0026 mulmod(x, y, denominator) \u003e 0) {\n result += 1;\n }\n return result;\n }\n\n /**\n * @dev Returns the square root of a number. If the number is not a perfect square, the value is rounded down.\n *\n * Inspired by Henry S. Warren, Jr.'s \"Hacker's Delight\" (Chapter 11).\n */\n function sqrt(uint256 a) internal pure returns (uint256) {\n if (a == 0) {\n return 0;\n }\n\n // For our first guess, we get the biggest power of 2 which is smaller than the square root of the target.\n //\n // We know that the \"msb\" (most significant bit) of our target number `a` is a power of 2 such that we have\n // `msb(a) \u003c= a \u003c 2*msb(a)`. This value can be written `msb(a)=2**k` with `k=log2(a)`.\n //\n // This can be rewritten `2**log2(a) \u003c= a \u003c 2**(log2(a) + 1)`\n // → `sqrt(2**k) \u003c= sqrt(a) \u003c sqrt(2**(k+1))`\n // → `2**(k/2) \u003c= sqrt(a) \u003c 2**((k+1)/2) \u003c= 2**(k/2 + 1)`\n //\n // Consequently, `2**(log2(a) / 2)` is a good first approximation of `sqrt(a)` with at least 1 correct bit.\n uint256 result = 1 \u003c\u003c (log2(a) \u003e\u003e 1);\n\n // At this point `result` is an estimation with one bit of precision. We know the true value is a uint128,\n // since it is the square root of a uint256. Newton's method converges quadratically (precision doubles at\n // every iteration). We thus need at most 7 iteration to turn our partial result with one bit of precision\n // into the expected uint128 result.\n unchecked {\n result = (result + a / result) \u003e\u003e 1;\n result = (result + a / result) \u003e\u003e 1;\n result = (result + a / result) \u003e\u003e 1;\n result = (result + a / result) \u003e\u003e 1;\n result = (result + a / result) \u003e\u003e 1;\n result = (result + a / result) \u003e\u003e 1;\n result = (result + a / result) \u003e\u003e 1;\n return min(result, a / result);\n }\n }\n\n /**\n * @notice Calculates sqrt(a), following the selected rounding direction.\n */\n function sqrt(uint256 a, Rounding rounding) internal pure returns (uint256) {\n unchecked {\n uint256 result = sqrt(a);\n return result + (rounding == Rounding.Up \u0026\u0026 result * result \u003c a ? 1 : 0);\n }\n }\n\n /**\n * @dev Return the log in base 2, rounded down, of a positive value.\n * Returns 0 if given 0.\n */\n function log2(uint256 value) internal pure returns (uint256) {\n uint256 result = 0;\n unchecked {\n if (value \u003e\u003e 128 \u003e 0) {\n value \u003e\u003e= 128;\n result += 128;\n }\n if (value \u003e\u003e 64 \u003e 0) {\n value \u003e\u003e= 64;\n result += 64;\n }\n if (value \u003e\u003e 32 \u003e 0) {\n value \u003e\u003e= 32;\n result += 32;\n }\n if (value \u003e\u003e 16 \u003e 0) {\n value \u003e\u003e= 16;\n result += 16;\n }\n if (value \u003e\u003e 8 \u003e 0) {\n value \u003e\u003e= 8;\n result += 8;\n }\n if (value \u003e\u003e 4 \u003e 0) {\n value \u003e\u003e= 4;\n result += 4;\n }\n if (value \u003e\u003e 2 \u003e 0) {\n value \u003e\u003e= 2;\n result += 2;\n }\n if (value \u003e\u003e 1 \u003e 0) {\n result += 1;\n }\n }\n return result;\n }\n\n /**\n * @dev Return the log in base 2, following the selected rounding direction, of a positive value.\n * Returns 0 if given 0.\n */\n function log2(uint256 value, Rounding rounding) internal pure returns (uint256) {\n unchecked {\n uint256 result = log2(value);\n return result + (rounding == Rounding.Up \u0026\u0026 1 \u003c\u003c result \u003c value ? 1 : 0);\n }\n }\n\n /**\n * @dev Return the log in base 10, rounded down, of a positive value.\n * Returns 0 if given 0.\n */\n function log10(uint256 value) internal pure returns (uint256) {\n uint256 result = 0;\n unchecked {\n if (value \u003e= 10 ** 64) {\n value /= 10 ** 64;\n result += 64;\n }\n if (value \u003e= 10 ** 32) {\n value /= 10 ** 32;\n result += 32;\n }\n if (value \u003e= 10 ** 16) {\n value /= 10 ** 16;\n result += 16;\n }\n if (value \u003e= 10 ** 8) {\n value /= 10 ** 8;\n result += 8;\n }\n if (value \u003e= 10 ** 4) {\n value /= 10 ** 4;\n result += 4;\n }\n if (value \u003e= 10 ** 2) {\n value /= 10 ** 2;\n result += 2;\n }\n if (value \u003e= 10 ** 1) {\n result += 1;\n }\n }\n return result;\n }\n\n /**\n * @dev Return the log in base 10, following the selected rounding direction, of a positive value.\n * Returns 0 if given 0.\n */\n function log10(uint256 value, Rounding rounding) internal pure returns (uint256) {\n unchecked {\n uint256 result = log10(value);\n return result + (rounding == Rounding.Up \u0026\u0026 10 ** result \u003c value ? 1 : 0);\n }\n }\n\n /**\n * @dev Return the log in base 256, rounded down, of a positive value.\n * Returns 0 if given 0.\n *\n * Adding one to the result gives the number of pairs of hex symbols needed to represent `value` as a hex string.\n */\n function log256(uint256 value) internal pure returns (uint256) {\n uint256 result = 0;\n unchecked {\n if (value \u003e\u003e 128 \u003e 0) {\n value \u003e\u003e= 128;\n result += 16;\n }\n if (value \u003e\u003e 64 \u003e 0) {\n value \u003e\u003e= 64;\n result += 8;\n }\n if (value \u003e\u003e 32 \u003e 0) {\n value \u003e\u003e= 32;\n result += 4;\n }\n if (value \u003e\u003e 16 \u003e 0) {\n value \u003e\u003e= 16;\n result += 2;\n }\n if (value \u003e\u003e 8 \u003e 0) {\n result += 1;\n }\n }\n return result;\n }\n\n /**\n * @dev Return the log in base 256, following the selected rounding direction, of a positive value.\n * Returns 0 if given 0.\n */\n function log256(uint256 value, Rounding rounding) internal pure returns (uint256) {\n unchecked {\n uint256 result = log256(value);\n return result + (rounding == Rounding.Up \u0026\u0026 1 \u003c\u003c (result \u003c\u003c 3) \u003c value ? 1 : 0);\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/utils/math/SignedMath.sol\n\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/math/SignedMath.sol)\n\n/**\n * @dev Standard signed math utilities missing in the Solidity language.\n */\nlibrary SignedMath {\n /**\n * @dev Returns the largest of two signed numbers.\n */\n function max(int256 a, int256 b) internal pure returns (int256) {\n return a \u003e b ? a : b;\n }\n\n /**\n * @dev Returns the smallest of two signed numbers.\n */\n function min(int256 a, int256 b) internal pure returns (int256) {\n return a \u003c b ? a : b;\n }\n\n /**\n * @dev Returns the average of two signed numbers without overflow.\n * The result is rounded towards zero.\n */\n function average(int256 a, int256 b) internal pure returns (int256) {\n // Formula from the book \"Hacker's Delight\"\n int256 x = (a \u0026 b) + ((a ^ b) \u003e\u003e 1);\n return x + (int256(uint256(x) \u003e\u003e 255) \u0026 (a ^ b));\n }\n\n /**\n * @dev Returns the absolute unsigned value of a signed value.\n */\n function abs(int256 n) internal pure returns (uint256) {\n unchecked {\n // must be unchecked in order to support `n = type(int256).min`\n return uint256(n \u003e= 0 ? n : -n);\n }\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// 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/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/InterfaceSummit.sol\n\ninterface InterfaceSummit {\n // ══════════════════════════════════════════ ACCEPT AGENT STATEMENTS ══════════════════════════════════════════════\n\n /**\n * @notice Accepts a receipt, which local `AgentManager` verified to have been signed by an active Notary.\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 * - Notary who signed the receipt is referenced as the \"Receipt Notary\".\n * - Notary who signed the attestation on destination chain is referenced as the \"Attestation Notary\".\n * \u003e Will revert if any of these is true:\n * \u003e - Called by anyone other than local `AgentManager`.\n * \u003e - Receipt body payload is not properly formatted.\n * \u003e - Receipt signer is in Dispute.\n * \u003e - Receipt's snapshot root is unknown.\n * @param rcptNotaryIndex Index of Receipt Notary in Agent Merkle Tree\n * @param attNotaryIndex Index of Attestation Notary in Agent Merkle Tree\n * @param sigIndex Index of stored Notary signature\n * @param attNonce Nonce of the attestation used for proving the executed message\n * @param paddedTips Padded encoded paid tips information\n * @param rcptPayload Raw payload with message execution receipt\n * @return wasAccepted Whether the receipt was accepted\n */\n function acceptReceipt(\n uint32 rcptNotaryIndex,\n uint32 attNotaryIndex,\n uint256 sigIndex,\n uint32 attNonce,\n uint256 paddedTips,\n bytes memory rcptPayload\n ) external returns (bool wasAccepted);\n\n /**\n * @notice Accepts a snapshot, which local `AgentManager` verified to have been signed by an active Guard.\n * \u003e Snapshot is a list of states for a set of Origin contracts residing on any of the chains.\n * All the states in the Guard-signed snapshot become available for Notary signing.\n * \u003e Will revert if any of these is true:\n * \u003e - Called by anyone other than local `AgentManager`.\n * \u003e - Snapshot payload is not properly formatted.\n * \u003e - Snapshot contains a state older then the Guard has previously submitted.\n * @param guardIndex Index of Guard in Agent Merkle Tree\n * @param sigIndex Index of stored Agent signature\n * @param snapPayload Raw payload with snapshot data\n */\n function acceptGuardSnapshot(uint32 guardIndex, uint256 sigIndex, bytes memory snapPayload) external;\n\n /**\n * @notice Accepts a snapshot, which local `AgentManager` verified to have been signed by an active Notary.\n * \u003e Snapshot is a list of states for a set of Origin contracts residing on any of the chains.\n * Snapshot Merkle Root is calculated and saved for valid snapshots, i.e.\n * snapshots which are only using states previously submitted by any of the Guards.\n * - Notary could use states singed by the same of different Guards 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 - Called by anyone other than local `AgentManager`.\n * \u003e - Snapshot payload is not properly formatted.\n * \u003e - Snapshot contains a state older then the Notary has previously submitted.\n * \u003e - Snapshot contains a state that no Guard has previously submitted.\n * @param notaryIndex Index of Notary in Agent Merkle Tree\n * @param sigIndex Index of stored Agent signature\n * @param agentRoot Current root of the Agent Merkle Tree\n * @param snapPayload Raw payload with snapshot data\n * @return attPayload Raw payload with data for attestation derived from Notary snapshot.\n */\n function acceptNotarySnapshot(uint32 notaryIndex, uint256 sigIndex, bytes32 agentRoot, bytes memory snapPayload)\n external\n returns (bytes memory attPayload);\n\n // ════════════════════════════════════════════════ TIPS LOGIC ═════════════════════════════════════════════════════\n\n /**\n * @notice Distributes tips using the first Receipt from the \"receipt quarantine queue\".\n * Possible scenarios:\n * - Receipt queue is empty =\u003e does nothing\n * - Receipt optimistic period is not over =\u003e does nothing\n * - Either of Notaries present in Receipt was slashed =\u003e receipt is deleted from the queue\n * - Either of Notaries present in Receipt in Dispute =\u003e receipt is moved to the end of queue\n * - None of the above =\u003e receipt tips are distributed\n * @dev Returned value makes it possible to do the following: `while (distributeTips()) {}`\n * @return queuePopped Whether the first element was popped from the queue\n */\n function distributeTips() external returns (bool queuePopped);\n\n /**\n * @notice Withdraws locked base message tips from requested domain Origin to the recipient.\n * This is done by a call to a local Origin contract, or by a manager message to the remote chain.\n * @dev This will revert, if the pending balance of origin tips (earned-claimed) is lower than requested.\n * @param origin Domain of chain to withdraw tips on\n * @param amount Amount of tips to withdraw\n */\n function withdrawTips(uint32 origin, uint256 amount) external;\n\n // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════\n\n /**\n * @notice Returns earned and claimed tips for the actor.\n * Note: Tips for address(0) belong to the Treasury.\n * @param actor Address of the actor\n * @param origin Domain where the tips were initially paid\n * @return earned Total amount of origin tips the actor has earned so far\n * @return claimed Total amount of origin tips the actor has claimed so far\n */\n function actorTips(address actor, uint32 origin) external view returns (uint128 earned, uint128 claimed);\n\n /**\n * @notice Returns the amount of receipts in the \"Receipt Quarantine Queue\".\n */\n function receiptQueueLength() external view returns (uint256);\n\n /**\n * @notice Returns the state with the highest known nonce\n * submitted by any of the currently active Guards.\n * @param origin Domain of origin chain\n * @return statePayload Raw payload with latest active Guard state for origin\n */\n function getLatestState(uint32 origin) external view returns (bytes memory statePayload);\n}\n\n// node_modules/@openzeppelin/contracts/utils/Strings.sol\n\n// OpenZeppelin Contracts (last updated v4.9.0) (utils/Strings.sol)\n\n/**\n * @dev String operations.\n */\nlibrary Strings {\n bytes16 private constant _SYMBOLS = \"0123456789abcdef\";\n uint8 private constant _ADDRESS_LENGTH = 20;\n\n /**\n * @dev Converts a `uint256` to its ASCII `string` decimal representation.\n */\n function toString(uint256 value) internal pure returns (string memory) {\n unchecked {\n uint256 length = Math.log10(value) + 1;\n string memory buffer = new string(length);\n uint256 ptr;\n /// @solidity memory-safe-assembly\n assembly {\n ptr := add(buffer, add(32, length))\n }\n while (true) {\n ptr--;\n /// @solidity memory-safe-assembly\n assembly {\n mstore8(ptr, byte(mod(value, 10), _SYMBOLS))\n }\n value /= 10;\n if (value == 0) break;\n }\n return buffer;\n }\n }\n\n /**\n * @dev Converts a `int256` to its ASCII `string` decimal representation.\n */\n function toString(int256 value) internal pure returns (string memory) {\n return string(abi.encodePacked(value \u003c 0 ? \"-\" : \"\", toString(SignedMath.abs(value))));\n }\n\n /**\n * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation.\n */\n function toHexString(uint256 value) internal pure returns (string memory) {\n unchecked {\n return toHexString(value, Math.log256(value) + 1);\n }\n }\n\n /**\n * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length.\n */\n function toHexString(uint256 value, uint256 length) internal pure returns (string memory) {\n bytes memory buffer = new bytes(2 * length + 2);\n buffer[0] = \"0\";\n buffer[1] = \"x\";\n for (uint256 i = 2 * length + 1; i \u003e 1; --i) {\n buffer[i] = _SYMBOLS[value \u0026 0xf];\n value \u003e\u003e= 4;\n }\n require(value == 0, \"Strings: hex length insufficient\");\n return string(buffer);\n }\n\n /**\n * @dev Converts an `address` with fixed length of 20 bytes to its not checksummed ASCII `string` hexadecimal representation.\n */\n function toHexString(address addr) internal pure returns (string memory) {\n return toHexString(uint256(uint160(addr)), _ADDRESS_LENGTH);\n }\n\n /**\n * @dev Returns true if the two strings are equal.\n */\n function equal(string memory a, string memory b) internal pure returns (bool) {\n return keccak256(bytes(a)) == keccak256(bytes(b));\n }\n}\n\n// node_modules/@openzeppelin/contracts-upgradeable/utils/ContextUpgradeable.sol\n\n// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)\n\n/**\n * @dev Provides information about the current execution context, including the\n * sender of the transaction and its data. While these are generally available\n * via msg.sender and msg.data, they should not be accessed in such a direct\n * manner, since when dealing with meta-transactions the account sending and\n * paying for execution may not be the actual sender (as far as an application\n * is concerned).\n *\n * This contract is only required for intermediate, library-like contracts.\n */\nabstract contract ContextUpgradeable is Initializable {\n function __Context_init() internal onlyInitializing {\n }\n\n function __Context_init_unchained() internal onlyInitializing {\n }\n function _msgSender() internal view virtual returns (address) {\n return msg.sender;\n }\n\n function _msgData() internal view virtual returns (bytes calldata) {\n return msg.data;\n }\n\n /**\n * @dev This empty reserved space is put in place to allow future versions to add new\n * variables without shifting down storage in the inheritance chain.\n * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\n */\n uint256[50] private __gap;\n}\n\n// contracts/libs/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/utils/cryptography/ECDSA.sol\n\n// OpenZeppelin Contracts (last updated v4.9.0) (utils/cryptography/ECDSA.sol)\n\n/**\n * @dev Elliptic Curve Digital Signature Algorithm (ECDSA) operations.\n *\n * These functions can be used to verify that a message was signed by the holder\n * of the private keys of a given address.\n */\nlibrary ECDSA {\n enum RecoverError {\n NoError,\n InvalidSignature,\n InvalidSignatureLength,\n InvalidSignatureS,\n InvalidSignatureV // Deprecated in v4.8\n }\n\n function _throwError(RecoverError error) private pure {\n if (error == RecoverError.NoError) {\n return; // no error: do nothing\n } else if (error == RecoverError.InvalidSignature) {\n revert(\"ECDSA: invalid signature\");\n } else if (error == RecoverError.InvalidSignatureLength) {\n revert(\"ECDSA: invalid signature length\");\n } else if (error == RecoverError.InvalidSignatureS) {\n revert(\"ECDSA: invalid signature 's' value\");\n }\n }\n\n /**\n * @dev Returns the address that signed a hashed message (`hash`) with\n * `signature` or error string. This address can then be used for verification purposes.\n *\n * The `ecrecover` EVM opcode allows for malleable (non-unique) signatures:\n * this function rejects them by requiring the `s` value to be in the lower\n * half order, and the `v` value to be either 27 or 28.\n *\n * IMPORTANT: `hash` _must_ be the result of a hash operation for the\n * verification to be secure: it is possible to craft signatures that\n * recover to arbitrary addresses for non-hashed data. A safe way to ensure\n * this is by receiving a hash of the original message (which may otherwise\n * be too long), and then calling {toEthSignedMessageHash} on it.\n *\n * Documentation for signature generation:\n * - with https://web3js.readthedocs.io/en/v1.3.4/web3-eth-accounts.html#sign[Web3.js]\n * - with https://docs.ethers.io/v5/api/signer/#Signer-signMessage[ethers]\n *\n * _Available since v4.3._\n */\n function tryRecover(bytes32 hash, bytes memory signature) internal pure returns (address, RecoverError) {\n if (signature.length == 65) {\n bytes32 r;\n bytes32 s;\n uint8 v;\n // ecrecover takes the signature parameters, and the only way to get them\n // currently is to use assembly.\n /// @solidity memory-safe-assembly\n assembly {\n r := mload(add(signature, 0x20))\n s := mload(add(signature, 0x40))\n v := byte(0, mload(add(signature, 0x60)))\n }\n return tryRecover(hash, v, r, s);\n } else {\n return (address(0), RecoverError.InvalidSignatureLength);\n }\n }\n\n /**\n * @dev Returns the address that signed a hashed message (`hash`) with\n * `signature`. This address can then be used for verification purposes.\n *\n * The `ecrecover` EVM opcode allows for malleable (non-unique) signatures:\n * this function rejects them by requiring the `s` value to be in the lower\n * half order, and the `v` value to be either 27 or 28.\n *\n * IMPORTANT: `hash` _must_ be the result of a hash operation for the\n * verification to be secure: it is possible to craft signatures that\n * recover to arbitrary addresses for non-hashed data. A safe way to ensure\n * this is by receiving a hash of the original message (which may otherwise\n * be too long), and then calling {toEthSignedMessageHash} on it.\n */\n function recover(bytes32 hash, bytes memory signature) internal pure returns (address) {\n (address recovered, RecoverError error) = tryRecover(hash, signature);\n _throwError(error);\n return recovered;\n }\n\n /**\n * @dev Overload of {ECDSA-tryRecover} that receives the `r` and `vs` short-signature fields separately.\n *\n * See https://eips.ethereum.org/EIPS/eip-2098[EIP-2098 short signatures]\n *\n * _Available since v4.3._\n */\n function tryRecover(bytes32 hash, bytes32 r, bytes32 vs) internal pure returns (address, RecoverError) {\n bytes32 s = vs \u0026 bytes32(0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff);\n uint8 v = uint8((uint256(vs) \u003e\u003e 255) + 27);\n return tryRecover(hash, v, r, s);\n }\n\n /**\n * @dev Overload of {ECDSA-recover} that receives the `r and `vs` short-signature fields separately.\n *\n * _Available since v4.2._\n */\n function recover(bytes32 hash, bytes32 r, bytes32 vs) internal pure returns (address) {\n (address recovered, RecoverError error) = tryRecover(hash, r, vs);\n _throwError(error);\n return recovered;\n }\n\n /**\n * @dev Overload of {ECDSA-tryRecover} that receives the `v`,\n * `r` and `s` signature fields separately.\n *\n * _Available since v4.3._\n */\n function tryRecover(bytes32 hash, uint8 v, bytes32 r, bytes32 s) internal pure returns (address, RecoverError) {\n // EIP-2 still allows signature malleability for ecrecover(). Remove this possibility and make the signature\n // unique. Appendix F in the Ethereum Yellow paper (https://ethereum.github.io/yellowpaper/paper.pdf), defines\n // the valid range for s in (301): 0 \u003c s \u003c secp256k1n ÷ 2 + 1, and for v in (302): v ∈ {27, 28}. Most\n // signatures from current libraries generate a unique signature with an s-value in the lower half order.\n //\n // If your library generates malleable signatures, such as s-values in the upper range, calculate a new s-value\n // with 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141 - s1 and flip v from 27 to 28 or\n // vice versa. If your library also generates signatures with 0/1 for v instead 27/28, add 27 to v to accept\n // these malleable signatures as well.\n if (uint256(s) \u003e 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0) {\n return (address(0), RecoverError.InvalidSignatureS);\n }\n\n // If the signature is valid (and not malleable), return the signer address\n address signer = ecrecover(hash, v, r, s);\n if (signer == address(0)) {\n return (address(0), RecoverError.InvalidSignature);\n }\n\n return (signer, RecoverError.NoError);\n }\n\n /**\n * @dev Overload of {ECDSA-recover} that receives the `v`,\n * `r` and `s` signature fields separately.\n */\n function recover(bytes32 hash, uint8 v, bytes32 r, bytes32 s) internal pure returns (address) {\n (address recovered, RecoverError error) = tryRecover(hash, v, r, s);\n _throwError(error);\n return recovered;\n }\n\n /**\n * @dev Returns an Ethereum Signed Message, created from a `hash`. This\n * produces hash corresponding to the one signed with the\n * https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`]\n * JSON-RPC method as part of EIP-191.\n *\n * See {recover}.\n */\n function toEthSignedMessageHash(bytes32 hash) internal pure returns (bytes32 message) {\n // 32 is the length in bytes of hash,\n // enforced by the type signature above\n /// @solidity memory-safe-assembly\n assembly {\n mstore(0x00, \"\\x19Ethereum Signed Message:\\n32\")\n mstore(0x1c, hash)\n message := keccak256(0x00, 0x3c)\n }\n }\n\n /**\n * @dev Returns an Ethereum Signed Message, created from `s`. This\n * produces hash corresponding to the one signed with the\n * https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`]\n * JSON-RPC method as part of EIP-191.\n *\n * See {recover}.\n */\n function toEthSignedMessageHash(bytes memory s) internal pure returns (bytes32) {\n return keccak256(abi.encodePacked(\"\\x19Ethereum Signed Message:\\n\", Strings.toString(s.length), s));\n }\n\n /**\n * @dev Returns an Ethereum Signed Typed Data, created from a\n * `domainSeparator` and a `structHash`. This produces hash corresponding\n * to the one signed with the\n * https://eips.ethereum.org/EIPS/eip-712[`eth_signTypedData`]\n * JSON-RPC method as part of EIP-712.\n *\n * See {recover}.\n */\n function toTypedDataHash(bytes32 domainSeparator, bytes32 structHash) internal pure returns (bytes32 data) {\n /// @solidity memory-safe-assembly\n assembly {\n let ptr := mload(0x40)\n mstore(ptr, \"\\x19\\x01\")\n mstore(add(ptr, 0x02), domainSeparator)\n mstore(add(ptr, 0x22), structHash)\n data := keccak256(ptr, 0x42)\n }\n }\n\n /**\n * @dev Returns an Ethereum Signed Data with intended validator, created from a\n * `validator` and `data` according to the version 0 of EIP-191.\n *\n * See {recover}.\n */\n function toDataWithIntendedValidatorHash(address validator, bytes memory data) internal pure returns (bytes32) {\n return keccak256(abi.encodePacked(\"\\x19\\x00\", validator, data));\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/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/inbox/StatementInbox.sol\n\n// ══════════════════════════════ LIBRARY IMPORTS ══════════════════════════════\n\n// ═════════════════════════════ INTERNAL IMPORTS ══════════════════════════════\n\n// ═════════════════════════════ EXTERNAL IMPORTS ══════════════════════════════\n\n/// @notice `StatementInbox` is the entry point for all agent-signed statements. It verifies the\n/// agent signatures, and passes the unsigned statements to the contract to consume it via `acceptX` functions. Is is\n/// also used to verify the agent-signed statements and initiate the agent slashing, should the statement be invalid.\n/// `StatementInbox` is responsible for the following:\n/// - Accepting State and Receipt Reports to initiate a dispute between Guard and Notary.\n/// - Storing all the Guard Reports with the Guard signature leading to a dispute.\n/// - Verifying State/State Reports referencing the local chain and slashing the signer if statement is invalid.\n/// - Verifying Receipt/Receipt Reports referencing the local chain and slashing the signer if statement is invalid.\nabstract contract StatementInbox is MessagingBase, StatementInboxEvents, IStatementInbox {\n using AttestationLib for bytes;\n using ReceiptLib for bytes;\n using StateLib for bytes;\n using SnapshotLib for bytes;\n\n struct StoredReport {\n uint256 sigIndex;\n bytes statementPayload;\n }\n\n // ══════════════════════════════════════════════════ STORAGE ══════════════════════════════════════════════════════\n\n address public agentManager;\n address public origin;\n address public destination;\n\n // TODO: optimize this\n bytes[] internal _storedSignatures;\n StoredReport[] internal _storedReports;\n\n /// @dev gap for upgrade safety\n uint256[45] private __GAP; // solhint-disable-line var-name-mixedcase\n\n // ════════════════════════════════════════════════ INITIALIZER ════════════════════════════════════════════════════\n\n /// @dev Initializes the contract:\n /// - Sets up `msg.sender` as the owner of the contract.\n /// - Sets up `agentManager`, `origin`, and `destination`.\n // solhint-disable-next-line func-name-mixedcase\n function __StatementInbox_init(address agentManager_, address origin_, address destination_)\n internal\n onlyInitializing\n {\n agentManager = agentManager_;\n origin = origin_;\n destination = destination_;\n __Ownable2Step_init();\n }\n\n // ══════════════════════════════════════════ SUBMIT AGENT STATEMENTS ══════════════════════════════════════════════\n\n /// @inheritdoc IStatementInbox\n // solhint-disable-next-line ordering\n function submitStateReportWithSnapshot(\n uint8 stateIndex,\n bytes memory srSignature,\n bytes memory snapPayload,\n bytes memory snapSignature\n ) external returns (bool wasAccepted) {\n // This will revert if payload is not a snapshot\n Snapshot snapshot = snapPayload.castToSnapshot();\n // This will revert if the snapshot signer is not a known Notary\n (AgentStatus memory notaryStatus,) =\n _verifySnapshot({snapshot: snapshot, snapSignature: snapSignature, verifyNotary: true});\n // Notary needs to be Active/Unstaking\n notaryStatus.verifyActiveUnstaking();\n // Check if Notary is active on this chain\n _verifyNotaryDomain(notaryStatus.domain);\n // This will revert if state index is out of range\n State state = snapshot.state(stateIndex);\n // This will revert if the report signer is not an known Guard\n (AgentStatus memory guardStatus,) = _verifyStateReport(state, srSignature);\n // Check that Guard is active\n guardStatus.verifyActive();\n _saveReport(state.unwrap().clone(), srSignature);\n // This will revert if either actor is already in dispute\n IAgentManager(agentManager).openDispute(guardStatus.index, notaryStatus.index);\n return true;\n }\n\n /// @inheritdoc IStatementInbox\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 // This will revert if payload is not a snapshot\n Snapshot snapshot = snapPayload.castToSnapshot();\n // This will revert if state index is out of range\n State state = snapshot.state(stateIndex);\n // This will revert if the report signer is not an known Guard\n (AgentStatus memory guardStatus,) = _verifyStateReport(state, srSignature);\n // Check that Guard is active\n guardStatus.verifyActive();\n // This will revert if payload is not an attestation\n Attestation att = attPayload.castToAttestation();\n // This will revert if signer is not an known Notary\n (AgentStatus memory notaryStatus,) = _verifyAttestation(att, attSignature);\n // Notary needs to be Active/Unstaking\n notaryStatus.verifyActiveUnstaking();\n // Check if Notary is active on this chain\n _verifyNotaryDomain(notaryStatus.domain);\n if (snapshot.calculateRoot() != att.snapRoot()) revert IncorrectSnapshotRoot();\n _saveReport(state.unwrap().clone(), srSignature);\n // This will revert if either actor is already in dispute\n IAgentManager(agentManager).openDispute(guardStatus.index, notaryStatus.index);\n return true;\n }\n\n /// @inheritdoc IStatementInbox\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 // This will revert if payload is not a state\n State state = statePayload.castToState();\n // This will revert if the report signer is not an known Guard\n (AgentStatus memory guardStatus,) = _verifyStateReport(state, srSignature);\n // Check that Guard is active\n guardStatus.verifyActive();\n // This will revert if payload is not an attestation\n Attestation att = attPayload.castToAttestation();\n // This will revert if signer is not a known Notary\n (AgentStatus memory notaryStatus,) = _verifyAttestation(att, attSignature);\n // Notary needs to be Active/Unstaking\n notaryStatus.verifyActiveUnstaking();\n // Check if Notary is active on this chain\n _verifyNotaryDomain(notaryStatus.domain);\n // This will revert if any of these is true:\n // - Attestation root is not equal to Merkle Root derived from State and Snapshot Proof.\n // - Snapshot Proof's first element does not match the State metadata.\n // - Snapshot Proof length exceeds Snapshot tree Height.\n // - State index is out of range.\n _verifySnapshotMerkle(att, stateIndex, state, snapProof);\n _saveReport(statePayload, srSignature);\n // This will revert if either actor is already in dispute\n IAgentManager(agentManager).openDispute(guardStatus.index, notaryStatus.index);\n return true;\n }\n\n // ══════════════════════════════════════════ VERIFY AGENT STATEMENTS ══════════════════════════════════════════════\n\n /// @inheritdoc IStatementInbox\n function verifyReceipt(bytes memory rcptPayload, bytes memory rcptSignature)\n external\n returns (bool isValidReceipt)\n {\n // This will revert if payload is not a receipt\n Receipt rcpt = rcptPayload.castToReceipt();\n // This will revert if the attestation signer is not a known Notary\n (AgentStatus memory status, address notary) = _verifyReceipt(rcpt, rcptSignature);\n // Notary needs to be Active/Unstaking\n status.verifyActiveUnstaking();\n isValidReceipt = IExecutionHub(destination).isValidReceipt(rcptPayload);\n if (!isValidReceipt) {\n emit InvalidReceipt(rcptPayload, rcptSignature);\n IAgentManager(agentManager).slashAgent(status.domain, notary, msg.sender);\n }\n }\n\n /// @inheritdoc IStatementInbox\n function verifyReceiptReport(bytes memory rcptPayload, bytes memory rrSignature)\n external\n returns (bool isValidReport)\n {\n // This will revert if payload is not a receipt\n Receipt rcpt = rcptPayload.castToReceipt();\n // This will revert if the report signer is not a known Guard\n (AgentStatus memory status, address guard) = _verifyReceiptReport(rcpt, rrSignature);\n // Guard needs to be Active/Unstaking\n status.verifyActiveUnstaking();\n // Report is valid IF AND ONLY IF the reported receipt in invalid\n isValidReport = !IExecutionHub(destination).isValidReceipt(rcptPayload);\n if (!isValidReport) {\n emit InvalidReceiptReport(rcptPayload, rrSignature);\n IAgentManager(agentManager).slashAgent(status.domain, guard, msg.sender);\n }\n }\n\n /// @inheritdoc IStatementInbox\n function verifyStateWithAttestation(\n uint8 stateIndex,\n bytes memory snapPayload,\n bytes memory attPayload,\n bytes memory attSignature\n ) external returns (bool isValidState) {\n // This will revert if payload is not an attestation\n Attestation att = attPayload.castToAttestation();\n // This will revert if the attestation signer is not a known Notary\n (AgentStatus memory status, address notary) = _verifyAttestation(att, attSignature);\n // Notary needs to be Active/Unstaking\n status.verifyActiveUnstaking();\n // This will revert if payload is not a snapshot\n Snapshot snapshot = snapPayload.castToSnapshot();\n if (snapshot.calculateRoot() != att.snapRoot()) revert IncorrectSnapshotRoot();\n // This will revert if state does not refer to this chain\n bytes memory statePayload = snapshot.state(stateIndex).unwrap().clone();\n isValidState = IStateHub(origin).isValidState(statePayload);\n if (!isValidState) {\n emit InvalidStateWithAttestation(stateIndex, statePayload, attPayload, attSignature);\n IAgentManager(agentManager).slashAgent(status.domain, notary, msg.sender);\n }\n }\n\n /// @inheritdoc IStatementInbox\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 // This will revert if payload is not an attestation\n Attestation att = attPayload.castToAttestation();\n // This will revert if the attestation signer is not a known Notary\n (AgentStatus memory status, address notary) = _verifyAttestation(att, attSignature);\n // Notary needs to be Active/Unstaking\n status.verifyActiveUnstaking();\n // This will revert if payload is not a state\n State state = statePayload.castToState();\n // This will revert if any of these is true:\n // - Attestation root is not equal to Merkle Root derived from State and Snapshot Proof.\n // - Snapshot Proof's first element does not match the State metadata.\n // - Snapshot Proof length exceeds Snapshot tree Height.\n // - State index is out of range.\n _verifySnapshotMerkle(att, stateIndex, state, snapProof);\n // This will revert if state does not refer to this chain\n isValidState = IStateHub(origin).isValidState(statePayload);\n if (!isValidState) {\n emit InvalidStateWithAttestation(stateIndex, statePayload, attPayload, attSignature);\n IAgentManager(agentManager).slashAgent(status.domain, notary, msg.sender);\n }\n }\n\n /// @inheritdoc IStatementInbox\n function verifyStateWithSnapshot(uint8 stateIndex, bytes memory snapPayload, bytes memory snapSignature)\n external\n returns (bool isValidState)\n {\n // This will revert if payload is not a snapshot\n Snapshot snapshot = snapPayload.castToSnapshot();\n // This will revert if the snapshot signer is not a known Guard/Notary\n (AgentStatus memory status, address agent) =\n _verifySnapshot({snapshot: snapshot, snapSignature: snapSignature, verifyNotary: false});\n // Agent needs to be Active/Unstaking\n status.verifyActiveUnstaking();\n // This will revert if state does not refer to this chain\n isValidState = IStateHub(origin).isValidState(snapshot.state(stateIndex).unwrap().clone());\n if (!isValidState) {\n emit InvalidStateWithSnapshot(stateIndex, snapPayload, snapSignature);\n IAgentManager(agentManager).slashAgent(status.domain, agent, msg.sender);\n }\n }\n\n /// @inheritdoc IStatementInbox\n function verifyStateReport(bytes memory statePayload, bytes memory srSignature)\n external\n returns (bool isValidReport)\n {\n // This will revert if payload is not a state\n State state = statePayload.castToState();\n // This will revert if the report signer is not a known Guard\n (AgentStatus memory status, address guard) = _verifyStateReport(state, srSignature);\n // Guard needs to be Active/Unstaking\n status.verifyActiveUnstaking();\n // Report is valid IF AND ONLY IF the reported state in invalid\n // This will revert if the reported state does not refer to this chain\n isValidReport = !IStateHub(origin).isValidState(statePayload);\n if (!isValidReport) {\n emit InvalidStateReport(statePayload, srSignature);\n IAgentManager(agentManager).slashAgent(status.domain, guard, msg.sender);\n }\n }\n\n // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════\n\n /// @inheritdoc IStatementInbox\n function getReportsAmount() external view returns (uint256) {\n return _storedReports.length;\n }\n\n /// @inheritdoc IStatementInbox\n function getGuardReport(uint256 index)\n external\n view\n returns (bytes memory statementPayload, bytes memory reportSignature)\n {\n if (index \u003e= _storedReports.length) revert IndexOutOfRange();\n StoredReport memory storedReport = _storedReports[index];\n statementPayload = storedReport.statementPayload;\n reportSignature = _storedSignatures[storedReport.sigIndex];\n }\n\n /// @inheritdoc IStatementInbox\n function getStoredSignature(uint256 index) external view returns (bytes memory) {\n return _storedSignatures[index];\n }\n\n // ══════════════════════════════════════════════ INTERNAL LOGIC ═══════════════════════════════════════════════════\n\n /// @dev Saves the statement reported by Guard as invalid and the Guard Report signature.\n function _saveReport(bytes memory statementPayload, bytes memory reportSignature) internal {\n uint256 sigIndex = _saveSignature(reportSignature);\n _storedReports.push(StoredReport(sigIndex, statementPayload));\n }\n\n /// @dev Saves the signature and returns its index.\n function _saveSignature(bytes memory signature) internal returns (uint256 sigIndex) {\n sigIndex = _storedSignatures.length;\n _storedSignatures.push(signature);\n }\n\n // ═══════════════════════════════════════════════ AGENT CHECKS ════════════════════════════════════════════════════\n\n /**\n * @dev Recovers a signer from a hashed message, and a EIP-191 signature for it.\n * Will revert, if the signer is not a known agent.\n * @dev Agent flag could be any of these: Active/Unstaking/Resting/Fraudulent/Slashed\n * Further checks need to be performed in a caller function.\n * @param hashedStatement Hash of the statement that was signed by an Agent\n * @param signature Agent signature for the hashed statement\n * @return status Struct representing agent status:\n * - flag Unknown/Active/Unstaking/Resting/Fraudulent/Slashed\n * - domain Domain where agent is/was active\n * - index Index of agent in the Agent Merkle Tree\n * @return agent Agent that signed the statement\n */\n function _recoverAgent(bytes32 hashedStatement, bytes memory signature)\n internal\n view\n returns (AgentStatus memory status, address agent)\n {\n bytes32 ethSignedMsg = ECDSA.toEthSignedMessageHash(hashedStatement);\n agent = ECDSA.recover(ethSignedMsg, signature);\n status = IAgentManager(agentManager).agentStatus(agent);\n // Discard signature of unknown agents.\n // Further flag checks are supposed to be performed in a caller function.\n status.verifyKnown();\n }\n\n /// @dev Verifies that Notary signature is active on local domain.\n function _verifyNotaryDomain(uint32 notaryDomain) internal view {\n // Notary needs to be from the local domain (if contract is not deployed on Synapse Chain).\n // Or Notary could be from any domain (if contract is deployed on Synapse Chain).\n if (notaryDomain != localDomain \u0026\u0026 localDomain != synapseDomain) revert IncorrectAgentDomain();\n }\n\n // ════════════════════════════════════════ ATTESTATION RELATED CHECKS ═════════════════════════════════════════════\n\n /**\n * @dev Internal function to verify the signed attestation payload.\n * Reverts if any of these is true:\n * - Attestation signer is not a known Notary.\n * @param att Typed memory view over attestation payload\n * @param attSignature Notary signature for the attestation\n * @return status Struct representing agent status, see {_recoverAgent}\n * @return notary Notary that signed the snapshot\n */\n function _verifyAttestation(Attestation att, bytes memory attSignature)\n internal\n view\n returns (AgentStatus memory status, address notary)\n {\n // This will revert if signer is not a known agent\n (status, notary) = _recoverAgent(att.hashValid(), attSignature);\n // Attestation signer needs to be a Notary, not a Guard\n if (status.domain == 0) revert AgentNotNotary();\n }\n\n /**\n * @dev Internal function to verify the signed attestation report payload.\n * Reverts if any of these is true:\n * - Report signer is not a known Guard.\n * @param att Typed memory view over attestation payload that Guard reports as invalid\n * @param arSignature Guard signature for the \"invalid attestation\" report\n * @return status Struct representing guard status, see {_recoverAgent}\n * @return guard Guard that signed the report\n */\n function _verifyAttestationReport(Attestation att, bytes memory arSignature)\n internal\n view\n returns (AgentStatus memory status, address guard)\n {\n // This will revert if signer is not a known agent\n (status, guard) = _recoverAgent(att.hashInvalid(), arSignature);\n // Report signer needs to be a Guard, not a Notary\n if (status.domain != 0) revert AgentNotGuard();\n }\n\n // ══════════════════════════════════════════ RECEIPT RELATED CHECKS ═══════════════════════════════════════════════\n\n /**\n * @dev Internal function to verify the signed receipt payload.\n * Reverts if any of these is true:\n * - Receipt signer is not a known Notary.\n * @param rcpt Typed memory view over receipt payload\n * @param rcptSignature Notary signature for the receipt\n * @return status Struct representing agent status, see {_recoverAgent}\n * @return notary Notary that signed the snapshot\n */\n function _verifyReceipt(Receipt rcpt, bytes memory rcptSignature)\n internal\n view\n returns (AgentStatus memory status, address notary)\n {\n // This will revert if signer is not a known agent\n (status, notary) = _recoverAgent(rcpt.hashValid(), rcptSignature);\n // Receipt signer needs to be a Notary, not a Guard\n if (status.domain == 0) revert AgentNotNotary();\n }\n\n /**\n * @dev Internal function to verify the signed receipt report payload.\n * Reverts if any of these is true:\n * - Report signer is not a known Guard.\n * @param rcpt Typed memory view over receipt payload that Guard reports as invalid\n * @param rrSignature Guard signature for the \"invalid receipt\" report\n * @return status Struct representing guard status, see {_recoverAgent}\n * @return guard Guard that signed the report\n */\n function _verifyReceiptReport(Receipt rcpt, bytes memory rrSignature)\n internal\n view\n returns (AgentStatus memory status, address guard)\n {\n // This will revert if signer is not a known agent\n (status, guard) = _recoverAgent(rcpt.hashInvalid(), rrSignature);\n // Report signer needs to be a Guard, not a Notary\n if (status.domain != 0) revert AgentNotGuard();\n }\n\n // ═══════════════════════════════════════ STATE/SNAPSHOT RELATED CHECKS ═══════════════════════════════════════════\n\n /**\n * @dev Internal function to verify the signed snapshot report payload.\n * Reverts if any of these is true:\n * - Report signer is not a known Guard.\n * @param state Typed memory view over state payload that Guard reports as invalid\n * @param srSignature Guard signature for the report\n * @return status Struct representing guard status, see {_recoverAgent}\n * @return guard Guard that signed the report\n */\n function _verifyStateReport(State state, bytes memory srSignature)\n internal\n view\n returns (AgentStatus memory status, address guard)\n {\n // This will revert if signer is not a known agent\n (status, guard) = _recoverAgent(state.hashInvalid(), srSignature);\n // Report signer needs to be a Guard, not a Notary\n if (status.domain != 0) revert AgentNotGuard();\n }\n\n /**\n * @dev Internal function to verify the signed snapshot payload.\n * Reverts if any of these is true:\n * - Snapshot signer is not a known Agent.\n * - Snapshot signer is not a Notary (if verifyNotary is true).\n * @param snapshot Typed memory view over snapshot payload\n * @param snapSignature Agent signature for the snapshot\n * @param verifyNotary If true, snapshot signer needs to be a Notary, not a Guard\n * @return status Struct representing agent status, see {_recoverAgent}\n * @return agent Agent that signed the snapshot\n */\n function _verifySnapshot(Snapshot snapshot, bytes memory snapSignature, bool verifyNotary)\n internal\n view\n returns (AgentStatus memory status, address agent)\n {\n // This will revert if signer is not a known agent\n (status, agent) = _recoverAgent(snapshot.hashValid(), snapSignature);\n // If requested, snapshot signer needs to be a Notary, not a Guard\n if (verifyNotary \u0026\u0026 status.domain == 0) revert AgentNotNotary();\n }\n\n // ═══════════════════════════════════════════ MERKLE RELATED CHECKS ═══════════════════════════════════════════════\n\n /**\n * @dev Internal function to verify that snapshot roots match.\n * Reverts if any of these is true:\n * - Attestation root is not equal to Merkle Root derived from State and Snapshot Proof.\n * - Snapshot Proof's first element does not match the State metadata.\n * - Snapshot Proof length exceeds Snapshot tree Height.\n * - State index is out of range.\n * @param att Typed memory view over Attestation\n * @param stateIndex Index of state in the snapshot\n * @param state Typed memory view over the provided state payload\n * @param snapProof Raw payload with snapshot data\n */\n function _verifySnapshotMerkle(Attestation att, uint8 stateIndex, State state, bytes32[] memory snapProof)\n internal\n pure\n {\n // Snapshot proof first element should match State metadata (aka \"right sub-leaf\")\n (, bytes32 rightSubLeaf) = state.subLeafs();\n if (snapProof[0] != rightSubLeaf) revert IncorrectSnapshotProof();\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(state.root(), state.origin(), snapProof, stateIndex);\n // Snapshot root should match the attestation root\n if (att.snapRoot() != snapshotRoot) revert IncorrectSnapshotRoot();\n }\n}\n\n// contracts/inbox/Inbox.sol\n\n// ══════════════════════════════ LIBRARY IMPORTS ══════════════════════════════\n\n// ═════════════════════════════ INTERNAL IMPORTS ══════════════════════════════\n\n/// @notice `Inbox` is the child of `StatementInbox` contract, that is used on Synapse Chain.\n/// In addition to the functionality of `StatementInbox`, it also:\n/// - Accepts Guard and Notary Snapshots and passes them to `Summit` contract.\n/// - Accepts Notary-signed Receipts and passes them to `Summit` contract.\n/// - Accepts Receipt Reports to initiate a dispute between Guard and Notary.\n/// - Verifies Attestations and Attestation Reports, and slashes the signer if they are invalid.\ncontract Inbox is StatementInbox, InboxEvents, InterfaceInbox {\n using AttestationLib for bytes;\n using ReceiptLib for bytes;\n using SnapshotLib for bytes;\n\n // Struct to get around stack too deep error. TODO: revisit this\n struct ReceiptInfo {\n AgentStatus rcptNotaryStatus;\n address notary;\n uint32 attNonce;\n AgentStatus attNotaryStatus;\n }\n\n // ══════════════════════════════════════════════════ STORAGE ══════════════════════════════════════════════════════\n\n // The address of the Summit contract.\n address public summit;\n\n // ═════════════════════════════════════════ CONSTRUCTOR \u0026 INITIALIZER ═════════════════════════════════════════════\n\n constructor(uint32 synapseDomain_) MessagingBase(\"0.0.3\", synapseDomain_) {\n if (localDomain != synapseDomain) revert MustBeSynapseDomain();\n }\n\n /// @notice Initializes `Inbox` contract:\n /// - Sets `msg.sender` as the owner of the contract\n /// - Sets `agentManager`, `origin`, `destination` and `summit` addresses\n function initialize(address agentManager_, address origin_, address destination_, address summit_)\n external\n initializer\n {\n __StatementInbox_init(agentManager_, origin_, destination_);\n summit = summit_;\n }\n\n // ══════════════════════════════════════════ SUBMIT AGENT STATEMENTS ══════════════════════════════════════════════\n\n /// @inheritdoc InterfaceInbox\n function submitSnapshot(bytes memory snapPayload, bytes memory snapSignature)\n external\n returns (bytes memory attPayload, bytes32 agentRoot_, uint256[] memory snapGas)\n {\n // This will revert if payload is not a snapshot\n Snapshot snapshot = snapPayload.castToSnapshot();\n // This will revert if the signer is not a known Guard/Notary\n (AgentStatus memory status, address agent) =\n _verifySnapshot({snapshot: snapshot, snapSignature: snapSignature, verifyNotary: false});\n // Check that Agent is active\n status.verifyActive();\n // Store Agent signature for the Snapshot\n uint256 sigIndex = _saveSignature(snapSignature);\n if (status.domain == 0) {\n // Guard that is in Dispute could still submit new snapshots, so we don't check that\n InterfaceSummit(summit).acceptGuardSnapshot({\n guardIndex: status.index,\n sigIndex: sigIndex,\n snapPayload: snapPayload\n });\n } else {\n // Get current agentRoot from AgentManager\n agentRoot_ = IAgentManager(agentManager).agentRoot();\n // This will revert if Notary is in Dispute\n attPayload = InterfaceSummit(summit).acceptNotarySnapshot({\n notaryIndex: status.index,\n sigIndex: sigIndex,\n agentRoot: agentRoot_,\n snapPayload: snapPayload\n });\n ChainGas[] memory snapGas_ = snapshot.snapGas();\n // Pass created attestation to Destination to enable executing messages coming to Synapse Chain\n InterfaceDestination(destination).acceptAttestation(\n status.index, type(uint256).max, attPayload, agentRoot_, snapGas_\n );\n // Use assembly to cast ChainGas[] to uint256[] without copying. Highest bits are left zeroed.\n // solhint-disable-next-line no-inline-assembly\n assembly {\n snapGas := snapGas_\n }\n }\n emit SnapshotAccepted(status.domain, agent, snapPayload, snapSignature);\n }\n\n /// @inheritdoc InterfaceInbox\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 // Struct to get around stack too deep error.\n ReceiptInfo memory info;\n // This will revert if payload is not a receipt\n Receipt rcpt = rcptPayload.castToReceipt();\n // This will revert if the receipt signer is not a known Notary\n (info.rcptNotaryStatus, info.notary) = _verifyReceipt(rcpt, rcptSignature);\n // Receipt Notary needs to be Active\n info.rcptNotaryStatus.verifyActive();\n info.attNonce = IExecutionHub(destination).getAttestationNonce(rcpt.snapshotRoot());\n if (info.attNonce == 0) revert IncorrectSnapshotRoot();\n // Attestation Notary domain needs to match the destination domain\n info.attNotaryStatus = IAgentManager(agentManager).agentStatus(rcpt.attNotary());\n if (info.attNotaryStatus.domain != rcpt.destination()) revert IncorrectAgentDomain();\n // Check that the correct tip values for the message were provided\n _verifyReceiptTips(rcpt.messageHash(), paddedTips, headerHash, bodyHash);\n // Store Notary signature for the Receipt\n uint256 sigIndex = _saveSignature(rcptSignature);\n // This will revert if Receipt Notary is in Dispute\n wasAccepted = InterfaceSummit(summit).acceptReceipt({\n rcptNotaryIndex: info.rcptNotaryStatus.index,\n attNotaryIndex: info.attNotaryStatus.index,\n sigIndex: sigIndex,\n attNonce: info.attNonce,\n paddedTips: paddedTips,\n rcptPayload: rcptPayload\n });\n if (wasAccepted) {\n emit ReceiptAccepted(info.rcptNotaryStatus.domain, info.notary, rcptPayload, rcptSignature);\n }\n }\n\n /// @inheritdoc InterfaceInbox\n function submitReceiptReport(bytes memory rcptPayload, bytes memory rcptSignature, bytes memory rrSignature)\n external\n returns (bool wasAccepted)\n {\n // This will revert if payload is not a receipt\n Receipt rcpt = rcptPayload.castToReceipt();\n // This will revert if the receipt signer is not a known Guard\n (AgentStatus memory guardStatus,) = _verifyReceiptReport(rcpt, rrSignature);\n // Guard needs to be Active\n guardStatus.verifyActive();\n // This will revert if report signer is not a known Notary\n (AgentStatus memory notaryStatus,) = _verifyReceipt(rcpt, rcptSignature);\n // Notary needs to be Active/Unstaking\n notaryStatus.verifyActiveUnstaking();\n _saveReport(rcptPayload, rrSignature);\n // This will revert if either actor is already in dispute\n IAgentManager(agentManager).openDispute(guardStatus.index, notaryStatus.index);\n return true;\n }\n\n /// @inheritdoc InterfaceInbox\n function passReceipt(uint32 attNotaryIndex, uint32 attNonce, uint256 paddedTips, bytes memory rcptPayload)\n external\n returns (bool wasAccepted)\n {\n // Only Destination can pass receipts\n if (msg.sender != destination) revert CallerNotDestination();\n return InterfaceSummit(summit).acceptReceipt({\n rcptNotaryIndex: attNotaryIndex,\n attNotaryIndex: attNotaryIndex,\n sigIndex: type(uint256).max,\n attNonce: attNonce,\n paddedTips: paddedTips,\n rcptPayload: rcptPayload\n });\n }\n\n // ══════════════════════════════════════════ VERIFY AGENT STATEMENTS ══════════════════════════════════════════════\n\n /// @inheritdoc InterfaceInbox\n function verifyAttestation(bytes memory attPayload, bytes memory attSignature)\n external\n returns (bool isValidAttestation)\n {\n // This will revert if payload is not an attestation\n Attestation att = attPayload.castToAttestation();\n // This will revert if the attestation signer is not a known Notary\n (AgentStatus memory status, address notary) = _verifyAttestation(att, attSignature);\n // Notary needs to be Active/Unstaking\n status.verifyActiveUnstaking();\n isValidAttestation = ISnapshotHub(summit).isValidAttestation(attPayload);\n if (!isValidAttestation) {\n emit InvalidAttestation(attPayload, attSignature);\n IAgentManager(agentManager).slashAgent(status.domain, notary, msg.sender);\n }\n }\n\n /// @inheritdoc InterfaceInbox\n function verifyAttestationReport(bytes memory attPayload, bytes memory arSignature)\n external\n returns (bool isValidReport)\n {\n // This will revert if payload is not an attestation\n Attestation att = attPayload.castToAttestation();\n // This will revert if the report signer is not a known Guard\n (AgentStatus memory status, address guard) = _verifyAttestationReport(att, arSignature);\n // Guard needs to be Active/Unstaking\n status.verifyActiveUnstaking();\n // Report is valid IF AND ONLY IF the reported attestation in invalid\n isValidReport = !ISnapshotHub(summit).isValidAttestation(attPayload);\n if (!isValidReport) {\n emit InvalidAttestationReport(attPayload, arSignature);\n IAgentManager(agentManager).slashAgent(status.domain, guard, msg.sender);\n }\n }\n\n // ══════════════════════════════════════════════ INTERNAL VIEWS ═══════════════════════════════════════════════════\n\n /// @dev Verifies that tips proof matches the message hash.\n function _verifyReceiptTips(bytes32 msgHash, uint256 paddedTips, bytes32 headerHash, bytes32 bodyHash)\n internal\n pure\n {\n Tips tips = TipsLib.wrapPadded(paddedTips);\n // full message leaf is (header, baseMessage), while base message leaf is (tips, remainingBody).\n if (MerkleMath.getParent(headerHash, MerkleMath.getParent(tips.leaf(), bodyHash)) != msgHash) {\n revert IncorrectTipsProof();\n }\n }\n}\n","language":"Solidity","languageVersion":"0.8.17","compilerVersion":"0.8.17","compilerOptions":"--combined-json bin,bin-runtime,srcmap,srcmap-runtime,abi,userdoc,devdoc,metadata,hashes --optimize --optimize-runs 10000 --allow-paths ., ./, ../","srcMap":"","srcMapRuntime":"","abiDefinition":[{"inputs":[],"name":"IncorrectVersionLength","type":"error"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint8","name":"version","type":"uint8"}],"name":"Initialized","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferStarted","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"inputs":[],"name":"acceptOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"localDomain","outputs":[{"internalType":"uint32","name":"","type":"uint32"}],"stateMutability":"view","type":"function"},{"inputs":[{"components":[{"internalType":"bool","name":"allowFailure","type":"bool"},{"internalType":"bytes","name":"callData","type":"bytes"}],"internalType":"struct MultiCallable.Call[]","name":"calls","type":"tuple[]"}],"name":"multicall","outputs":[{"components":[{"internalType":"bool","name":"success","type":"bool"},{"internalType":"bytes","name":"returnData","type":"bytes"}],"internalType":"struct MultiCallable.Result[]","name":"callResults","type":"tuple[]"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"pendingOwner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"synapseDomain","outputs":[{"internalType":"uint32","name":"","type":"uint32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"version","outputs":[{"internalType":"string","name":"versionString","type":"string"}],"stateMutability":"view","type":"function"}],"userDoc":{"kind":"user","methods":{"localDomain()":{"notice":"Domain of the local chain, set once upon contract creation"},"multicall((bool,bytes)[])":{"notice":"Aggregates a few calls to this contract into one multicall without modifying `msg.sender`."}},"notice":"Base contract for all messaging contracts. - Provides context on the local chain's domain. - Provides ownership functionality. - Will be providing pausing functionality when it is implemented.","version":1},"developerDoc":{"kind":"dev","methods":{"acceptOwnership()":{"details":"The new owner accepts the ownership transfer."},"owner()":{"details":"Returns the address of the current owner."},"pendingOwner()":{"details":"Returns the address of the pending owner."},"renounceOwnership()":{"details":"Should be impossible to renounce ownership; we override OpenZeppelin OwnableUpgradeable's implementation of renounceOwnership to make it a no-op"},"transferOwnership(address)":{"details":"Starts the ownership transfer of the contract to a new account. Replaces the pending transfer if there is one. Can only be called by the current owner."}},"stateVariables":{"__GAP":{"details":"gap for upgrade safety"}},"version":1},"metadata":"{\"compiler\":{\"version\":\"0.8.17+commit.8df45f5f\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[],\"name\":\"IncorrectVersionLength\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint8\",\"name\":\"version\",\"type\":\"uint8\"}],\"name\":\"Initialized\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"previousOwner\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"OwnershipTransferStarted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"previousOwner\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"OwnershipTransferred\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"acceptOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"localDomain\",\"outputs\":[{\"internalType\":\"uint32\",\"name\":\"\",\"type\":\"uint32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bool\",\"name\":\"allowFailure\",\"type\":\"bool\"},{\"internalType\":\"bytes\",\"name\":\"callData\",\"type\":\"bytes\"}],\"internalType\":\"struct MultiCallable.Call[]\",\"name\":\"calls\",\"type\":\"tuple[]\"}],\"name\":\"multicall\",\"outputs\":[{\"components\":[{\"internalType\":\"bool\",\"name\":\"success\",\"type\":\"bool\"},{\"internalType\":\"bytes\",\"name\":\"returnData\",\"type\":\"bytes\"}],\"internalType\":\"struct MultiCallable.Result[]\",\"name\":\"callResults\",\"type\":\"tuple[]\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"pendingOwner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"renounceOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"synapseDomain\",\"outputs\":[{\"internalType\":\"uint32\",\"name\":\"\",\"type\":\"uint32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"version\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"versionString\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{\"acceptOwnership()\":{\"details\":\"The new owner accepts the ownership transfer.\"},\"owner()\":{\"details\":\"Returns the address of the current owner.\"},\"pendingOwner()\":{\"details\":\"Returns the address of the pending owner.\"},\"renounceOwnership()\":{\"details\":\"Should be impossible to renounce ownership; we override OpenZeppelin OwnableUpgradeable's implementation of renounceOwnership to make it a no-op\"},\"transferOwnership(address)\":{\"details\":\"Starts the ownership transfer of the contract to a new account. Replaces the pending transfer if there is one. Can only be called by the current owner.\"}},\"stateVariables\":{\"__GAP\":{\"details\":\"gap for upgrade safety\"}},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{\"localDomain()\":{\"notice\":\"Domain of the local chain, set once upon contract creation\"},\"multicall((bool,bytes)[])\":{\"notice\":\"Aggregates a few calls to this contract into one multicall without modifying `msg.sender`.\"}},\"notice\":\"Base contract for all messaging contracts. - Provides context on the local chain's domain. - Provides ownership functionality. - Will be providing pausing functionality when it is implemented.\",\"version\":1}},\"settings\":{\"compilationTarget\":{\"solidity/Inbox.sol\":\"MessagingBase\"},\"evmVersion\":\"london\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\"},\"optimizer\":{\"enabled\":true,\"runs\":10000},\"remappings\":[]},\"sources\":{\"solidity/Inbox.sol\":{\"keccak256\":\"0x9b516081a036814c0169e20e484d4a5499066b7a6f48fada952b5e844a1ca3e5\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://32bde393b3f24ef4307d9626d4143f337b3c0bd34e17bb969fd5a15221d96987\",\"dweb:/ipfs/QmTkt2XZRtgsbSpmsVQUM3c4ebETQoDVYbmEV9yheBghnr\"]}},\"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/Inbox.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/InboxEvents.sol\n\nabstract contract InboxEvents {\n /**\n * @notice Emitted when a snapshot is accepted by the Summit contract.\n * @param domain Domain where the signed Agent is active (ZERO for Guards)\n * @param agent Agent who signed the snapshot\n * @param snapPayload Raw payload with snapshot data\n * @param snapSignature Agent signature for the snapshot\n */\n event SnapshotAccepted(uint32 indexed domain, address indexed agent, bytes snapPayload, bytes snapSignature);\n\n /**\n * @notice Emitted when a snapshot is accepted by the Summit contract.\n * @param domain Domain where the signed Notary is active\n * @param notary Notary who signed the attestation\n * @param rcptPayload Raw payload with receipt data\n * @param rcptSignature Notary signature for the receipt\n */\n event ReceiptAccepted(uint32 domain, address notary, bytes rcptPayload, bytes rcptSignature);\n\n /**\n * @notice Emitted when a proof of invalid attestation is submitted.\n * @param attPayload Raw payload with Attestation data\n * @param attSignature Notary signature for the attestation\n */\n event InvalidAttestation(bytes attPayload, bytes attSignature);\n\n /**\n * @notice Emitted when a proof of invalid attestation report is submitted.\n * @param arPayload Raw payload with report data\n * @param arSignature Guard signature for the report\n */\n event InvalidAttestationReport(bytes arPayload, bytes arSignature);\n}\n\n// contracts/events/StatementInboxEvents.sol\n\nabstract contract StatementInboxEvents {\n // ════════════════════════════════════════════ STATEMENT ACCEPTED ═════════════════════════════════════════════════\n\n /**\n * @notice Emitted when a snapshot is accepted by the Destination contract.\n * @param domain Domain where the signed Notary is active\n * @param notary Notary who signed the attestation\n * @param attPayload Raw payload with attestation data\n * @param attSignature Notary signature for the attestation\n */\n event AttestationAccepted(uint32 domain, address notary, bytes attPayload, bytes attSignature);\n\n // ═════════════════════════════════════════ INVALID STATEMENT PROVED ══════════════════════════════════════════════\n\n /**\n * @notice Emitted when a proof of invalid receipt statement is submitted.\n * @param rcptPayload Raw payload with the receipt statement\n * @param rcptSignature Notary signature for the receipt statement\n */\n event InvalidReceipt(bytes rcptPayload, bytes rcptSignature);\n\n /**\n * @notice Emitted when a proof of invalid receipt report is submitted.\n * @param rrPayload Raw payload with report data\n * @param rrSignature Guard signature for the report\n */\n event InvalidReceiptReport(bytes rrPayload, bytes rrSignature);\n\n /**\n * @notice Emitted when a proof of invalid state in the signed attestation is submitted.\n * @param stateIndex Index of invalid state in the snapshot\n * @param statePayload Raw payload with state data\n * @param attPayload Raw payload with Attestation data for snapshot\n * @param attSignature Notary signature for the attestation\n */\n event InvalidStateWithAttestation(uint8 stateIndex, bytes statePayload, bytes attPayload, bytes attSignature);\n\n /**\n * @notice Emitted when a proof of invalid state in the signed snapshot is submitted.\n * @param stateIndex Index of invalid state in the snapshot\n * @param snapPayload Raw payload with snapshot data\n * @param snapSignature Agent signature for the snapshot\n */\n event InvalidStateWithSnapshot(uint8 stateIndex, bytes snapPayload, bytes snapSignature);\n\n /**\n * @notice Emitted when a proof of invalid state report is submitted.\n * @param srPayload Raw payload with report data\n * @param srSignature Guard signature for the report\n */\n event InvalidStateReport(bytes srPayload, bytes srSignature);\n}\n\n// contracts/interfaces/ISnapshotHub.sol\n\ninterface ISnapshotHub {\n /**\n * @notice Check that a given attestation is valid: matches the historical attestation\n * derived from an accepted Notary snapshot.\n * @dev Will revert if any of these is true:\n * - Attestation payload is not properly formatted.\n * @param attPayload Raw payload with attestation data\n * @return isValid Whether the provided attestation is valid\n */\n function isValidAttestation(bytes memory attPayload) external view returns (bool isValid);\n\n /**\n * @notice Returns saved attestation with the given nonce.\n * @dev Reverts if attestation with given nonce hasn't been created yet.\n * @param attNonce Nonce for the attestation\n * @return attPayload Raw payload with formatted Attestation data\n * @return agentRoot Agent root hash used for the attestation\n * @return snapGas Snapshot gas data used for the attestation\n */\n function getAttestation(uint32 attNonce)\n external\n view\n returns (bytes memory attPayload, bytes32 agentRoot, uint256[] memory snapGas);\n\n /**\n * @notice Returns the state with the highest known nonce submitted by a given Agent.\n * @param origin Domain of origin chain\n * @param agent Agent address\n * @return statePayload Raw payload with agent's latest state for origin\n */\n function getLatestAgentState(uint32 origin, address agent) external view returns (bytes memory statePayload);\n\n /**\n * @notice Returns latest saved attestation for a Notary.\n * @param notary Notary address\n * @return attPayload Raw payload with formatted Attestation data\n * @return agentRoot Agent root hash used for the attestation\n * @return snapGas Snapshot gas data used for the attestation\n */\n function getLatestNotaryAttestation(address notary)\n external\n view\n returns (bytes memory attPayload, bytes32 agentRoot, uint256[] memory snapGas);\n\n /**\n * @notice Returns Guard snapshot from the list of all accepted Guard snapshots.\n * @dev Reverts if snapshot with given index hasn't been accepted yet.\n * @param index Snapshot index in the list of all Guard snapshots\n * @return snapPayload Raw payload with Guard snapshot\n * @return snapSignature Raw payload with Guard signature for snapshot\n */\n function getGuardSnapshot(uint256 index)\n external\n view\n returns (bytes memory snapPayload, bytes memory snapSignature);\n\n /**\n * @notice Returns Notary snapshot from the list of all accepted Guard snapshots.\n * @dev Reverts if snapshot with given index hasn't been accepted yet.\n * @param index Snapshot index in the list of all Notary snapshots\n * @return snapPayload Raw payload with Notary snapshot\n * @return snapSignature Raw payload with Notary signature for snapshot\n */\n function getNotarySnapshot(uint256 index)\n external\n view\n returns (bytes memory snapPayload, bytes memory snapSignature);\n\n /**\n * @notice Returns Notary snapshot that was used for creating a given attestation.\n * @dev Reverts if any of these is true:\n * - Attestation payload is not properly formatted.\n * - Attestation is invalid (doesn't have a matching Notary snapshot).\n * @param attPayload Raw payload with attestation data\n * @return snapPayload Raw payload with Notary snapshot\n * @return snapSignature Raw payload with Notary signature for snapshot\n */\n function getNotarySnapshot(bytes memory attPayload)\n external\n view\n returns (bytes memory snapPayload, bytes memory snapSignature);\n\n /**\n * @notice Returns proof of inclusion of (root, origin) fields of a given snapshot's state\n * into the Snapshot Merkle Tree for a given attestation.\n * @dev Reverts if any of these is true:\n * - Attestation with given nonce hasn't been created yet.\n * - State index is out of range of snapshot list.\n * @param attNonce Nonce for the attestation\n * @param stateIndex Index of state in the attestation's snapshot\n * @return snapProof The snapshot proof\n */\n function getSnapshotProof(uint32 attNonce, uint8 stateIndex) external view returns (bytes32[] memory snapProof);\n}\n\n// contracts/interfaces/IStateHub.sol\n\ninterface IStateHub {\n /**\n * @notice Check that a given state is valid: matches the historical state of Origin contract.\n * Note: any Agent including an invalid state in their snapshot will be slashed\n * upon providing the snapshot and agent signature for it to Origin contract.\n * @dev Will revert if any of these is true:\n * - State payload is not properly formatted.\n * @param statePayload Raw payload with state data\n * @return isValid Whether the provided state is valid\n */\n function isValidState(bytes memory statePayload) external view returns (bool isValid);\n\n /**\n * @notice Returns the amount of saved states so far.\n * @dev This includes the initial state of \"empty Origin Merkle Tree\".\n */\n function statesAmount() external view returns (uint256);\n\n /**\n * @notice Suggest the data (state after latest sent message) to sign for an Agent.\n * Note: signing the suggested state data will will never lead to slashing of the actor,\n * assuming they have confirmed that the block, which number is included in the data,\n * is not subject to reorganization (which is different for every observed chain).\n * @return statePayload Raw payload with the latest state data\n */\n function suggestLatestState() external view returns (bytes memory statePayload);\n\n /**\n * @notice Given the historical nonce, suggest the state data to sign for an Agent.\n * Note: signing the suggested state data will will never lead to slashing of the actor,\n * assuming they have confirmed that the block, which number is included in the data,\n * is not subject to reorganization (which is different for every observed chain).\n * @param nonce Historical nonce to form a state\n * @return statePayload Raw payload with historical state data\n */\n function suggestState(uint32 nonce) external view returns (bytes memory statePayload);\n}\n\n// contracts/interfaces/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/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// node_modules/@openzeppelin/contracts/utils/math/Math.sol\n\n// OpenZeppelin Contracts (last updated v4.9.0) (utils/math/Math.sol)\n\n/**\n * @dev Standard math utilities missing in the Solidity language.\n */\nlibrary Math {\n enum Rounding {\n Down, // Toward negative infinity\n Up, // Toward infinity\n Zero // Toward zero\n }\n\n /**\n * @dev Returns the largest of two numbers.\n */\n function max(uint256 a, uint256 b) internal pure returns (uint256) {\n return a \u003e b ? a : b;\n }\n\n /**\n * @dev Returns the smallest of two numbers.\n */\n function min(uint256 a, uint256 b) internal pure returns (uint256) {\n return a \u003c b ? a : b;\n }\n\n /**\n * @dev Returns the average of two numbers. The result is rounded towards\n * zero.\n */\n function average(uint256 a, uint256 b) internal pure returns (uint256) {\n // (a + b) / 2 can overflow.\n return (a \u0026 b) + (a ^ b) / 2;\n }\n\n /**\n * @dev Returns the ceiling of the division of two numbers.\n *\n * This differs from standard division with `/` in that it rounds up instead\n * of rounding down.\n */\n function ceilDiv(uint256 a, uint256 b) internal pure returns (uint256) {\n // (a + b - 1) / b can overflow on addition, so we distribute.\n return a == 0 ? 0 : (a - 1) / b + 1;\n }\n\n /**\n * @notice Calculates floor(x * y / denominator) with full precision. Throws if result overflows a uint256 or denominator == 0\n * @dev Original credit to Remco Bloemen under MIT license (https://xn--2-umb.com/21/muldiv)\n * with further edits by Uniswap Labs also under MIT license.\n */\n function mulDiv(uint256 x, uint256 y, uint256 denominator) internal pure returns (uint256 result) {\n unchecked {\n // 512-bit multiply [prod1 prod0] = x * y. Compute the product mod 2^256 and mod 2^256 - 1, then use\n // use the Chinese Remainder Theorem to reconstruct the 512 bit result. The result is stored in two 256\n // variables such that product = prod1 * 2^256 + prod0.\n uint256 prod0; // Least significant 256 bits of the product\n uint256 prod1; // Most significant 256 bits of the product\n assembly {\n let mm := mulmod(x, y, not(0))\n prod0 := mul(x, y)\n prod1 := sub(sub(mm, prod0), lt(mm, prod0))\n }\n\n // Handle non-overflow cases, 256 by 256 division.\n if (prod1 == 0) {\n // Solidity will revert if denominator == 0, unlike the div opcode on its own.\n // The surrounding unchecked block does not change this fact.\n // See https://docs.soliditylang.org/en/latest/control-structures.html#checked-or-unchecked-arithmetic.\n return prod0 / denominator;\n }\n\n // Make sure the result is less than 2^256. Also prevents denominator == 0.\n require(denominator \u003e prod1, \"Math: mulDiv overflow\");\n\n ///////////////////////////////////////////////\n // 512 by 256 division.\n ///////////////////////////////////////////////\n\n // Make division exact by subtracting the remainder from [prod1 prod0].\n uint256 remainder;\n assembly {\n // Compute remainder using mulmod.\n remainder := mulmod(x, y, denominator)\n\n // Subtract 256 bit number from 512 bit number.\n prod1 := sub(prod1, gt(remainder, prod0))\n prod0 := sub(prod0, remainder)\n }\n\n // Factor powers of two out of denominator and compute largest power of two divisor of denominator. Always \u003e= 1.\n // See https://cs.stackexchange.com/q/138556/92363.\n\n // Does not overflow because the denominator cannot be zero at this stage in the function.\n uint256 twos = denominator \u0026 (~denominator + 1);\n assembly {\n // Divide denominator by twos.\n denominator := div(denominator, twos)\n\n // Divide [prod1 prod0] by twos.\n prod0 := div(prod0, twos)\n\n // Flip twos such that it is 2^256 / twos. If twos is zero, then it becomes one.\n twos := add(div(sub(0, twos), twos), 1)\n }\n\n // Shift in bits from prod1 into prod0.\n prod0 |= prod1 * twos;\n\n // Invert denominator mod 2^256. Now that denominator is an odd number, it has an inverse modulo 2^256 such\n // that denominator * inv = 1 mod 2^256. Compute the inverse by starting with a seed that is correct for\n // four bits. That is, denominator * inv = 1 mod 2^4.\n uint256 inverse = (3 * denominator) ^ 2;\n\n // Use the Newton-Raphson iteration to improve the precision. Thanks to Hensel's lifting lemma, this also works\n // in modular arithmetic, doubling the correct bits in each step.\n inverse *= 2 - denominator * inverse; // inverse mod 2^8\n inverse *= 2 - denominator * inverse; // inverse mod 2^16\n inverse *= 2 - denominator * inverse; // inverse mod 2^32\n inverse *= 2 - denominator * inverse; // inverse mod 2^64\n inverse *= 2 - denominator * inverse; // inverse mod 2^128\n inverse *= 2 - denominator * inverse; // inverse mod 2^256\n\n // Because the division is now exact we can divide by multiplying with the modular inverse of denominator.\n // This will give us the correct result modulo 2^256. Since the preconditions guarantee that the outcome is\n // less than 2^256, this is the final result. We don't need to compute the high bits of the result and prod1\n // is no longer required.\n result = prod0 * inverse;\n return result;\n }\n }\n\n /**\n * @notice Calculates x * y / denominator with full precision, following the selected rounding direction.\n */\n function mulDiv(uint256 x, uint256 y, uint256 denominator, Rounding rounding) internal pure returns (uint256) {\n uint256 result = mulDiv(x, y, denominator);\n if (rounding == Rounding.Up \u0026\u0026 mulmod(x, y, denominator) \u003e 0) {\n result += 1;\n }\n return result;\n }\n\n /**\n * @dev Returns the square root of a number. If the number is not a perfect square, the value is rounded down.\n *\n * Inspired by Henry S. Warren, Jr.'s \"Hacker's Delight\" (Chapter 11).\n */\n function sqrt(uint256 a) internal pure returns (uint256) {\n if (a == 0) {\n return 0;\n }\n\n // For our first guess, we get the biggest power of 2 which is smaller than the square root of the target.\n //\n // We know that the \"msb\" (most significant bit) of our target number `a` is a power of 2 such that we have\n // `msb(a) \u003c= a \u003c 2*msb(a)`. This value can be written `msb(a)=2**k` with `k=log2(a)`.\n //\n // This can be rewritten `2**log2(a) \u003c= a \u003c 2**(log2(a) + 1)`\n // → `sqrt(2**k) \u003c= sqrt(a) \u003c sqrt(2**(k+1))`\n // → `2**(k/2) \u003c= sqrt(a) \u003c 2**((k+1)/2) \u003c= 2**(k/2 + 1)`\n //\n // Consequently, `2**(log2(a) / 2)` is a good first approximation of `sqrt(a)` with at least 1 correct bit.\n uint256 result = 1 \u003c\u003c (log2(a) \u003e\u003e 1);\n\n // At this point `result` is an estimation with one bit of precision. We know the true value is a uint128,\n // since it is the square root of a uint256. Newton's method converges quadratically (precision doubles at\n // every iteration). We thus need at most 7 iteration to turn our partial result with one bit of precision\n // into the expected uint128 result.\n unchecked {\n result = (result + a / result) \u003e\u003e 1;\n result = (result + a / result) \u003e\u003e 1;\n result = (result + a / result) \u003e\u003e 1;\n result = (result + a / result) \u003e\u003e 1;\n result = (result + a / result) \u003e\u003e 1;\n result = (result + a / result) \u003e\u003e 1;\n result = (result + a / result) \u003e\u003e 1;\n return min(result, a / result);\n }\n }\n\n /**\n * @notice Calculates sqrt(a), following the selected rounding direction.\n */\n function sqrt(uint256 a, Rounding rounding) internal pure returns (uint256) {\n unchecked {\n uint256 result = sqrt(a);\n return result + (rounding == Rounding.Up \u0026\u0026 result * result \u003c a ? 1 : 0);\n }\n }\n\n /**\n * @dev Return the log in base 2, rounded down, of a positive value.\n * Returns 0 if given 0.\n */\n function log2(uint256 value) internal pure returns (uint256) {\n uint256 result = 0;\n unchecked {\n if (value \u003e\u003e 128 \u003e 0) {\n value \u003e\u003e= 128;\n result += 128;\n }\n if (value \u003e\u003e 64 \u003e 0) {\n value \u003e\u003e= 64;\n result += 64;\n }\n if (value \u003e\u003e 32 \u003e 0) {\n value \u003e\u003e= 32;\n result += 32;\n }\n if (value \u003e\u003e 16 \u003e 0) {\n value \u003e\u003e= 16;\n result += 16;\n }\n if (value \u003e\u003e 8 \u003e 0) {\n value \u003e\u003e= 8;\n result += 8;\n }\n if (value \u003e\u003e 4 \u003e 0) {\n value \u003e\u003e= 4;\n result += 4;\n }\n if (value \u003e\u003e 2 \u003e 0) {\n value \u003e\u003e= 2;\n result += 2;\n }\n if (value \u003e\u003e 1 \u003e 0) {\n result += 1;\n }\n }\n return result;\n }\n\n /**\n * @dev Return the log in base 2, following the selected rounding direction, of a positive value.\n * Returns 0 if given 0.\n */\n function log2(uint256 value, Rounding rounding) internal pure returns (uint256) {\n unchecked {\n uint256 result = log2(value);\n return result + (rounding == Rounding.Up \u0026\u0026 1 \u003c\u003c result \u003c value ? 1 : 0);\n }\n }\n\n /**\n * @dev Return the log in base 10, rounded down, of a positive value.\n * Returns 0 if given 0.\n */\n function log10(uint256 value) internal pure returns (uint256) {\n uint256 result = 0;\n unchecked {\n if (value \u003e= 10 ** 64) {\n value /= 10 ** 64;\n result += 64;\n }\n if (value \u003e= 10 ** 32) {\n value /= 10 ** 32;\n result += 32;\n }\n if (value \u003e= 10 ** 16) {\n value /= 10 ** 16;\n result += 16;\n }\n if (value \u003e= 10 ** 8) {\n value /= 10 ** 8;\n result += 8;\n }\n if (value \u003e= 10 ** 4) {\n value /= 10 ** 4;\n result += 4;\n }\n if (value \u003e= 10 ** 2) {\n value /= 10 ** 2;\n result += 2;\n }\n if (value \u003e= 10 ** 1) {\n result += 1;\n }\n }\n return result;\n }\n\n /**\n * @dev Return the log in base 10, following the selected rounding direction, of a positive value.\n * Returns 0 if given 0.\n */\n function log10(uint256 value, Rounding rounding) internal pure returns (uint256) {\n unchecked {\n uint256 result = log10(value);\n return result + (rounding == Rounding.Up \u0026\u0026 10 ** result \u003c value ? 1 : 0);\n }\n }\n\n /**\n * @dev Return the log in base 256, rounded down, of a positive value.\n * Returns 0 if given 0.\n *\n * Adding one to the result gives the number of pairs of hex symbols needed to represent `value` as a hex string.\n */\n function log256(uint256 value) internal pure returns (uint256) {\n uint256 result = 0;\n unchecked {\n if (value \u003e\u003e 128 \u003e 0) {\n value \u003e\u003e= 128;\n result += 16;\n }\n if (value \u003e\u003e 64 \u003e 0) {\n value \u003e\u003e= 64;\n result += 8;\n }\n if (value \u003e\u003e 32 \u003e 0) {\n value \u003e\u003e= 32;\n result += 4;\n }\n if (value \u003e\u003e 16 \u003e 0) {\n value \u003e\u003e= 16;\n result += 2;\n }\n if (value \u003e\u003e 8 \u003e 0) {\n result += 1;\n }\n }\n return result;\n }\n\n /**\n * @dev Return the log in base 256, following the selected rounding direction, of a positive value.\n * Returns 0 if given 0.\n */\n function log256(uint256 value, Rounding rounding) internal pure returns (uint256) {\n unchecked {\n uint256 result = log256(value);\n return result + (rounding == Rounding.Up \u0026\u0026 1 \u003c\u003c (result \u003c\u003c 3) \u003c value ? 1 : 0);\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/utils/math/SignedMath.sol\n\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/math/SignedMath.sol)\n\n/**\n * @dev Standard signed math utilities missing in the Solidity language.\n */\nlibrary SignedMath {\n /**\n * @dev Returns the largest of two signed numbers.\n */\n function max(int256 a, int256 b) internal pure returns (int256) {\n return a \u003e b ? a : b;\n }\n\n /**\n * @dev Returns the smallest of two signed numbers.\n */\n function min(int256 a, int256 b) internal pure returns (int256) {\n return a \u003c b ? a : b;\n }\n\n /**\n * @dev Returns the average of two signed numbers without overflow.\n * The result is rounded towards zero.\n */\n function average(int256 a, int256 b) internal pure returns (int256) {\n // Formula from the book \"Hacker's Delight\"\n int256 x = (a \u0026 b) + ((a ^ b) \u003e\u003e 1);\n return x + (int256(uint256(x) \u003e\u003e 255) \u0026 (a ^ b));\n }\n\n /**\n * @dev Returns the absolute unsigned value of a signed value.\n */\n function abs(int256 n) internal pure returns (uint256) {\n unchecked {\n // must be unchecked in order to support `n = type(int256).min`\n return uint256(n \u003e= 0 ? n : -n);\n }\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// 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/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/InterfaceSummit.sol\n\ninterface InterfaceSummit {\n // ══════════════════════════════════════════ ACCEPT AGENT STATEMENTS ══════════════════════════════════════════════\n\n /**\n * @notice Accepts a receipt, which local `AgentManager` verified to have been signed by an active Notary.\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 * - Notary who signed the receipt is referenced as the \"Receipt Notary\".\n * - Notary who signed the attestation on destination chain is referenced as the \"Attestation Notary\".\n * \u003e Will revert if any of these is true:\n * \u003e - Called by anyone other than local `AgentManager`.\n * \u003e - Receipt body payload is not properly formatted.\n * \u003e - Receipt signer is in Dispute.\n * \u003e - Receipt's snapshot root is unknown.\n * @param rcptNotaryIndex Index of Receipt Notary in Agent Merkle Tree\n * @param attNotaryIndex Index of Attestation Notary in Agent Merkle Tree\n * @param sigIndex Index of stored Notary signature\n * @param attNonce Nonce of the attestation used for proving the executed message\n * @param paddedTips Padded encoded paid tips information\n * @param rcptPayload Raw payload with message execution receipt\n * @return wasAccepted Whether the receipt was accepted\n */\n function acceptReceipt(\n uint32 rcptNotaryIndex,\n uint32 attNotaryIndex,\n uint256 sigIndex,\n uint32 attNonce,\n uint256 paddedTips,\n bytes memory rcptPayload\n ) external returns (bool wasAccepted);\n\n /**\n * @notice Accepts a snapshot, which local `AgentManager` verified to have been signed by an active Guard.\n * \u003e Snapshot is a list of states for a set of Origin contracts residing on any of the chains.\n * All the states in the Guard-signed snapshot become available for Notary signing.\n * \u003e Will revert if any of these is true:\n * \u003e - Called by anyone other than local `AgentManager`.\n * \u003e - Snapshot payload is not properly formatted.\n * \u003e - Snapshot contains a state older then the Guard has previously submitted.\n * @param guardIndex Index of Guard in Agent Merkle Tree\n * @param sigIndex Index of stored Agent signature\n * @param snapPayload Raw payload with snapshot data\n */\n function acceptGuardSnapshot(uint32 guardIndex, uint256 sigIndex, bytes memory snapPayload) external;\n\n /**\n * @notice Accepts a snapshot, which local `AgentManager` verified to have been signed by an active Notary.\n * \u003e Snapshot is a list of states for a set of Origin contracts residing on any of the chains.\n * Snapshot Merkle Root is calculated and saved for valid snapshots, i.e.\n * snapshots which are only using states previously submitted by any of the Guards.\n * - Notary could use states singed by the same of different Guards 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 - Called by anyone other than local `AgentManager`.\n * \u003e - Snapshot payload is not properly formatted.\n * \u003e - Snapshot contains a state older then the Notary has previously submitted.\n * \u003e - Snapshot contains a state that no Guard has previously submitted.\n * @param notaryIndex Index of Notary in Agent Merkle Tree\n * @param sigIndex Index of stored Agent signature\n * @param agentRoot Current root of the Agent Merkle Tree\n * @param snapPayload Raw payload with snapshot data\n * @return attPayload Raw payload with data for attestation derived from Notary snapshot.\n */\n function acceptNotarySnapshot(uint32 notaryIndex, uint256 sigIndex, bytes32 agentRoot, bytes memory snapPayload)\n external\n returns (bytes memory attPayload);\n\n // ════════════════════════════════════════════════ TIPS LOGIC ═════════════════════════════════════════════════════\n\n /**\n * @notice Distributes tips using the first Receipt from the \"receipt quarantine queue\".\n * Possible scenarios:\n * - Receipt queue is empty =\u003e does nothing\n * - Receipt optimistic period is not over =\u003e does nothing\n * - Either of Notaries present in Receipt was slashed =\u003e receipt is deleted from the queue\n * - Either of Notaries present in Receipt in Dispute =\u003e receipt is moved to the end of queue\n * - None of the above =\u003e receipt tips are distributed\n * @dev Returned value makes it possible to do the following: `while (distributeTips()) {}`\n * @return queuePopped Whether the first element was popped from the queue\n */\n function distributeTips() external returns (bool queuePopped);\n\n /**\n * @notice Withdraws locked base message tips from requested domain Origin to the recipient.\n * This is done by a call to a local Origin contract, or by a manager message to the remote chain.\n * @dev This will revert, if the pending balance of origin tips (earned-claimed) is lower than requested.\n * @param origin Domain of chain to withdraw tips on\n * @param amount Amount of tips to withdraw\n */\n function withdrawTips(uint32 origin, uint256 amount) external;\n\n // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════\n\n /**\n * @notice Returns earned and claimed tips for the actor.\n * Note: Tips for address(0) belong to the Treasury.\n * @param actor Address of the actor\n * @param origin Domain where the tips were initially paid\n * @return earned Total amount of origin tips the actor has earned so far\n * @return claimed Total amount of origin tips the actor has claimed so far\n */\n function actorTips(address actor, uint32 origin) external view returns (uint128 earned, uint128 claimed);\n\n /**\n * @notice Returns the amount of receipts in the \"Receipt Quarantine Queue\".\n */\n function receiptQueueLength() external view returns (uint256);\n\n /**\n * @notice Returns the state with the highest known nonce\n * submitted by any of the currently active Guards.\n * @param origin Domain of origin chain\n * @return statePayload Raw payload with latest active Guard state for origin\n */\n function getLatestState(uint32 origin) external view returns (bytes memory statePayload);\n}\n\n// node_modules/@openzeppelin/contracts/utils/Strings.sol\n\n// OpenZeppelin Contracts (last updated v4.9.0) (utils/Strings.sol)\n\n/**\n * @dev String operations.\n */\nlibrary Strings {\n bytes16 private constant _SYMBOLS = \"0123456789abcdef\";\n uint8 private constant _ADDRESS_LENGTH = 20;\n\n /**\n * @dev Converts a `uint256` to its ASCII `string` decimal representation.\n */\n function toString(uint256 value) internal pure returns (string memory) {\n unchecked {\n uint256 length = Math.log10(value) + 1;\n string memory buffer = new string(length);\n uint256 ptr;\n /// @solidity memory-safe-assembly\n assembly {\n ptr := add(buffer, add(32, length))\n }\n while (true) {\n ptr--;\n /// @solidity memory-safe-assembly\n assembly {\n mstore8(ptr, byte(mod(value, 10), _SYMBOLS))\n }\n value /= 10;\n if (value == 0) break;\n }\n return buffer;\n }\n }\n\n /**\n * @dev Converts a `int256` to its ASCII `string` decimal representation.\n */\n function toString(int256 value) internal pure returns (string memory) {\n return string(abi.encodePacked(value \u003c 0 ? \"-\" : \"\", toString(SignedMath.abs(value))));\n }\n\n /**\n * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation.\n */\n function toHexString(uint256 value) internal pure returns (string memory) {\n unchecked {\n return toHexString(value, Math.log256(value) + 1);\n }\n }\n\n /**\n * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length.\n */\n function toHexString(uint256 value, uint256 length) internal pure returns (string memory) {\n bytes memory buffer = new bytes(2 * length + 2);\n buffer[0] = \"0\";\n buffer[1] = \"x\";\n for (uint256 i = 2 * length + 1; i \u003e 1; --i) {\n buffer[i] = _SYMBOLS[value \u0026 0xf];\n value \u003e\u003e= 4;\n }\n require(value == 0, \"Strings: hex length insufficient\");\n return string(buffer);\n }\n\n /**\n * @dev Converts an `address` with fixed length of 20 bytes to its not checksummed ASCII `string` hexadecimal representation.\n */\n function toHexString(address addr) internal pure returns (string memory) {\n return toHexString(uint256(uint160(addr)), _ADDRESS_LENGTH);\n }\n\n /**\n * @dev Returns true if the two strings are equal.\n */\n function equal(string memory a, string memory b) internal pure returns (bool) {\n return keccak256(bytes(a)) == keccak256(bytes(b));\n }\n}\n\n// node_modules/@openzeppelin/contracts-upgradeable/utils/ContextUpgradeable.sol\n\n// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)\n\n/**\n * @dev Provides information about the current execution context, including the\n * sender of the transaction and its data. While these are generally available\n * via msg.sender and msg.data, they should not be accessed in such a direct\n * manner, since when dealing with meta-transactions the account sending and\n * paying for execution may not be the actual sender (as far as an application\n * is concerned).\n *\n * This contract is only required for intermediate, library-like contracts.\n */\nabstract contract ContextUpgradeable is Initializable {\n function __Context_init() internal onlyInitializing {\n }\n\n function __Context_init_unchained() internal onlyInitializing {\n }\n function _msgSender() internal view virtual returns (address) {\n return msg.sender;\n }\n\n function _msgData() internal view virtual returns (bytes calldata) {\n return msg.data;\n }\n\n /**\n * @dev This empty reserved space is put in place to allow future versions to add new\n * variables without shifting down storage in the inheritance chain.\n * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\n */\n uint256[50] private __gap;\n}\n\n// contracts/libs/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/utils/cryptography/ECDSA.sol\n\n// OpenZeppelin Contracts (last updated v4.9.0) (utils/cryptography/ECDSA.sol)\n\n/**\n * @dev Elliptic Curve Digital Signature Algorithm (ECDSA) operations.\n *\n * These functions can be used to verify that a message was signed by the holder\n * of the private keys of a given address.\n */\nlibrary ECDSA {\n enum RecoverError {\n NoError,\n InvalidSignature,\n InvalidSignatureLength,\n InvalidSignatureS,\n InvalidSignatureV // Deprecated in v4.8\n }\n\n function _throwError(RecoverError error) private pure {\n if (error == RecoverError.NoError) {\n return; // no error: do nothing\n } else if (error == RecoverError.InvalidSignature) {\n revert(\"ECDSA: invalid signature\");\n } else if (error == RecoverError.InvalidSignatureLength) {\n revert(\"ECDSA: invalid signature length\");\n } else if (error == RecoverError.InvalidSignatureS) {\n revert(\"ECDSA: invalid signature 's' value\");\n }\n }\n\n /**\n * @dev Returns the address that signed a hashed message (`hash`) with\n * `signature` or error string. This address can then be used for verification purposes.\n *\n * The `ecrecover` EVM opcode allows for malleable (non-unique) signatures:\n * this function rejects them by requiring the `s` value to be in the lower\n * half order, and the `v` value to be either 27 or 28.\n *\n * IMPORTANT: `hash` _must_ be the result of a hash operation for the\n * verification to be secure: it is possible to craft signatures that\n * recover to arbitrary addresses for non-hashed data. A safe way to ensure\n * this is by receiving a hash of the original message (which may otherwise\n * be too long), and then calling {toEthSignedMessageHash} on it.\n *\n * Documentation for signature generation:\n * - with https://web3js.readthedocs.io/en/v1.3.4/web3-eth-accounts.html#sign[Web3.js]\n * - with https://docs.ethers.io/v5/api/signer/#Signer-signMessage[ethers]\n *\n * _Available since v4.3._\n */\n function tryRecover(bytes32 hash, bytes memory signature) internal pure returns (address, RecoverError) {\n if (signature.length == 65) {\n bytes32 r;\n bytes32 s;\n uint8 v;\n // ecrecover takes the signature parameters, and the only way to get them\n // currently is to use assembly.\n /// @solidity memory-safe-assembly\n assembly {\n r := mload(add(signature, 0x20))\n s := mload(add(signature, 0x40))\n v := byte(0, mload(add(signature, 0x60)))\n }\n return tryRecover(hash, v, r, s);\n } else {\n return (address(0), RecoverError.InvalidSignatureLength);\n }\n }\n\n /**\n * @dev Returns the address that signed a hashed message (`hash`) with\n * `signature`. This address can then be used for verification purposes.\n *\n * The `ecrecover` EVM opcode allows for malleable (non-unique) signatures:\n * this function rejects them by requiring the `s` value to be in the lower\n * half order, and the `v` value to be either 27 or 28.\n *\n * IMPORTANT: `hash` _must_ be the result of a hash operation for the\n * verification to be secure: it is possible to craft signatures that\n * recover to arbitrary addresses for non-hashed data. A safe way to ensure\n * this is by receiving a hash of the original message (which may otherwise\n * be too long), and then calling {toEthSignedMessageHash} on it.\n */\n function recover(bytes32 hash, bytes memory signature) internal pure returns (address) {\n (address recovered, RecoverError error) = tryRecover(hash, signature);\n _throwError(error);\n return recovered;\n }\n\n /**\n * @dev Overload of {ECDSA-tryRecover} that receives the `r` and `vs` short-signature fields separately.\n *\n * See https://eips.ethereum.org/EIPS/eip-2098[EIP-2098 short signatures]\n *\n * _Available since v4.3._\n */\n function tryRecover(bytes32 hash, bytes32 r, bytes32 vs) internal pure returns (address, RecoverError) {\n bytes32 s = vs \u0026 bytes32(0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff);\n uint8 v = uint8((uint256(vs) \u003e\u003e 255) + 27);\n return tryRecover(hash, v, r, s);\n }\n\n /**\n * @dev Overload of {ECDSA-recover} that receives the `r and `vs` short-signature fields separately.\n *\n * _Available since v4.2._\n */\n function recover(bytes32 hash, bytes32 r, bytes32 vs) internal pure returns (address) {\n (address recovered, RecoverError error) = tryRecover(hash, r, vs);\n _throwError(error);\n return recovered;\n }\n\n /**\n * @dev Overload of {ECDSA-tryRecover} that receives the `v`,\n * `r` and `s` signature fields separately.\n *\n * _Available since v4.3._\n */\n function tryRecover(bytes32 hash, uint8 v, bytes32 r, bytes32 s) internal pure returns (address, RecoverError) {\n // EIP-2 still allows signature malleability for ecrecover(). Remove this possibility and make the signature\n // unique. Appendix F in the Ethereum Yellow paper (https://ethereum.github.io/yellowpaper/paper.pdf), defines\n // the valid range for s in (301): 0 \u003c s \u003c secp256k1n ÷ 2 + 1, and for v in (302): v ∈ {27, 28}. Most\n // signatures from current libraries generate a unique signature with an s-value in the lower half order.\n //\n // If your library generates malleable signatures, such as s-values in the upper range, calculate a new s-value\n // with 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141 - s1 and flip v from 27 to 28 or\n // vice versa. If your library also generates signatures with 0/1 for v instead 27/28, add 27 to v to accept\n // these malleable signatures as well.\n if (uint256(s) \u003e 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0) {\n return (address(0), RecoverError.InvalidSignatureS);\n }\n\n // If the signature is valid (and not malleable), return the signer address\n address signer = ecrecover(hash, v, r, s);\n if (signer == address(0)) {\n return (address(0), RecoverError.InvalidSignature);\n }\n\n return (signer, RecoverError.NoError);\n }\n\n /**\n * @dev Overload of {ECDSA-recover} that receives the `v`,\n * `r` and `s` signature fields separately.\n */\n function recover(bytes32 hash, uint8 v, bytes32 r, bytes32 s) internal pure returns (address) {\n (address recovered, RecoverError error) = tryRecover(hash, v, r, s);\n _throwError(error);\n return recovered;\n }\n\n /**\n * @dev Returns an Ethereum Signed Message, created from a `hash`. This\n * produces hash corresponding to the one signed with the\n * https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`]\n * JSON-RPC method as part of EIP-191.\n *\n * See {recover}.\n */\n function toEthSignedMessageHash(bytes32 hash) internal pure returns (bytes32 message) {\n // 32 is the length in bytes of hash,\n // enforced by the type signature above\n /// @solidity memory-safe-assembly\n assembly {\n mstore(0x00, \"\\x19Ethereum Signed Message:\\n32\")\n mstore(0x1c, hash)\n message := keccak256(0x00, 0x3c)\n }\n }\n\n /**\n * @dev Returns an Ethereum Signed Message, created from `s`. This\n * produces hash corresponding to the one signed with the\n * https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`]\n * JSON-RPC method as part of EIP-191.\n *\n * See {recover}.\n */\n function toEthSignedMessageHash(bytes memory s) internal pure returns (bytes32) {\n return keccak256(abi.encodePacked(\"\\x19Ethereum Signed Message:\\n\", Strings.toString(s.length), s));\n }\n\n /**\n * @dev Returns an Ethereum Signed Typed Data, created from a\n * `domainSeparator` and a `structHash`. This produces hash corresponding\n * to the one signed with the\n * https://eips.ethereum.org/EIPS/eip-712[`eth_signTypedData`]\n * JSON-RPC method as part of EIP-712.\n *\n * See {recover}.\n */\n function toTypedDataHash(bytes32 domainSeparator, bytes32 structHash) internal pure returns (bytes32 data) {\n /// @solidity memory-safe-assembly\n assembly {\n let ptr := mload(0x40)\n mstore(ptr, \"\\x19\\x01\")\n mstore(add(ptr, 0x02), domainSeparator)\n mstore(add(ptr, 0x22), structHash)\n data := keccak256(ptr, 0x42)\n }\n }\n\n /**\n * @dev Returns an Ethereum Signed Data with intended validator, created from a\n * `validator` and `data` according to the version 0 of EIP-191.\n *\n * See {recover}.\n */\n function toDataWithIntendedValidatorHash(address validator, bytes memory data) internal pure returns (bytes32) {\n return keccak256(abi.encodePacked(\"\\x19\\x00\", validator, data));\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/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/inbox/StatementInbox.sol\n\n// ══════════════════════════════ LIBRARY IMPORTS ══════════════════════════════\n\n// ═════════════════════════════ INTERNAL IMPORTS ══════════════════════════════\n\n// ═════════════════════════════ EXTERNAL IMPORTS ══════════════════════════════\n\n/// @notice `StatementInbox` is the entry point for all agent-signed statements. It verifies the\n/// agent signatures, and passes the unsigned statements to the contract to consume it via `acceptX` functions. Is is\n/// also used to verify the agent-signed statements and initiate the agent slashing, should the statement be invalid.\n/// `StatementInbox` is responsible for the following:\n/// - Accepting State and Receipt Reports to initiate a dispute between Guard and Notary.\n/// - Storing all the Guard Reports with the Guard signature leading to a dispute.\n/// - Verifying State/State Reports referencing the local chain and slashing the signer if statement is invalid.\n/// - Verifying Receipt/Receipt Reports referencing the local chain and slashing the signer if statement is invalid.\nabstract contract StatementInbox is MessagingBase, StatementInboxEvents, IStatementInbox {\n using AttestationLib for bytes;\n using ReceiptLib for bytes;\n using StateLib for bytes;\n using SnapshotLib for bytes;\n\n struct StoredReport {\n uint256 sigIndex;\n bytes statementPayload;\n }\n\n // ══════════════════════════════════════════════════ STORAGE ══════════════════════════════════════════════════════\n\n address public agentManager;\n address public origin;\n address public destination;\n\n // TODO: optimize this\n bytes[] internal _storedSignatures;\n StoredReport[] internal _storedReports;\n\n /// @dev gap for upgrade safety\n uint256[45] private __GAP; // solhint-disable-line var-name-mixedcase\n\n // ════════════════════════════════════════════════ INITIALIZER ════════════════════════════════════════════════════\n\n /// @dev Initializes the contract:\n /// - Sets up `msg.sender` as the owner of the contract.\n /// - Sets up `agentManager`, `origin`, and `destination`.\n // solhint-disable-next-line func-name-mixedcase\n function __StatementInbox_init(address agentManager_, address origin_, address destination_)\n internal\n onlyInitializing\n {\n agentManager = agentManager_;\n origin = origin_;\n destination = destination_;\n __Ownable2Step_init();\n }\n\n // ══════════════════════════════════════════ SUBMIT AGENT STATEMENTS ══════════════════════════════════════════════\n\n /// @inheritdoc IStatementInbox\n // solhint-disable-next-line ordering\n function submitStateReportWithSnapshot(\n uint8 stateIndex,\n bytes memory srSignature,\n bytes memory snapPayload,\n bytes memory snapSignature\n ) external returns (bool wasAccepted) {\n // This will revert if payload is not a snapshot\n Snapshot snapshot = snapPayload.castToSnapshot();\n // This will revert if the snapshot signer is not a known Notary\n (AgentStatus memory notaryStatus,) =\n _verifySnapshot({snapshot: snapshot, snapSignature: snapSignature, verifyNotary: true});\n // Notary needs to be Active/Unstaking\n notaryStatus.verifyActiveUnstaking();\n // Check if Notary is active on this chain\n _verifyNotaryDomain(notaryStatus.domain);\n // This will revert if state index is out of range\n State state = snapshot.state(stateIndex);\n // This will revert if the report signer is not an known Guard\n (AgentStatus memory guardStatus,) = _verifyStateReport(state, srSignature);\n // Check that Guard is active\n guardStatus.verifyActive();\n _saveReport(state.unwrap().clone(), srSignature);\n // This will revert if either actor is already in dispute\n IAgentManager(agentManager).openDispute(guardStatus.index, notaryStatus.index);\n return true;\n }\n\n /// @inheritdoc IStatementInbox\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 // This will revert if payload is not a snapshot\n Snapshot snapshot = snapPayload.castToSnapshot();\n // This will revert if state index is out of range\n State state = snapshot.state(stateIndex);\n // This will revert if the report signer is not an known Guard\n (AgentStatus memory guardStatus,) = _verifyStateReport(state, srSignature);\n // Check that Guard is active\n guardStatus.verifyActive();\n // This will revert if payload is not an attestation\n Attestation att = attPayload.castToAttestation();\n // This will revert if signer is not an known Notary\n (AgentStatus memory notaryStatus,) = _verifyAttestation(att, attSignature);\n // Notary needs to be Active/Unstaking\n notaryStatus.verifyActiveUnstaking();\n // Check if Notary is active on this chain\n _verifyNotaryDomain(notaryStatus.domain);\n if (snapshot.calculateRoot() != att.snapRoot()) revert IncorrectSnapshotRoot();\n _saveReport(state.unwrap().clone(), srSignature);\n // This will revert if either actor is already in dispute\n IAgentManager(agentManager).openDispute(guardStatus.index, notaryStatus.index);\n return true;\n }\n\n /// @inheritdoc IStatementInbox\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 // This will revert if payload is not a state\n State state = statePayload.castToState();\n // This will revert if the report signer is not an known Guard\n (AgentStatus memory guardStatus,) = _verifyStateReport(state, srSignature);\n // Check that Guard is active\n guardStatus.verifyActive();\n // This will revert if payload is not an attestation\n Attestation att = attPayload.castToAttestation();\n // This will revert if signer is not a known Notary\n (AgentStatus memory notaryStatus,) = _verifyAttestation(att, attSignature);\n // Notary needs to be Active/Unstaking\n notaryStatus.verifyActiveUnstaking();\n // Check if Notary is active on this chain\n _verifyNotaryDomain(notaryStatus.domain);\n // This will revert if any of these is true:\n // - Attestation root is not equal to Merkle Root derived from State and Snapshot Proof.\n // - Snapshot Proof's first element does not match the State metadata.\n // - Snapshot Proof length exceeds Snapshot tree Height.\n // - State index is out of range.\n _verifySnapshotMerkle(att, stateIndex, state, snapProof);\n _saveReport(statePayload, srSignature);\n // This will revert if either actor is already in dispute\n IAgentManager(agentManager).openDispute(guardStatus.index, notaryStatus.index);\n return true;\n }\n\n // ══════════════════════════════════════════ VERIFY AGENT STATEMENTS ══════════════════════════════════════════════\n\n /// @inheritdoc IStatementInbox\n function verifyReceipt(bytes memory rcptPayload, bytes memory rcptSignature)\n external\n returns (bool isValidReceipt)\n {\n // This will revert if payload is not a receipt\n Receipt rcpt = rcptPayload.castToReceipt();\n // This will revert if the attestation signer is not a known Notary\n (AgentStatus memory status, address notary) = _verifyReceipt(rcpt, rcptSignature);\n // Notary needs to be Active/Unstaking\n status.verifyActiveUnstaking();\n isValidReceipt = IExecutionHub(destination).isValidReceipt(rcptPayload);\n if (!isValidReceipt) {\n emit InvalidReceipt(rcptPayload, rcptSignature);\n IAgentManager(agentManager).slashAgent(status.domain, notary, msg.sender);\n }\n }\n\n /// @inheritdoc IStatementInbox\n function verifyReceiptReport(bytes memory rcptPayload, bytes memory rrSignature)\n external\n returns (bool isValidReport)\n {\n // This will revert if payload is not a receipt\n Receipt rcpt = rcptPayload.castToReceipt();\n // This will revert if the report signer is not a known Guard\n (AgentStatus memory status, address guard) = _verifyReceiptReport(rcpt, rrSignature);\n // Guard needs to be Active/Unstaking\n status.verifyActiveUnstaking();\n // Report is valid IF AND ONLY IF the reported receipt in invalid\n isValidReport = !IExecutionHub(destination).isValidReceipt(rcptPayload);\n if (!isValidReport) {\n emit InvalidReceiptReport(rcptPayload, rrSignature);\n IAgentManager(agentManager).slashAgent(status.domain, guard, msg.sender);\n }\n }\n\n /// @inheritdoc IStatementInbox\n function verifyStateWithAttestation(\n uint8 stateIndex,\n bytes memory snapPayload,\n bytes memory attPayload,\n bytes memory attSignature\n ) external returns (bool isValidState) {\n // This will revert if payload is not an attestation\n Attestation att = attPayload.castToAttestation();\n // This will revert if the attestation signer is not a known Notary\n (AgentStatus memory status, address notary) = _verifyAttestation(att, attSignature);\n // Notary needs to be Active/Unstaking\n status.verifyActiveUnstaking();\n // This will revert if payload is not a snapshot\n Snapshot snapshot = snapPayload.castToSnapshot();\n if (snapshot.calculateRoot() != att.snapRoot()) revert IncorrectSnapshotRoot();\n // This will revert if state does not refer to this chain\n bytes memory statePayload = snapshot.state(stateIndex).unwrap().clone();\n isValidState = IStateHub(origin).isValidState(statePayload);\n if (!isValidState) {\n emit InvalidStateWithAttestation(stateIndex, statePayload, attPayload, attSignature);\n IAgentManager(agentManager).slashAgent(status.domain, notary, msg.sender);\n }\n }\n\n /// @inheritdoc IStatementInbox\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 // This will revert if payload is not an attestation\n Attestation att = attPayload.castToAttestation();\n // This will revert if the attestation signer is not a known Notary\n (AgentStatus memory status, address notary) = _verifyAttestation(att, attSignature);\n // Notary needs to be Active/Unstaking\n status.verifyActiveUnstaking();\n // This will revert if payload is not a state\n State state = statePayload.castToState();\n // This will revert if any of these is true:\n // - Attestation root is not equal to Merkle Root derived from State and Snapshot Proof.\n // - Snapshot Proof's first element does not match the State metadata.\n // - Snapshot Proof length exceeds Snapshot tree Height.\n // - State index is out of range.\n _verifySnapshotMerkle(att, stateIndex, state, snapProof);\n // This will revert if state does not refer to this chain\n isValidState = IStateHub(origin).isValidState(statePayload);\n if (!isValidState) {\n emit InvalidStateWithAttestation(stateIndex, statePayload, attPayload, attSignature);\n IAgentManager(agentManager).slashAgent(status.domain, notary, msg.sender);\n }\n }\n\n /// @inheritdoc IStatementInbox\n function verifyStateWithSnapshot(uint8 stateIndex, bytes memory snapPayload, bytes memory snapSignature)\n external\n returns (bool isValidState)\n {\n // This will revert if payload is not a snapshot\n Snapshot snapshot = snapPayload.castToSnapshot();\n // This will revert if the snapshot signer is not a known Guard/Notary\n (AgentStatus memory status, address agent) =\n _verifySnapshot({snapshot: snapshot, snapSignature: snapSignature, verifyNotary: false});\n // Agent needs to be Active/Unstaking\n status.verifyActiveUnstaking();\n // This will revert if state does not refer to this chain\n isValidState = IStateHub(origin).isValidState(snapshot.state(stateIndex).unwrap().clone());\n if (!isValidState) {\n emit InvalidStateWithSnapshot(stateIndex, snapPayload, snapSignature);\n IAgentManager(agentManager).slashAgent(status.domain, agent, msg.sender);\n }\n }\n\n /// @inheritdoc IStatementInbox\n function verifyStateReport(bytes memory statePayload, bytes memory srSignature)\n external\n returns (bool isValidReport)\n {\n // This will revert if payload is not a state\n State state = statePayload.castToState();\n // This will revert if the report signer is not a known Guard\n (AgentStatus memory status, address guard) = _verifyStateReport(state, srSignature);\n // Guard needs to be Active/Unstaking\n status.verifyActiveUnstaking();\n // Report is valid IF AND ONLY IF the reported state in invalid\n // This will revert if the reported state does not refer to this chain\n isValidReport = !IStateHub(origin).isValidState(statePayload);\n if (!isValidReport) {\n emit InvalidStateReport(statePayload, srSignature);\n IAgentManager(agentManager).slashAgent(status.domain, guard, msg.sender);\n }\n }\n\n // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════\n\n /// @inheritdoc IStatementInbox\n function getReportsAmount() external view returns (uint256) {\n return _storedReports.length;\n }\n\n /// @inheritdoc IStatementInbox\n function getGuardReport(uint256 index)\n external\n view\n returns (bytes memory statementPayload, bytes memory reportSignature)\n {\n if (index \u003e= _storedReports.length) revert IndexOutOfRange();\n StoredReport memory storedReport = _storedReports[index];\n statementPayload = storedReport.statementPayload;\n reportSignature = _storedSignatures[storedReport.sigIndex];\n }\n\n /// @inheritdoc IStatementInbox\n function getStoredSignature(uint256 index) external view returns (bytes memory) {\n return _storedSignatures[index];\n }\n\n // ══════════════════════════════════════════════ INTERNAL LOGIC ═══════════════════════════════════════════════════\n\n /// @dev Saves the statement reported by Guard as invalid and the Guard Report signature.\n function _saveReport(bytes memory statementPayload, bytes memory reportSignature) internal {\n uint256 sigIndex = _saveSignature(reportSignature);\n _storedReports.push(StoredReport(sigIndex, statementPayload));\n }\n\n /// @dev Saves the signature and returns its index.\n function _saveSignature(bytes memory signature) internal returns (uint256 sigIndex) {\n sigIndex = _storedSignatures.length;\n _storedSignatures.push(signature);\n }\n\n // ═══════════════════════════════════════════════ AGENT CHECKS ════════════════════════════════════════════════════\n\n /**\n * @dev Recovers a signer from a hashed message, and a EIP-191 signature for it.\n * Will revert, if the signer is not a known agent.\n * @dev Agent flag could be any of these: Active/Unstaking/Resting/Fraudulent/Slashed\n * Further checks need to be performed in a caller function.\n * @param hashedStatement Hash of the statement that was signed by an Agent\n * @param signature Agent signature for the hashed statement\n * @return status Struct representing agent status:\n * - flag Unknown/Active/Unstaking/Resting/Fraudulent/Slashed\n * - domain Domain where agent is/was active\n * - index Index of agent in the Agent Merkle Tree\n * @return agent Agent that signed the statement\n */\n function _recoverAgent(bytes32 hashedStatement, bytes memory signature)\n internal\n view\n returns (AgentStatus memory status, address agent)\n {\n bytes32 ethSignedMsg = ECDSA.toEthSignedMessageHash(hashedStatement);\n agent = ECDSA.recover(ethSignedMsg, signature);\n status = IAgentManager(agentManager).agentStatus(agent);\n // Discard signature of unknown agents.\n // Further flag checks are supposed to be performed in a caller function.\n status.verifyKnown();\n }\n\n /// @dev Verifies that Notary signature is active on local domain.\n function _verifyNotaryDomain(uint32 notaryDomain) internal view {\n // Notary needs to be from the local domain (if contract is not deployed on Synapse Chain).\n // Or Notary could be from any domain (if contract is deployed on Synapse Chain).\n if (notaryDomain != localDomain \u0026\u0026 localDomain != synapseDomain) revert IncorrectAgentDomain();\n }\n\n // ════════════════════════════════════════ ATTESTATION RELATED CHECKS ═════════════════════════════════════════════\n\n /**\n * @dev Internal function to verify the signed attestation payload.\n * Reverts if any of these is true:\n * - Attestation signer is not a known Notary.\n * @param att Typed memory view over attestation payload\n * @param attSignature Notary signature for the attestation\n * @return status Struct representing agent status, see {_recoverAgent}\n * @return notary Notary that signed the snapshot\n */\n function _verifyAttestation(Attestation att, bytes memory attSignature)\n internal\n view\n returns (AgentStatus memory status, address notary)\n {\n // This will revert if signer is not a known agent\n (status, notary) = _recoverAgent(att.hashValid(), attSignature);\n // Attestation signer needs to be a Notary, not a Guard\n if (status.domain == 0) revert AgentNotNotary();\n }\n\n /**\n * @dev Internal function to verify the signed attestation report payload.\n * Reverts if any of these is true:\n * - Report signer is not a known Guard.\n * @param att Typed memory view over attestation payload that Guard reports as invalid\n * @param arSignature Guard signature for the \"invalid attestation\" report\n * @return status Struct representing guard status, see {_recoverAgent}\n * @return guard Guard that signed the report\n */\n function _verifyAttestationReport(Attestation att, bytes memory arSignature)\n internal\n view\n returns (AgentStatus memory status, address guard)\n {\n // This will revert if signer is not a known agent\n (status, guard) = _recoverAgent(att.hashInvalid(), arSignature);\n // Report signer needs to be a Guard, not a Notary\n if (status.domain != 0) revert AgentNotGuard();\n }\n\n // ══════════════════════════════════════════ RECEIPT RELATED CHECKS ═══════════════════════════════════════════════\n\n /**\n * @dev Internal function to verify the signed receipt payload.\n * Reverts if any of these is true:\n * - Receipt signer is not a known Notary.\n * @param rcpt Typed memory view over receipt payload\n * @param rcptSignature Notary signature for the receipt\n * @return status Struct representing agent status, see {_recoverAgent}\n * @return notary Notary that signed the snapshot\n */\n function _verifyReceipt(Receipt rcpt, bytes memory rcptSignature)\n internal\n view\n returns (AgentStatus memory status, address notary)\n {\n // This will revert if signer is not a known agent\n (status, notary) = _recoverAgent(rcpt.hashValid(), rcptSignature);\n // Receipt signer needs to be a Notary, not a Guard\n if (status.domain == 0) revert AgentNotNotary();\n }\n\n /**\n * @dev Internal function to verify the signed receipt report payload.\n * Reverts if any of these is true:\n * - Report signer is not a known Guard.\n * @param rcpt Typed memory view over receipt payload that Guard reports as invalid\n * @param rrSignature Guard signature for the \"invalid receipt\" report\n * @return status Struct representing guard status, see {_recoverAgent}\n * @return guard Guard that signed the report\n */\n function _verifyReceiptReport(Receipt rcpt, bytes memory rrSignature)\n internal\n view\n returns (AgentStatus memory status, address guard)\n {\n // This will revert if signer is not a known agent\n (status, guard) = _recoverAgent(rcpt.hashInvalid(), rrSignature);\n // Report signer needs to be a Guard, not a Notary\n if (status.domain != 0) revert AgentNotGuard();\n }\n\n // ═══════════════════════════════════════ STATE/SNAPSHOT RELATED CHECKS ═══════════════════════════════════════════\n\n /**\n * @dev Internal function to verify the signed snapshot report payload.\n * Reverts if any of these is true:\n * - Report signer is not a known Guard.\n * @param state Typed memory view over state payload that Guard reports as invalid\n * @param srSignature Guard signature for the report\n * @return status Struct representing guard status, see {_recoverAgent}\n * @return guard Guard that signed the report\n */\n function _verifyStateReport(State state, bytes memory srSignature)\n internal\n view\n returns (AgentStatus memory status, address guard)\n {\n // This will revert if signer is not a known agent\n (status, guard) = _recoverAgent(state.hashInvalid(), srSignature);\n // Report signer needs to be a Guard, not a Notary\n if (status.domain != 0) revert AgentNotGuard();\n }\n\n /**\n * @dev Internal function to verify the signed snapshot payload.\n * Reverts if any of these is true:\n * - Snapshot signer is not a known Agent.\n * - Snapshot signer is not a Notary (if verifyNotary is true).\n * @param snapshot Typed memory view over snapshot payload\n * @param snapSignature Agent signature for the snapshot\n * @param verifyNotary If true, snapshot signer needs to be a Notary, not a Guard\n * @return status Struct representing agent status, see {_recoverAgent}\n * @return agent Agent that signed the snapshot\n */\n function _verifySnapshot(Snapshot snapshot, bytes memory snapSignature, bool verifyNotary)\n internal\n view\n returns (AgentStatus memory status, address agent)\n {\n // This will revert if signer is not a known agent\n (status, agent) = _recoverAgent(snapshot.hashValid(), snapSignature);\n // If requested, snapshot signer needs to be a Notary, not a Guard\n if (verifyNotary \u0026\u0026 status.domain == 0) revert AgentNotNotary();\n }\n\n // ═══════════════════════════════════════════ MERKLE RELATED CHECKS ═══════════════════════════════════════════════\n\n /**\n * @dev Internal function to verify that snapshot roots match.\n * Reverts if any of these is true:\n * - Attestation root is not equal to Merkle Root derived from State and Snapshot Proof.\n * - Snapshot Proof's first element does not match the State metadata.\n * - Snapshot Proof length exceeds Snapshot tree Height.\n * - State index is out of range.\n * @param att Typed memory view over Attestation\n * @param stateIndex Index of state in the snapshot\n * @param state Typed memory view over the provided state payload\n * @param snapProof Raw payload with snapshot data\n */\n function _verifySnapshotMerkle(Attestation att, uint8 stateIndex, State state, bytes32[] memory snapProof)\n internal\n pure\n {\n // Snapshot proof first element should match State metadata (aka \"right sub-leaf\")\n (, bytes32 rightSubLeaf) = state.subLeafs();\n if (snapProof[0] != rightSubLeaf) revert IncorrectSnapshotProof();\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(state.root(), state.origin(), snapProof, stateIndex);\n // Snapshot root should match the attestation root\n if (att.snapRoot() != snapshotRoot) revert IncorrectSnapshotRoot();\n }\n}\n\n// contracts/inbox/Inbox.sol\n\n// ══════════════════════════════ LIBRARY IMPORTS ══════════════════════════════\n\n// ═════════════════════════════ INTERNAL IMPORTS ══════════════════════════════\n\n/// @notice `Inbox` is the child of `StatementInbox` contract, that is used on Synapse Chain.\n/// In addition to the functionality of `StatementInbox`, it also:\n/// - Accepts Guard and Notary Snapshots and passes them to `Summit` contract.\n/// - Accepts Notary-signed Receipts and passes them to `Summit` contract.\n/// - Accepts Receipt Reports to initiate a dispute between Guard and Notary.\n/// - Verifies Attestations and Attestation Reports, and slashes the signer if they are invalid.\ncontract Inbox is StatementInbox, InboxEvents, InterfaceInbox {\n using AttestationLib for bytes;\n using ReceiptLib for bytes;\n using SnapshotLib for bytes;\n\n // Struct to get around stack too deep error. TODO: revisit this\n struct ReceiptInfo {\n AgentStatus rcptNotaryStatus;\n address notary;\n uint32 attNonce;\n AgentStatus attNotaryStatus;\n }\n\n // ══════════════════════════════════════════════════ STORAGE ══════════════════════════════════════════════════════\n\n // The address of the Summit contract.\n address public summit;\n\n // ═════════════════════════════════════════ CONSTRUCTOR \u0026 INITIALIZER ═════════════════════════════════════════════\n\n constructor(uint32 synapseDomain_) MessagingBase(\"0.0.3\", synapseDomain_) {\n if (localDomain != synapseDomain) revert MustBeSynapseDomain();\n }\n\n /// @notice Initializes `Inbox` contract:\n /// - Sets `msg.sender` as the owner of the contract\n /// - Sets `agentManager`, `origin`, `destination` and `summit` addresses\n function initialize(address agentManager_, address origin_, address destination_, address summit_)\n external\n initializer\n {\n __StatementInbox_init(agentManager_, origin_, destination_);\n summit = summit_;\n }\n\n // ══════════════════════════════════════════ SUBMIT AGENT STATEMENTS ══════════════════════════════════════════════\n\n /// @inheritdoc InterfaceInbox\n function submitSnapshot(bytes memory snapPayload, bytes memory snapSignature)\n external\n returns (bytes memory attPayload, bytes32 agentRoot_, uint256[] memory snapGas)\n {\n // This will revert if payload is not a snapshot\n Snapshot snapshot = snapPayload.castToSnapshot();\n // This will revert if the signer is not a known Guard/Notary\n (AgentStatus memory status, address agent) =\n _verifySnapshot({snapshot: snapshot, snapSignature: snapSignature, verifyNotary: false});\n // Check that Agent is active\n status.verifyActive();\n // Store Agent signature for the Snapshot\n uint256 sigIndex = _saveSignature(snapSignature);\n if (status.domain == 0) {\n // Guard that is in Dispute could still submit new snapshots, so we don't check that\n InterfaceSummit(summit).acceptGuardSnapshot({\n guardIndex: status.index,\n sigIndex: sigIndex,\n snapPayload: snapPayload\n });\n } else {\n // Get current agentRoot from AgentManager\n agentRoot_ = IAgentManager(agentManager).agentRoot();\n // This will revert if Notary is in Dispute\n attPayload = InterfaceSummit(summit).acceptNotarySnapshot({\n notaryIndex: status.index,\n sigIndex: sigIndex,\n agentRoot: agentRoot_,\n snapPayload: snapPayload\n });\n ChainGas[] memory snapGas_ = snapshot.snapGas();\n // Pass created attestation to Destination to enable executing messages coming to Synapse Chain\n InterfaceDestination(destination).acceptAttestation(\n status.index, type(uint256).max, attPayload, agentRoot_, snapGas_\n );\n // Use assembly to cast ChainGas[] to uint256[] without copying. Highest bits are left zeroed.\n // solhint-disable-next-line no-inline-assembly\n assembly {\n snapGas := snapGas_\n }\n }\n emit SnapshotAccepted(status.domain, agent, snapPayload, snapSignature);\n }\n\n /// @inheritdoc InterfaceInbox\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 // Struct to get around stack too deep error.\n ReceiptInfo memory info;\n // This will revert if payload is not a receipt\n Receipt rcpt = rcptPayload.castToReceipt();\n // This will revert if the receipt signer is not a known Notary\n (info.rcptNotaryStatus, info.notary) = _verifyReceipt(rcpt, rcptSignature);\n // Receipt Notary needs to be Active\n info.rcptNotaryStatus.verifyActive();\n info.attNonce = IExecutionHub(destination).getAttestationNonce(rcpt.snapshotRoot());\n if (info.attNonce == 0) revert IncorrectSnapshotRoot();\n // Attestation Notary domain needs to match the destination domain\n info.attNotaryStatus = IAgentManager(agentManager).agentStatus(rcpt.attNotary());\n if (info.attNotaryStatus.domain != rcpt.destination()) revert IncorrectAgentDomain();\n // Check that the correct tip values for the message were provided\n _verifyReceiptTips(rcpt.messageHash(), paddedTips, headerHash, bodyHash);\n // Store Notary signature for the Receipt\n uint256 sigIndex = _saveSignature(rcptSignature);\n // This will revert if Receipt Notary is in Dispute\n wasAccepted = InterfaceSummit(summit).acceptReceipt({\n rcptNotaryIndex: info.rcptNotaryStatus.index,\n attNotaryIndex: info.attNotaryStatus.index,\n sigIndex: sigIndex,\n attNonce: info.attNonce,\n paddedTips: paddedTips,\n rcptPayload: rcptPayload\n });\n if (wasAccepted) {\n emit ReceiptAccepted(info.rcptNotaryStatus.domain, info.notary, rcptPayload, rcptSignature);\n }\n }\n\n /// @inheritdoc InterfaceInbox\n function submitReceiptReport(bytes memory rcptPayload, bytes memory rcptSignature, bytes memory rrSignature)\n external\n returns (bool wasAccepted)\n {\n // This will revert if payload is not a receipt\n Receipt rcpt = rcptPayload.castToReceipt();\n // This will revert if the receipt signer is not a known Guard\n (AgentStatus memory guardStatus,) = _verifyReceiptReport(rcpt, rrSignature);\n // Guard needs to be Active\n guardStatus.verifyActive();\n // This will revert if report signer is not a known Notary\n (AgentStatus memory notaryStatus,) = _verifyReceipt(rcpt, rcptSignature);\n // Notary needs to be Active/Unstaking\n notaryStatus.verifyActiveUnstaking();\n _saveReport(rcptPayload, rrSignature);\n // This will revert if either actor is already in dispute\n IAgentManager(agentManager).openDispute(guardStatus.index, notaryStatus.index);\n return true;\n }\n\n /// @inheritdoc InterfaceInbox\n function passReceipt(uint32 attNotaryIndex, uint32 attNonce, uint256 paddedTips, bytes memory rcptPayload)\n external\n returns (bool wasAccepted)\n {\n // Only Destination can pass receipts\n if (msg.sender != destination) revert CallerNotDestination();\n return InterfaceSummit(summit).acceptReceipt({\n rcptNotaryIndex: attNotaryIndex,\n attNotaryIndex: attNotaryIndex,\n sigIndex: type(uint256).max,\n attNonce: attNonce,\n paddedTips: paddedTips,\n rcptPayload: rcptPayload\n });\n }\n\n // ══════════════════════════════════════════ VERIFY AGENT STATEMENTS ══════════════════════════════════════════════\n\n /// @inheritdoc InterfaceInbox\n function verifyAttestation(bytes memory attPayload, bytes memory attSignature)\n external\n returns (bool isValidAttestation)\n {\n // This will revert if payload is not an attestation\n Attestation att = attPayload.castToAttestation();\n // This will revert if the attestation signer is not a known Notary\n (AgentStatus memory status, address notary) = _verifyAttestation(att, attSignature);\n // Notary needs to be Active/Unstaking\n status.verifyActiveUnstaking();\n isValidAttestation = ISnapshotHub(summit).isValidAttestation(attPayload);\n if (!isValidAttestation) {\n emit InvalidAttestation(attPayload, attSignature);\n IAgentManager(agentManager).slashAgent(status.domain, notary, msg.sender);\n }\n }\n\n /// @inheritdoc InterfaceInbox\n function verifyAttestationReport(bytes memory attPayload, bytes memory arSignature)\n external\n returns (bool isValidReport)\n {\n // This will revert if payload is not an attestation\n Attestation att = attPayload.castToAttestation();\n // This will revert if the report signer is not a known Guard\n (AgentStatus memory status, address guard) = _verifyAttestationReport(att, arSignature);\n // Guard needs to be Active/Unstaking\n status.verifyActiveUnstaking();\n // Report is valid IF AND ONLY IF the reported attestation in invalid\n isValidReport = !ISnapshotHub(summit).isValidAttestation(attPayload);\n if (!isValidReport) {\n emit InvalidAttestationReport(attPayload, arSignature);\n IAgentManager(agentManager).slashAgent(status.domain, guard, msg.sender);\n }\n }\n\n // ══════════════════════════════════════════════ INTERNAL VIEWS ═══════════════════════════════════════════════════\n\n /// @dev Verifies that tips proof matches the message hash.\n function _verifyReceiptTips(bytes32 msgHash, uint256 paddedTips, bytes32 headerHash, bytes32 bodyHash)\n internal\n pure\n {\n Tips tips = TipsLib.wrapPadded(paddedTips);\n // full message leaf is (header, baseMessage), while base message leaf is (tips, remainingBody).\n if (MerkleMath.getParent(headerHash, MerkleMath.getParent(tips.leaf(), bodyHash)) != msgHash) {\n revert IncorrectTipsProof();\n }\n }\n}\n","language":"Solidity","languageVersion":"0.8.17","compilerVersion":"0.8.17","compilerOptions":"--combined-json bin,bin-runtime,srcmap,srcmap-runtime,abi,userdoc,devdoc,metadata,hashes --optimize --optimize-runs 10000 --allow-paths ., ./, ../","srcMap":"","srcMapRuntime":"","abiDefinition":[{"inputs":[{"components":[{"internalType":"bool","name":"allowFailure","type":"bool"},{"internalType":"bytes","name":"callData","type":"bytes"}],"internalType":"struct MultiCallable.Call[]","name":"calls","type":"tuple[]"}],"name":"multicall","outputs":[{"components":[{"internalType":"bool","name":"success","type":"bool"},{"internalType":"bytes","name":"returnData","type":"bytes"}],"internalType":"struct MultiCallable.Result[]","name":"callResults","type":"tuple[]"}],"stateMutability":"nonpayable","type":"function"}],"userDoc":{"kind":"user","methods":{"multicall((bool,bytes)[])":{"notice":"Aggregates a few calls to this contract into one multicall without modifying `msg.sender`."}},"notice":"Collection of Multicall utilities. Fork of Multicall3: https://github.com/mds1/multicall/blob/master/src/Multicall3.sol","version":1},"developerDoc":{"kind":"dev","methods":{},"version":1},"metadata":"{\"compiler\":{\"version\":\"0.8.17+commit.8df45f5f\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"components\":[{\"internalType\":\"bool\",\"name\":\"allowFailure\",\"type\":\"bool\"},{\"internalType\":\"bytes\",\"name\":\"callData\",\"type\":\"bytes\"}],\"internalType\":\"struct MultiCallable.Call[]\",\"name\":\"calls\",\"type\":\"tuple[]\"}],\"name\":\"multicall\",\"outputs\":[{\"components\":[{\"internalType\":\"bool\",\"name\":\"success\",\"type\":\"bool\"},{\"internalType\":\"bytes\",\"name\":\"returnData\",\"type\":\"bytes\"}],\"internalType\":\"struct MultiCallable.Result[]\",\"name\":\"callResults\",\"type\":\"tuple[]\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{\"multicall((bool,bytes)[])\":{\"notice\":\"Aggregates a few calls to this contract into one multicall without modifying `msg.sender`.\"}},\"notice\":\"Collection of Multicall utilities. Fork of Multicall3: https://github.com/mds1/multicall/blob/master/src/Multicall3.sol\",\"version\":1}},\"settings\":{\"compilationTarget\":{\"solidity/Inbox.sol\":\"MultiCallable\"},\"evmVersion\":\"london\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\"},\"optimizer\":{\"enabled\":true,\"runs\":10000},\"remappings\":[]},\"sources\":{\"solidity/Inbox.sol\":{\"keccak256\":\"0x9b516081a036814c0169e20e484d4a5499066b7a6f48fada952b5e844a1ca3e5\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://32bde393b3f24ef4307d9626d4143f337b3c0bd34e17bb969fd5a15221d96987\",\"dweb:/ipfs/QmTkt2XZRtgsbSpmsVQUM3c4ebETQoDVYbmEV9yheBghnr\"]}},\"version\":1}"},"hashes":{"multicall((bool,bytes)[])":"60fc8466"}},"solidity/Inbox.sol:NumberLib":{"code":"0x60566037600b82828239805160001a607314602a57634e487b7160e01b600052600060045260246000fd5b30600052607381538281f3fe73000000000000000000000000000000000000000030146080604052600080fdfea2646970667358221220494ec8d8fefa1f2e7fc262752709a99895361f6d5439e2aabbfa16e0e02aa75064736f6c63430008110033","runtime-code":"0x73000000000000000000000000000000000000000030146080604052600080fdfea2646970667358221220494ec8d8fefa1f2e7fc262752709a99895361f6d5439e2aabbfa16e0e02aa75064736f6c63430008110033","info":{"source":"// SPDX-License-Identifier: MIT\npragma solidity =0.8.17 ^0.8.0 ^0.8.1 ^0.8.2;\n\n// contracts/events/InboxEvents.sol\n\nabstract contract InboxEvents {\n /**\n * @notice Emitted when a snapshot is accepted by the Summit contract.\n * @param domain Domain where the signed Agent is active (ZERO for Guards)\n * @param agent Agent who signed the snapshot\n * @param snapPayload Raw payload with snapshot data\n * @param snapSignature Agent signature for the snapshot\n */\n event SnapshotAccepted(uint32 indexed domain, address indexed agent, bytes snapPayload, bytes snapSignature);\n\n /**\n * @notice Emitted when a snapshot is accepted by the Summit contract.\n * @param domain Domain where the signed Notary is active\n * @param notary Notary who signed the attestation\n * @param rcptPayload Raw payload with receipt data\n * @param rcptSignature Notary signature for the receipt\n */\n event ReceiptAccepted(uint32 domain, address notary, bytes rcptPayload, bytes rcptSignature);\n\n /**\n * @notice Emitted when a proof of invalid attestation is submitted.\n * @param attPayload Raw payload with Attestation data\n * @param attSignature Notary signature for the attestation\n */\n event InvalidAttestation(bytes attPayload, bytes attSignature);\n\n /**\n * @notice Emitted when a proof of invalid attestation report is submitted.\n * @param arPayload Raw payload with report data\n * @param arSignature Guard signature for the report\n */\n event InvalidAttestationReport(bytes arPayload, bytes arSignature);\n}\n\n// contracts/events/StatementInboxEvents.sol\n\nabstract contract StatementInboxEvents {\n // ════════════════════════════════════════════ STATEMENT ACCEPTED ═════════════════════════════════════════════════\n\n /**\n * @notice Emitted when a snapshot is accepted by the Destination contract.\n * @param domain Domain where the signed Notary is active\n * @param notary Notary who signed the attestation\n * @param attPayload Raw payload with attestation data\n * @param attSignature Notary signature for the attestation\n */\n event AttestationAccepted(uint32 domain, address notary, bytes attPayload, bytes attSignature);\n\n // ═════════════════════════════════════════ INVALID STATEMENT PROVED ══════════════════════════════════════════════\n\n /**\n * @notice Emitted when a proof of invalid receipt statement is submitted.\n * @param rcptPayload Raw payload with the receipt statement\n * @param rcptSignature Notary signature for the receipt statement\n */\n event InvalidReceipt(bytes rcptPayload, bytes rcptSignature);\n\n /**\n * @notice Emitted when a proof of invalid receipt report is submitted.\n * @param rrPayload Raw payload with report data\n * @param rrSignature Guard signature for the report\n */\n event InvalidReceiptReport(bytes rrPayload, bytes rrSignature);\n\n /**\n * @notice Emitted when a proof of invalid state in the signed attestation is submitted.\n * @param stateIndex Index of invalid state in the snapshot\n * @param statePayload Raw payload with state data\n * @param attPayload Raw payload with Attestation data for snapshot\n * @param attSignature Notary signature for the attestation\n */\n event InvalidStateWithAttestation(uint8 stateIndex, bytes statePayload, bytes attPayload, bytes attSignature);\n\n /**\n * @notice Emitted when a proof of invalid state in the signed snapshot is submitted.\n * @param stateIndex Index of invalid state in the snapshot\n * @param snapPayload Raw payload with snapshot data\n * @param snapSignature Agent signature for the snapshot\n */\n event InvalidStateWithSnapshot(uint8 stateIndex, bytes snapPayload, bytes snapSignature);\n\n /**\n * @notice Emitted when a proof of invalid state report is submitted.\n * @param srPayload Raw payload with report data\n * @param srSignature Guard signature for the report\n */\n event InvalidStateReport(bytes srPayload, bytes srSignature);\n}\n\n// contracts/interfaces/ISnapshotHub.sol\n\ninterface ISnapshotHub {\n /**\n * @notice Check that a given attestation is valid: matches the historical attestation\n * derived from an accepted Notary snapshot.\n * @dev Will revert if any of these is true:\n * - Attestation payload is not properly formatted.\n * @param attPayload Raw payload with attestation data\n * @return isValid Whether the provided attestation is valid\n */\n function isValidAttestation(bytes memory attPayload) external view returns (bool isValid);\n\n /**\n * @notice Returns saved attestation with the given nonce.\n * @dev Reverts if attestation with given nonce hasn't been created yet.\n * @param attNonce Nonce for the attestation\n * @return attPayload Raw payload with formatted Attestation data\n * @return agentRoot Agent root hash used for the attestation\n * @return snapGas Snapshot gas data used for the attestation\n */\n function getAttestation(uint32 attNonce)\n external\n view\n returns (bytes memory attPayload, bytes32 agentRoot, uint256[] memory snapGas);\n\n /**\n * @notice Returns the state with the highest known nonce submitted by a given Agent.\n * @param origin Domain of origin chain\n * @param agent Agent address\n * @return statePayload Raw payload with agent's latest state for origin\n */\n function getLatestAgentState(uint32 origin, address agent) external view returns (bytes memory statePayload);\n\n /**\n * @notice Returns latest saved attestation for a Notary.\n * @param notary Notary address\n * @return attPayload Raw payload with formatted Attestation data\n * @return agentRoot Agent root hash used for the attestation\n * @return snapGas Snapshot gas data used for the attestation\n */\n function getLatestNotaryAttestation(address notary)\n external\n view\n returns (bytes memory attPayload, bytes32 agentRoot, uint256[] memory snapGas);\n\n /**\n * @notice Returns Guard snapshot from the list of all accepted Guard snapshots.\n * @dev Reverts if snapshot with given index hasn't been accepted yet.\n * @param index Snapshot index in the list of all Guard snapshots\n * @return snapPayload Raw payload with Guard snapshot\n * @return snapSignature Raw payload with Guard signature for snapshot\n */\n function getGuardSnapshot(uint256 index)\n external\n view\n returns (bytes memory snapPayload, bytes memory snapSignature);\n\n /**\n * @notice Returns Notary snapshot from the list of all accepted Guard snapshots.\n * @dev Reverts if snapshot with given index hasn't been accepted yet.\n * @param index Snapshot index in the list of all Notary snapshots\n * @return snapPayload Raw payload with Notary snapshot\n * @return snapSignature Raw payload with Notary signature for snapshot\n */\n function getNotarySnapshot(uint256 index)\n external\n view\n returns (bytes memory snapPayload, bytes memory snapSignature);\n\n /**\n * @notice Returns Notary snapshot that was used for creating a given attestation.\n * @dev Reverts if any of these is true:\n * - Attestation payload is not properly formatted.\n * - Attestation is invalid (doesn't have a matching Notary snapshot).\n * @param attPayload Raw payload with attestation data\n * @return snapPayload Raw payload with Notary snapshot\n * @return snapSignature Raw payload with Notary signature for snapshot\n */\n function getNotarySnapshot(bytes memory attPayload)\n external\n view\n returns (bytes memory snapPayload, bytes memory snapSignature);\n\n /**\n * @notice Returns proof of inclusion of (root, origin) fields of a given snapshot's state\n * into the Snapshot Merkle Tree for a given attestation.\n * @dev Reverts if any of these is true:\n * - Attestation with given nonce hasn't been created yet.\n * - State index is out of range of snapshot list.\n * @param attNonce Nonce for the attestation\n * @param stateIndex Index of state in the attestation's snapshot\n * @return snapProof The snapshot proof\n */\n function getSnapshotProof(uint32 attNonce, uint8 stateIndex) external view returns (bytes32[] memory snapProof);\n}\n\n// contracts/interfaces/IStateHub.sol\n\ninterface IStateHub {\n /**\n * @notice Check that a given state is valid: matches the historical state of Origin contract.\n * Note: any Agent including an invalid state in their snapshot will be slashed\n * upon providing the snapshot and agent signature for it to Origin contract.\n * @dev Will revert if any of these is true:\n * - State payload is not properly formatted.\n * @param statePayload Raw payload with state data\n * @return isValid Whether the provided state is valid\n */\n function isValidState(bytes memory statePayload) external view returns (bool isValid);\n\n /**\n * @notice Returns the amount of saved states so far.\n * @dev This includes the initial state of \"empty Origin Merkle Tree\".\n */\n function statesAmount() external view returns (uint256);\n\n /**\n * @notice Suggest the data (state after latest sent message) to sign for an Agent.\n * Note: signing the suggested state data will will never lead to slashing of the actor,\n * assuming they have confirmed that the block, which number is included in the data,\n * is not subject to reorganization (which is different for every observed chain).\n * @return statePayload Raw payload with the latest state data\n */\n function suggestLatestState() external view returns (bytes memory statePayload);\n\n /**\n * @notice Given the historical nonce, suggest the state data to sign for an Agent.\n * Note: signing the suggested state data will will never lead to slashing of the actor,\n * assuming they have confirmed that the block, which number is included in the data,\n * is not subject to reorganization (which is different for every observed chain).\n * @param nonce Historical nonce to form a state\n * @return statePayload Raw payload with historical state data\n */\n function suggestState(uint32 nonce) external view returns (bytes memory statePayload);\n}\n\n// contracts/interfaces/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/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// node_modules/@openzeppelin/contracts/utils/math/Math.sol\n\n// OpenZeppelin Contracts (last updated v4.9.0) (utils/math/Math.sol)\n\n/**\n * @dev Standard math utilities missing in the Solidity language.\n */\nlibrary Math {\n enum Rounding {\n Down, // Toward negative infinity\n Up, // Toward infinity\n Zero // Toward zero\n }\n\n /**\n * @dev Returns the largest of two numbers.\n */\n function max(uint256 a, uint256 b) internal pure returns (uint256) {\n return a \u003e b ? a : b;\n }\n\n /**\n * @dev Returns the smallest of two numbers.\n */\n function min(uint256 a, uint256 b) internal pure returns (uint256) {\n return a \u003c b ? a : b;\n }\n\n /**\n * @dev Returns the average of two numbers. The result is rounded towards\n * zero.\n */\n function average(uint256 a, uint256 b) internal pure returns (uint256) {\n // (a + b) / 2 can overflow.\n return (a \u0026 b) + (a ^ b) / 2;\n }\n\n /**\n * @dev Returns the ceiling of the division of two numbers.\n *\n * This differs from standard division with `/` in that it rounds up instead\n * of rounding down.\n */\n function ceilDiv(uint256 a, uint256 b) internal pure returns (uint256) {\n // (a + b - 1) / b can overflow on addition, so we distribute.\n return a == 0 ? 0 : (a - 1) / b + 1;\n }\n\n /**\n * @notice Calculates floor(x * y / denominator) with full precision. Throws if result overflows a uint256 or denominator == 0\n * @dev Original credit to Remco Bloemen under MIT license (https://xn--2-umb.com/21/muldiv)\n * with further edits by Uniswap Labs also under MIT license.\n */\n function mulDiv(uint256 x, uint256 y, uint256 denominator) internal pure returns (uint256 result) {\n unchecked {\n // 512-bit multiply [prod1 prod0] = x * y. Compute the product mod 2^256 and mod 2^256 - 1, then use\n // use the Chinese Remainder Theorem to reconstruct the 512 bit result. The result is stored in two 256\n // variables such that product = prod1 * 2^256 + prod0.\n uint256 prod0; // Least significant 256 bits of the product\n uint256 prod1; // Most significant 256 bits of the product\n assembly {\n let mm := mulmod(x, y, not(0))\n prod0 := mul(x, y)\n prod1 := sub(sub(mm, prod0), lt(mm, prod0))\n }\n\n // Handle non-overflow cases, 256 by 256 division.\n if (prod1 == 0) {\n // Solidity will revert if denominator == 0, unlike the div opcode on its own.\n // The surrounding unchecked block does not change this fact.\n // See https://docs.soliditylang.org/en/latest/control-structures.html#checked-or-unchecked-arithmetic.\n return prod0 / denominator;\n }\n\n // Make sure the result is less than 2^256. Also prevents denominator == 0.\n require(denominator \u003e prod1, \"Math: mulDiv overflow\");\n\n ///////////////////////////////////////////////\n // 512 by 256 division.\n ///////////////////////////////////////////////\n\n // Make division exact by subtracting the remainder from [prod1 prod0].\n uint256 remainder;\n assembly {\n // Compute remainder using mulmod.\n remainder := mulmod(x, y, denominator)\n\n // Subtract 256 bit number from 512 bit number.\n prod1 := sub(prod1, gt(remainder, prod0))\n prod0 := sub(prod0, remainder)\n }\n\n // Factor powers of two out of denominator and compute largest power of two divisor of denominator. Always \u003e= 1.\n // See https://cs.stackexchange.com/q/138556/92363.\n\n // Does not overflow because the denominator cannot be zero at this stage in the function.\n uint256 twos = denominator \u0026 (~denominator + 1);\n assembly {\n // Divide denominator by twos.\n denominator := div(denominator, twos)\n\n // Divide [prod1 prod0] by twos.\n prod0 := div(prod0, twos)\n\n // Flip twos such that it is 2^256 / twos. If twos is zero, then it becomes one.\n twos := add(div(sub(0, twos), twos), 1)\n }\n\n // Shift in bits from prod1 into prod0.\n prod0 |= prod1 * twos;\n\n // Invert denominator mod 2^256. Now that denominator is an odd number, it has an inverse modulo 2^256 such\n // that denominator * inv = 1 mod 2^256. Compute the inverse by starting with a seed that is correct for\n // four bits. That is, denominator * inv = 1 mod 2^4.\n uint256 inverse = (3 * denominator) ^ 2;\n\n // Use the Newton-Raphson iteration to improve the precision. Thanks to Hensel's lifting lemma, this also works\n // in modular arithmetic, doubling the correct bits in each step.\n inverse *= 2 - denominator * inverse; // inverse mod 2^8\n inverse *= 2 - denominator * inverse; // inverse mod 2^16\n inverse *= 2 - denominator * inverse; // inverse mod 2^32\n inverse *= 2 - denominator * inverse; // inverse mod 2^64\n inverse *= 2 - denominator * inverse; // inverse mod 2^128\n inverse *= 2 - denominator * inverse; // inverse mod 2^256\n\n // Because the division is now exact we can divide by multiplying with the modular inverse of denominator.\n // This will give us the correct result modulo 2^256. Since the preconditions guarantee that the outcome is\n // less than 2^256, this is the final result. We don't need to compute the high bits of the result and prod1\n // is no longer required.\n result = prod0 * inverse;\n return result;\n }\n }\n\n /**\n * @notice Calculates x * y / denominator with full precision, following the selected rounding direction.\n */\n function mulDiv(uint256 x, uint256 y, uint256 denominator, Rounding rounding) internal pure returns (uint256) {\n uint256 result = mulDiv(x, y, denominator);\n if (rounding == Rounding.Up \u0026\u0026 mulmod(x, y, denominator) \u003e 0) {\n result += 1;\n }\n return result;\n }\n\n /**\n * @dev Returns the square root of a number. If the number is not a perfect square, the value is rounded down.\n *\n * Inspired by Henry S. Warren, Jr.'s \"Hacker's Delight\" (Chapter 11).\n */\n function sqrt(uint256 a) internal pure returns (uint256) {\n if (a == 0) {\n return 0;\n }\n\n // For our first guess, we get the biggest power of 2 which is smaller than the square root of the target.\n //\n // We know that the \"msb\" (most significant bit) of our target number `a` is a power of 2 such that we have\n // `msb(a) \u003c= a \u003c 2*msb(a)`. This value can be written `msb(a)=2**k` with `k=log2(a)`.\n //\n // This can be rewritten `2**log2(a) \u003c= a \u003c 2**(log2(a) + 1)`\n // → `sqrt(2**k) \u003c= sqrt(a) \u003c sqrt(2**(k+1))`\n // → `2**(k/2) \u003c= sqrt(a) \u003c 2**((k+1)/2) \u003c= 2**(k/2 + 1)`\n //\n // Consequently, `2**(log2(a) / 2)` is a good first approximation of `sqrt(a)` with at least 1 correct bit.\n uint256 result = 1 \u003c\u003c (log2(a) \u003e\u003e 1);\n\n // At this point `result` is an estimation with one bit of precision. We know the true value is a uint128,\n // since it is the square root of a uint256. Newton's method converges quadratically (precision doubles at\n // every iteration). We thus need at most 7 iteration to turn our partial result with one bit of precision\n // into the expected uint128 result.\n unchecked {\n result = (result + a / result) \u003e\u003e 1;\n result = (result + a / result) \u003e\u003e 1;\n result = (result + a / result) \u003e\u003e 1;\n result = (result + a / result) \u003e\u003e 1;\n result = (result + a / result) \u003e\u003e 1;\n result = (result + a / result) \u003e\u003e 1;\n result = (result + a / result) \u003e\u003e 1;\n return min(result, a / result);\n }\n }\n\n /**\n * @notice Calculates sqrt(a), following the selected rounding direction.\n */\n function sqrt(uint256 a, Rounding rounding) internal pure returns (uint256) {\n unchecked {\n uint256 result = sqrt(a);\n return result + (rounding == Rounding.Up \u0026\u0026 result * result \u003c a ? 1 : 0);\n }\n }\n\n /**\n * @dev Return the log in base 2, rounded down, of a positive value.\n * Returns 0 if given 0.\n */\n function log2(uint256 value) internal pure returns (uint256) {\n uint256 result = 0;\n unchecked {\n if (value \u003e\u003e 128 \u003e 0) {\n value \u003e\u003e= 128;\n result += 128;\n }\n if (value \u003e\u003e 64 \u003e 0) {\n value \u003e\u003e= 64;\n result += 64;\n }\n if (value \u003e\u003e 32 \u003e 0) {\n value \u003e\u003e= 32;\n result += 32;\n }\n if (value \u003e\u003e 16 \u003e 0) {\n value \u003e\u003e= 16;\n result += 16;\n }\n if (value \u003e\u003e 8 \u003e 0) {\n value \u003e\u003e= 8;\n result += 8;\n }\n if (value \u003e\u003e 4 \u003e 0) {\n value \u003e\u003e= 4;\n result += 4;\n }\n if (value \u003e\u003e 2 \u003e 0) {\n value \u003e\u003e= 2;\n result += 2;\n }\n if (value \u003e\u003e 1 \u003e 0) {\n result += 1;\n }\n }\n return result;\n }\n\n /**\n * @dev Return the log in base 2, following the selected rounding direction, of a positive value.\n * Returns 0 if given 0.\n */\n function log2(uint256 value, Rounding rounding) internal pure returns (uint256) {\n unchecked {\n uint256 result = log2(value);\n return result + (rounding == Rounding.Up \u0026\u0026 1 \u003c\u003c result \u003c value ? 1 : 0);\n }\n }\n\n /**\n * @dev Return the log in base 10, rounded down, of a positive value.\n * Returns 0 if given 0.\n */\n function log10(uint256 value) internal pure returns (uint256) {\n uint256 result = 0;\n unchecked {\n if (value \u003e= 10 ** 64) {\n value /= 10 ** 64;\n result += 64;\n }\n if (value \u003e= 10 ** 32) {\n value /= 10 ** 32;\n result += 32;\n }\n if (value \u003e= 10 ** 16) {\n value /= 10 ** 16;\n result += 16;\n }\n if (value \u003e= 10 ** 8) {\n value /= 10 ** 8;\n result += 8;\n }\n if (value \u003e= 10 ** 4) {\n value /= 10 ** 4;\n result += 4;\n }\n if (value \u003e= 10 ** 2) {\n value /= 10 ** 2;\n result += 2;\n }\n if (value \u003e= 10 ** 1) {\n result += 1;\n }\n }\n return result;\n }\n\n /**\n * @dev Return the log in base 10, following the selected rounding direction, of a positive value.\n * Returns 0 if given 0.\n */\n function log10(uint256 value, Rounding rounding) internal pure returns (uint256) {\n unchecked {\n uint256 result = log10(value);\n return result + (rounding == Rounding.Up \u0026\u0026 10 ** result \u003c value ? 1 : 0);\n }\n }\n\n /**\n * @dev Return the log in base 256, rounded down, of a positive value.\n * Returns 0 if given 0.\n *\n * Adding one to the result gives the number of pairs of hex symbols needed to represent `value` as a hex string.\n */\n function log256(uint256 value) internal pure returns (uint256) {\n uint256 result = 0;\n unchecked {\n if (value \u003e\u003e 128 \u003e 0) {\n value \u003e\u003e= 128;\n result += 16;\n }\n if (value \u003e\u003e 64 \u003e 0) {\n value \u003e\u003e= 64;\n result += 8;\n }\n if (value \u003e\u003e 32 \u003e 0) {\n value \u003e\u003e= 32;\n result += 4;\n }\n if (value \u003e\u003e 16 \u003e 0) {\n value \u003e\u003e= 16;\n result += 2;\n }\n if (value \u003e\u003e 8 \u003e 0) {\n result += 1;\n }\n }\n return result;\n }\n\n /**\n * @dev Return the log in base 256, following the selected rounding direction, of a positive value.\n * Returns 0 if given 0.\n */\n function log256(uint256 value, Rounding rounding) internal pure returns (uint256) {\n unchecked {\n uint256 result = log256(value);\n return result + (rounding == Rounding.Up \u0026\u0026 1 \u003c\u003c (result \u003c\u003c 3) \u003c value ? 1 : 0);\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/utils/math/SignedMath.sol\n\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/math/SignedMath.sol)\n\n/**\n * @dev Standard signed math utilities missing in the Solidity language.\n */\nlibrary SignedMath {\n /**\n * @dev Returns the largest of two signed numbers.\n */\n function max(int256 a, int256 b) internal pure returns (int256) {\n return a \u003e b ? a : b;\n }\n\n /**\n * @dev Returns the smallest of two signed numbers.\n */\n function min(int256 a, int256 b) internal pure returns (int256) {\n return a \u003c b ? a : b;\n }\n\n /**\n * @dev Returns the average of two signed numbers without overflow.\n * The result is rounded towards zero.\n */\n function average(int256 a, int256 b) internal pure returns (int256) {\n // Formula from the book \"Hacker's Delight\"\n int256 x = (a \u0026 b) + ((a ^ b) \u003e\u003e 1);\n return x + (int256(uint256(x) \u003e\u003e 255) \u0026 (a ^ b));\n }\n\n /**\n * @dev Returns the absolute unsigned value of a signed value.\n */\n function abs(int256 n) internal pure returns (uint256) {\n unchecked {\n // must be unchecked in order to support `n = type(int256).min`\n return uint256(n \u003e= 0 ? n : -n);\n }\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// 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/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/InterfaceSummit.sol\n\ninterface InterfaceSummit {\n // ══════════════════════════════════════════ ACCEPT AGENT STATEMENTS ══════════════════════════════════════════════\n\n /**\n * @notice Accepts a receipt, which local `AgentManager` verified to have been signed by an active Notary.\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 * - Notary who signed the receipt is referenced as the \"Receipt Notary\".\n * - Notary who signed the attestation on destination chain is referenced as the \"Attestation Notary\".\n * \u003e Will revert if any of these is true:\n * \u003e - Called by anyone other than local `AgentManager`.\n * \u003e - Receipt body payload is not properly formatted.\n * \u003e - Receipt signer is in Dispute.\n * \u003e - Receipt's snapshot root is unknown.\n * @param rcptNotaryIndex Index of Receipt Notary in Agent Merkle Tree\n * @param attNotaryIndex Index of Attestation Notary in Agent Merkle Tree\n * @param sigIndex Index of stored Notary signature\n * @param attNonce Nonce of the attestation used for proving the executed message\n * @param paddedTips Padded encoded paid tips information\n * @param rcptPayload Raw payload with message execution receipt\n * @return wasAccepted Whether the receipt was accepted\n */\n function acceptReceipt(\n uint32 rcptNotaryIndex,\n uint32 attNotaryIndex,\n uint256 sigIndex,\n uint32 attNonce,\n uint256 paddedTips,\n bytes memory rcptPayload\n ) external returns (bool wasAccepted);\n\n /**\n * @notice Accepts a snapshot, which local `AgentManager` verified to have been signed by an active Guard.\n * \u003e Snapshot is a list of states for a set of Origin contracts residing on any of the chains.\n * All the states in the Guard-signed snapshot become available for Notary signing.\n * \u003e Will revert if any of these is true:\n * \u003e - Called by anyone other than local `AgentManager`.\n * \u003e - Snapshot payload is not properly formatted.\n * \u003e - Snapshot contains a state older then the Guard has previously submitted.\n * @param guardIndex Index of Guard in Agent Merkle Tree\n * @param sigIndex Index of stored Agent signature\n * @param snapPayload Raw payload with snapshot data\n */\n function acceptGuardSnapshot(uint32 guardIndex, uint256 sigIndex, bytes memory snapPayload) external;\n\n /**\n * @notice Accepts a snapshot, which local `AgentManager` verified to have been signed by an active Notary.\n * \u003e Snapshot is a list of states for a set of Origin contracts residing on any of the chains.\n * Snapshot Merkle Root is calculated and saved for valid snapshots, i.e.\n * snapshots which are only using states previously submitted by any of the Guards.\n * - Notary could use states singed by the same of different Guards 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 - Called by anyone other than local `AgentManager`.\n * \u003e - Snapshot payload is not properly formatted.\n * \u003e - Snapshot contains a state older then the Notary has previously submitted.\n * \u003e - Snapshot contains a state that no Guard has previously submitted.\n * @param notaryIndex Index of Notary in Agent Merkle Tree\n * @param sigIndex Index of stored Agent signature\n * @param agentRoot Current root of the Agent Merkle Tree\n * @param snapPayload Raw payload with snapshot data\n * @return attPayload Raw payload with data for attestation derived from Notary snapshot.\n */\n function acceptNotarySnapshot(uint32 notaryIndex, uint256 sigIndex, bytes32 agentRoot, bytes memory snapPayload)\n external\n returns (bytes memory attPayload);\n\n // ════════════════════════════════════════════════ TIPS LOGIC ═════════════════════════════════════════════════════\n\n /**\n * @notice Distributes tips using the first Receipt from the \"receipt quarantine queue\".\n * Possible scenarios:\n * - Receipt queue is empty =\u003e does nothing\n * - Receipt optimistic period is not over =\u003e does nothing\n * - Either of Notaries present in Receipt was slashed =\u003e receipt is deleted from the queue\n * - Either of Notaries present in Receipt in Dispute =\u003e receipt is moved to the end of queue\n * - None of the above =\u003e receipt tips are distributed\n * @dev Returned value makes it possible to do the following: `while (distributeTips()) {}`\n * @return queuePopped Whether the first element was popped from the queue\n */\n function distributeTips() external returns (bool queuePopped);\n\n /**\n * @notice Withdraws locked base message tips from requested domain Origin to the recipient.\n * This is done by a call to a local Origin contract, or by a manager message to the remote chain.\n * @dev This will revert, if the pending balance of origin tips (earned-claimed) is lower than requested.\n * @param origin Domain of chain to withdraw tips on\n * @param amount Amount of tips to withdraw\n */\n function withdrawTips(uint32 origin, uint256 amount) external;\n\n // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════\n\n /**\n * @notice Returns earned and claimed tips for the actor.\n * Note: Tips for address(0) belong to the Treasury.\n * @param actor Address of the actor\n * @param origin Domain where the tips were initially paid\n * @return earned Total amount of origin tips the actor has earned so far\n * @return claimed Total amount of origin tips the actor has claimed so far\n */\n function actorTips(address actor, uint32 origin) external view returns (uint128 earned, uint128 claimed);\n\n /**\n * @notice Returns the amount of receipts in the \"Receipt Quarantine Queue\".\n */\n function receiptQueueLength() external view returns (uint256);\n\n /**\n * @notice Returns the state with the highest known nonce\n * submitted by any of the currently active Guards.\n * @param origin Domain of origin chain\n * @return statePayload Raw payload with latest active Guard state for origin\n */\n function getLatestState(uint32 origin) external view returns (bytes memory statePayload);\n}\n\n// node_modules/@openzeppelin/contracts/utils/Strings.sol\n\n// OpenZeppelin Contracts (last updated v4.9.0) (utils/Strings.sol)\n\n/**\n * @dev String operations.\n */\nlibrary Strings {\n bytes16 private constant _SYMBOLS = \"0123456789abcdef\";\n uint8 private constant _ADDRESS_LENGTH = 20;\n\n /**\n * @dev Converts a `uint256` to its ASCII `string` decimal representation.\n */\n function toString(uint256 value) internal pure returns (string memory) {\n unchecked {\n uint256 length = Math.log10(value) + 1;\n string memory buffer = new string(length);\n uint256 ptr;\n /// @solidity memory-safe-assembly\n assembly {\n ptr := add(buffer, add(32, length))\n }\n while (true) {\n ptr--;\n /// @solidity memory-safe-assembly\n assembly {\n mstore8(ptr, byte(mod(value, 10), _SYMBOLS))\n }\n value /= 10;\n if (value == 0) break;\n }\n return buffer;\n }\n }\n\n /**\n * @dev Converts a `int256` to its ASCII `string` decimal representation.\n */\n function toString(int256 value) internal pure returns (string memory) {\n return string(abi.encodePacked(value \u003c 0 ? \"-\" : \"\", toString(SignedMath.abs(value))));\n }\n\n /**\n * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation.\n */\n function toHexString(uint256 value) internal pure returns (string memory) {\n unchecked {\n return toHexString(value, Math.log256(value) + 1);\n }\n }\n\n /**\n * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length.\n */\n function toHexString(uint256 value, uint256 length) internal pure returns (string memory) {\n bytes memory buffer = new bytes(2 * length + 2);\n buffer[0] = \"0\";\n buffer[1] = \"x\";\n for (uint256 i = 2 * length + 1; i \u003e 1; --i) {\n buffer[i] = _SYMBOLS[value \u0026 0xf];\n value \u003e\u003e= 4;\n }\n require(value == 0, \"Strings: hex length insufficient\");\n return string(buffer);\n }\n\n /**\n * @dev Converts an `address` with fixed length of 20 bytes to its not checksummed ASCII `string` hexadecimal representation.\n */\n function toHexString(address addr) internal pure returns (string memory) {\n return toHexString(uint256(uint160(addr)), _ADDRESS_LENGTH);\n }\n\n /**\n * @dev Returns true if the two strings are equal.\n */\n function equal(string memory a, string memory b) internal pure returns (bool) {\n return keccak256(bytes(a)) == keccak256(bytes(b));\n }\n}\n\n// node_modules/@openzeppelin/contracts-upgradeable/utils/ContextUpgradeable.sol\n\n// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)\n\n/**\n * @dev Provides information about the current execution context, including the\n * sender of the transaction and its data. While these are generally available\n * via msg.sender and msg.data, they should not be accessed in such a direct\n * manner, since when dealing with meta-transactions the account sending and\n * paying for execution may not be the actual sender (as far as an application\n * is concerned).\n *\n * This contract is only required for intermediate, library-like contracts.\n */\nabstract contract ContextUpgradeable is Initializable {\n function __Context_init() internal onlyInitializing {\n }\n\n function __Context_init_unchained() internal onlyInitializing {\n }\n function _msgSender() internal view virtual returns (address) {\n return msg.sender;\n }\n\n function _msgData() internal view virtual returns (bytes calldata) {\n return msg.data;\n }\n\n /**\n * @dev This empty reserved space is put in place to allow future versions to add new\n * variables without shifting down storage in the inheritance chain.\n * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\n */\n uint256[50] private __gap;\n}\n\n// contracts/libs/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/utils/cryptography/ECDSA.sol\n\n// OpenZeppelin Contracts (last updated v4.9.0) (utils/cryptography/ECDSA.sol)\n\n/**\n * @dev Elliptic Curve Digital Signature Algorithm (ECDSA) operations.\n *\n * These functions can be used to verify that a message was signed by the holder\n * of the private keys of a given address.\n */\nlibrary ECDSA {\n enum RecoverError {\n NoError,\n InvalidSignature,\n InvalidSignatureLength,\n InvalidSignatureS,\n InvalidSignatureV // Deprecated in v4.8\n }\n\n function _throwError(RecoverError error) private pure {\n if (error == RecoverError.NoError) {\n return; // no error: do nothing\n } else if (error == RecoverError.InvalidSignature) {\n revert(\"ECDSA: invalid signature\");\n } else if (error == RecoverError.InvalidSignatureLength) {\n revert(\"ECDSA: invalid signature length\");\n } else if (error == RecoverError.InvalidSignatureS) {\n revert(\"ECDSA: invalid signature 's' value\");\n }\n }\n\n /**\n * @dev Returns the address that signed a hashed message (`hash`) with\n * `signature` or error string. This address can then be used for verification purposes.\n *\n * The `ecrecover` EVM opcode allows for malleable (non-unique) signatures:\n * this function rejects them by requiring the `s` value to be in the lower\n * half order, and the `v` value to be either 27 or 28.\n *\n * IMPORTANT: `hash` _must_ be the result of a hash operation for the\n * verification to be secure: it is possible to craft signatures that\n * recover to arbitrary addresses for non-hashed data. A safe way to ensure\n * this is by receiving a hash of the original message (which may otherwise\n * be too long), and then calling {toEthSignedMessageHash} on it.\n *\n * Documentation for signature generation:\n * - with https://web3js.readthedocs.io/en/v1.3.4/web3-eth-accounts.html#sign[Web3.js]\n * - with https://docs.ethers.io/v5/api/signer/#Signer-signMessage[ethers]\n *\n * _Available since v4.3._\n */\n function tryRecover(bytes32 hash, bytes memory signature) internal pure returns (address, RecoverError) {\n if (signature.length == 65) {\n bytes32 r;\n bytes32 s;\n uint8 v;\n // ecrecover takes the signature parameters, and the only way to get them\n // currently is to use assembly.\n /// @solidity memory-safe-assembly\n assembly {\n r := mload(add(signature, 0x20))\n s := mload(add(signature, 0x40))\n v := byte(0, mload(add(signature, 0x60)))\n }\n return tryRecover(hash, v, r, s);\n } else {\n return (address(0), RecoverError.InvalidSignatureLength);\n }\n }\n\n /**\n * @dev Returns the address that signed a hashed message (`hash`) with\n * `signature`. This address can then be used for verification purposes.\n *\n * The `ecrecover` EVM opcode allows for malleable (non-unique) signatures:\n * this function rejects them by requiring the `s` value to be in the lower\n * half order, and the `v` value to be either 27 or 28.\n *\n * IMPORTANT: `hash` _must_ be the result of a hash operation for the\n * verification to be secure: it is possible to craft signatures that\n * recover to arbitrary addresses for non-hashed data. A safe way to ensure\n * this is by receiving a hash of the original message (which may otherwise\n * be too long), and then calling {toEthSignedMessageHash} on it.\n */\n function recover(bytes32 hash, bytes memory signature) internal pure returns (address) {\n (address recovered, RecoverError error) = tryRecover(hash, signature);\n _throwError(error);\n return recovered;\n }\n\n /**\n * @dev Overload of {ECDSA-tryRecover} that receives the `r` and `vs` short-signature fields separately.\n *\n * See https://eips.ethereum.org/EIPS/eip-2098[EIP-2098 short signatures]\n *\n * _Available since v4.3._\n */\n function tryRecover(bytes32 hash, bytes32 r, bytes32 vs) internal pure returns (address, RecoverError) {\n bytes32 s = vs \u0026 bytes32(0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff);\n uint8 v = uint8((uint256(vs) \u003e\u003e 255) + 27);\n return tryRecover(hash, v, r, s);\n }\n\n /**\n * @dev Overload of {ECDSA-recover} that receives the `r and `vs` short-signature fields separately.\n *\n * _Available since v4.2._\n */\n function recover(bytes32 hash, bytes32 r, bytes32 vs) internal pure returns (address) {\n (address recovered, RecoverError error) = tryRecover(hash, r, vs);\n _throwError(error);\n return recovered;\n }\n\n /**\n * @dev Overload of {ECDSA-tryRecover} that receives the `v`,\n * `r` and `s` signature fields separately.\n *\n * _Available since v4.3._\n */\n function tryRecover(bytes32 hash, uint8 v, bytes32 r, bytes32 s) internal pure returns (address, RecoverError) {\n // EIP-2 still allows signature malleability for ecrecover(). Remove this possibility and make the signature\n // unique. Appendix F in the Ethereum Yellow paper (https://ethereum.github.io/yellowpaper/paper.pdf), defines\n // the valid range for s in (301): 0 \u003c s \u003c secp256k1n ÷ 2 + 1, and for v in (302): v ∈ {27, 28}. Most\n // signatures from current libraries generate a unique signature with an s-value in the lower half order.\n //\n // If your library generates malleable signatures, such as s-values in the upper range, calculate a new s-value\n // with 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141 - s1 and flip v from 27 to 28 or\n // vice versa. If your library also generates signatures with 0/1 for v instead 27/28, add 27 to v to accept\n // these malleable signatures as well.\n if (uint256(s) \u003e 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0) {\n return (address(0), RecoverError.InvalidSignatureS);\n }\n\n // If the signature is valid (and not malleable), return the signer address\n address signer = ecrecover(hash, v, r, s);\n if (signer == address(0)) {\n return (address(0), RecoverError.InvalidSignature);\n }\n\n return (signer, RecoverError.NoError);\n }\n\n /**\n * @dev Overload of {ECDSA-recover} that receives the `v`,\n * `r` and `s` signature fields separately.\n */\n function recover(bytes32 hash, uint8 v, bytes32 r, bytes32 s) internal pure returns (address) {\n (address recovered, RecoverError error) = tryRecover(hash, v, r, s);\n _throwError(error);\n return recovered;\n }\n\n /**\n * @dev Returns an Ethereum Signed Message, created from a `hash`. This\n * produces hash corresponding to the one signed with the\n * https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`]\n * JSON-RPC method as part of EIP-191.\n *\n * See {recover}.\n */\n function toEthSignedMessageHash(bytes32 hash) internal pure returns (bytes32 message) {\n // 32 is the length in bytes of hash,\n // enforced by the type signature above\n /// @solidity memory-safe-assembly\n assembly {\n mstore(0x00, \"\\x19Ethereum Signed Message:\\n32\")\n mstore(0x1c, hash)\n message := keccak256(0x00, 0x3c)\n }\n }\n\n /**\n * @dev Returns an Ethereum Signed Message, created from `s`. This\n * produces hash corresponding to the one signed with the\n * https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`]\n * JSON-RPC method as part of EIP-191.\n *\n * See {recover}.\n */\n function toEthSignedMessageHash(bytes memory s) internal pure returns (bytes32) {\n return keccak256(abi.encodePacked(\"\\x19Ethereum Signed Message:\\n\", Strings.toString(s.length), s));\n }\n\n /**\n * @dev Returns an Ethereum Signed Typed Data, created from a\n * `domainSeparator` and a `structHash`. This produces hash corresponding\n * to the one signed with the\n * https://eips.ethereum.org/EIPS/eip-712[`eth_signTypedData`]\n * JSON-RPC method as part of EIP-712.\n *\n * See {recover}.\n */\n function toTypedDataHash(bytes32 domainSeparator, bytes32 structHash) internal pure returns (bytes32 data) {\n /// @solidity memory-safe-assembly\n assembly {\n let ptr := mload(0x40)\n mstore(ptr, \"\\x19\\x01\")\n mstore(add(ptr, 0x02), domainSeparator)\n mstore(add(ptr, 0x22), structHash)\n data := keccak256(ptr, 0x42)\n }\n }\n\n /**\n * @dev Returns an Ethereum Signed Data with intended validator, created from a\n * `validator` and `data` according to the version 0 of EIP-191.\n *\n * See {recover}.\n */\n function toDataWithIntendedValidatorHash(address validator, bytes memory data) internal pure returns (bytes32) {\n return keccak256(abi.encodePacked(\"\\x19\\x00\", validator, data));\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/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/inbox/StatementInbox.sol\n\n// ══════════════════════════════ LIBRARY IMPORTS ══════════════════════════════\n\n// ═════════════════════════════ INTERNAL IMPORTS ══════════════════════════════\n\n// ═════════════════════════════ EXTERNAL IMPORTS ══════════════════════════════\n\n/// @notice `StatementInbox` is the entry point for all agent-signed statements. It verifies the\n/// agent signatures, and passes the unsigned statements to the contract to consume it via `acceptX` functions. Is is\n/// also used to verify the agent-signed statements and initiate the agent slashing, should the statement be invalid.\n/// `StatementInbox` is responsible for the following:\n/// - Accepting State and Receipt Reports to initiate a dispute between Guard and Notary.\n/// - Storing all the Guard Reports with the Guard signature leading to a dispute.\n/// - Verifying State/State Reports referencing the local chain and slashing the signer if statement is invalid.\n/// - Verifying Receipt/Receipt Reports referencing the local chain and slashing the signer if statement is invalid.\nabstract contract StatementInbox is MessagingBase, StatementInboxEvents, IStatementInbox {\n using AttestationLib for bytes;\n using ReceiptLib for bytes;\n using StateLib for bytes;\n using SnapshotLib for bytes;\n\n struct StoredReport {\n uint256 sigIndex;\n bytes statementPayload;\n }\n\n // ══════════════════════════════════════════════════ STORAGE ══════════════════════════════════════════════════════\n\n address public agentManager;\n address public origin;\n address public destination;\n\n // TODO: optimize this\n bytes[] internal _storedSignatures;\n StoredReport[] internal _storedReports;\n\n /// @dev gap for upgrade safety\n uint256[45] private __GAP; // solhint-disable-line var-name-mixedcase\n\n // ════════════════════════════════════════════════ INITIALIZER ════════════════════════════════════════════════════\n\n /// @dev Initializes the contract:\n /// - Sets up `msg.sender` as the owner of the contract.\n /// - Sets up `agentManager`, `origin`, and `destination`.\n // solhint-disable-next-line func-name-mixedcase\n function __StatementInbox_init(address agentManager_, address origin_, address destination_)\n internal\n onlyInitializing\n {\n agentManager = agentManager_;\n origin = origin_;\n destination = destination_;\n __Ownable2Step_init();\n }\n\n // ══════════════════════════════════════════ SUBMIT AGENT STATEMENTS ══════════════════════════════════════════════\n\n /// @inheritdoc IStatementInbox\n // solhint-disable-next-line ordering\n function submitStateReportWithSnapshot(\n uint8 stateIndex,\n bytes memory srSignature,\n bytes memory snapPayload,\n bytes memory snapSignature\n ) external returns (bool wasAccepted) {\n // This will revert if payload is not a snapshot\n Snapshot snapshot = snapPayload.castToSnapshot();\n // This will revert if the snapshot signer is not a known Notary\n (AgentStatus memory notaryStatus,) =\n _verifySnapshot({snapshot: snapshot, snapSignature: snapSignature, verifyNotary: true});\n // Notary needs to be Active/Unstaking\n notaryStatus.verifyActiveUnstaking();\n // Check if Notary is active on this chain\n _verifyNotaryDomain(notaryStatus.domain);\n // This will revert if state index is out of range\n State state = snapshot.state(stateIndex);\n // This will revert if the report signer is not an known Guard\n (AgentStatus memory guardStatus,) = _verifyStateReport(state, srSignature);\n // Check that Guard is active\n guardStatus.verifyActive();\n _saveReport(state.unwrap().clone(), srSignature);\n // This will revert if either actor is already in dispute\n IAgentManager(agentManager).openDispute(guardStatus.index, notaryStatus.index);\n return true;\n }\n\n /// @inheritdoc IStatementInbox\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 // This will revert if payload is not a snapshot\n Snapshot snapshot = snapPayload.castToSnapshot();\n // This will revert if state index is out of range\n State state = snapshot.state(stateIndex);\n // This will revert if the report signer is not an known Guard\n (AgentStatus memory guardStatus,) = _verifyStateReport(state, srSignature);\n // Check that Guard is active\n guardStatus.verifyActive();\n // This will revert if payload is not an attestation\n Attestation att = attPayload.castToAttestation();\n // This will revert if signer is not an known Notary\n (AgentStatus memory notaryStatus,) = _verifyAttestation(att, attSignature);\n // Notary needs to be Active/Unstaking\n notaryStatus.verifyActiveUnstaking();\n // Check if Notary is active on this chain\n _verifyNotaryDomain(notaryStatus.domain);\n if (snapshot.calculateRoot() != att.snapRoot()) revert IncorrectSnapshotRoot();\n _saveReport(state.unwrap().clone(), srSignature);\n // This will revert if either actor is already in dispute\n IAgentManager(agentManager).openDispute(guardStatus.index, notaryStatus.index);\n return true;\n }\n\n /// @inheritdoc IStatementInbox\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 // This will revert if payload is not a state\n State state = statePayload.castToState();\n // This will revert if the report signer is not an known Guard\n (AgentStatus memory guardStatus,) = _verifyStateReport(state, srSignature);\n // Check that Guard is active\n guardStatus.verifyActive();\n // This will revert if payload is not an attestation\n Attestation att = attPayload.castToAttestation();\n // This will revert if signer is not a known Notary\n (AgentStatus memory notaryStatus,) = _verifyAttestation(att, attSignature);\n // Notary needs to be Active/Unstaking\n notaryStatus.verifyActiveUnstaking();\n // Check if Notary is active on this chain\n _verifyNotaryDomain(notaryStatus.domain);\n // This will revert if any of these is true:\n // - Attestation root is not equal to Merkle Root derived from State and Snapshot Proof.\n // - Snapshot Proof's first element does not match the State metadata.\n // - Snapshot Proof length exceeds Snapshot tree Height.\n // - State index is out of range.\n _verifySnapshotMerkle(att, stateIndex, state, snapProof);\n _saveReport(statePayload, srSignature);\n // This will revert if either actor is already in dispute\n IAgentManager(agentManager).openDispute(guardStatus.index, notaryStatus.index);\n return true;\n }\n\n // ══════════════════════════════════════════ VERIFY AGENT STATEMENTS ══════════════════════════════════════════════\n\n /// @inheritdoc IStatementInbox\n function verifyReceipt(bytes memory rcptPayload, bytes memory rcptSignature)\n external\n returns (bool isValidReceipt)\n {\n // This will revert if payload is not a receipt\n Receipt rcpt = rcptPayload.castToReceipt();\n // This will revert if the attestation signer is not a known Notary\n (AgentStatus memory status, address notary) = _verifyReceipt(rcpt, rcptSignature);\n // Notary needs to be Active/Unstaking\n status.verifyActiveUnstaking();\n isValidReceipt = IExecutionHub(destination).isValidReceipt(rcptPayload);\n if (!isValidReceipt) {\n emit InvalidReceipt(rcptPayload, rcptSignature);\n IAgentManager(agentManager).slashAgent(status.domain, notary, msg.sender);\n }\n }\n\n /// @inheritdoc IStatementInbox\n function verifyReceiptReport(bytes memory rcptPayload, bytes memory rrSignature)\n external\n returns (bool isValidReport)\n {\n // This will revert if payload is not a receipt\n Receipt rcpt = rcptPayload.castToReceipt();\n // This will revert if the report signer is not a known Guard\n (AgentStatus memory status, address guard) = _verifyReceiptReport(rcpt, rrSignature);\n // Guard needs to be Active/Unstaking\n status.verifyActiveUnstaking();\n // Report is valid IF AND ONLY IF the reported receipt in invalid\n isValidReport = !IExecutionHub(destination).isValidReceipt(rcptPayload);\n if (!isValidReport) {\n emit InvalidReceiptReport(rcptPayload, rrSignature);\n IAgentManager(agentManager).slashAgent(status.domain, guard, msg.sender);\n }\n }\n\n /// @inheritdoc IStatementInbox\n function verifyStateWithAttestation(\n uint8 stateIndex,\n bytes memory snapPayload,\n bytes memory attPayload,\n bytes memory attSignature\n ) external returns (bool isValidState) {\n // This will revert if payload is not an attestation\n Attestation att = attPayload.castToAttestation();\n // This will revert if the attestation signer is not a known Notary\n (AgentStatus memory status, address notary) = _verifyAttestation(att, attSignature);\n // Notary needs to be Active/Unstaking\n status.verifyActiveUnstaking();\n // This will revert if payload is not a snapshot\n Snapshot snapshot = snapPayload.castToSnapshot();\n if (snapshot.calculateRoot() != att.snapRoot()) revert IncorrectSnapshotRoot();\n // This will revert if state does not refer to this chain\n bytes memory statePayload = snapshot.state(stateIndex).unwrap().clone();\n isValidState = IStateHub(origin).isValidState(statePayload);\n if (!isValidState) {\n emit InvalidStateWithAttestation(stateIndex, statePayload, attPayload, attSignature);\n IAgentManager(agentManager).slashAgent(status.domain, notary, msg.sender);\n }\n }\n\n /// @inheritdoc IStatementInbox\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 // This will revert if payload is not an attestation\n Attestation att = attPayload.castToAttestation();\n // This will revert if the attestation signer is not a known Notary\n (AgentStatus memory status, address notary) = _verifyAttestation(att, attSignature);\n // Notary needs to be Active/Unstaking\n status.verifyActiveUnstaking();\n // This will revert if payload is not a state\n State state = statePayload.castToState();\n // This will revert if any of these is true:\n // - Attestation root is not equal to Merkle Root derived from State and Snapshot Proof.\n // - Snapshot Proof's first element does not match the State metadata.\n // - Snapshot Proof length exceeds Snapshot tree Height.\n // - State index is out of range.\n _verifySnapshotMerkle(att, stateIndex, state, snapProof);\n // This will revert if state does not refer to this chain\n isValidState = IStateHub(origin).isValidState(statePayload);\n if (!isValidState) {\n emit InvalidStateWithAttestation(stateIndex, statePayload, attPayload, attSignature);\n IAgentManager(agentManager).slashAgent(status.domain, notary, msg.sender);\n }\n }\n\n /// @inheritdoc IStatementInbox\n function verifyStateWithSnapshot(uint8 stateIndex, bytes memory snapPayload, bytes memory snapSignature)\n external\n returns (bool isValidState)\n {\n // This will revert if payload is not a snapshot\n Snapshot snapshot = snapPayload.castToSnapshot();\n // This will revert if the snapshot signer is not a known Guard/Notary\n (AgentStatus memory status, address agent) =\n _verifySnapshot({snapshot: snapshot, snapSignature: snapSignature, verifyNotary: false});\n // Agent needs to be Active/Unstaking\n status.verifyActiveUnstaking();\n // This will revert if state does not refer to this chain\n isValidState = IStateHub(origin).isValidState(snapshot.state(stateIndex).unwrap().clone());\n if (!isValidState) {\n emit InvalidStateWithSnapshot(stateIndex, snapPayload, snapSignature);\n IAgentManager(agentManager).slashAgent(status.domain, agent, msg.sender);\n }\n }\n\n /// @inheritdoc IStatementInbox\n function verifyStateReport(bytes memory statePayload, bytes memory srSignature)\n external\n returns (bool isValidReport)\n {\n // This will revert if payload is not a state\n State state = statePayload.castToState();\n // This will revert if the report signer is not a known Guard\n (AgentStatus memory status, address guard) = _verifyStateReport(state, srSignature);\n // Guard needs to be Active/Unstaking\n status.verifyActiveUnstaking();\n // Report is valid IF AND ONLY IF the reported state in invalid\n // This will revert if the reported state does not refer to this chain\n isValidReport = !IStateHub(origin).isValidState(statePayload);\n if (!isValidReport) {\n emit InvalidStateReport(statePayload, srSignature);\n IAgentManager(agentManager).slashAgent(status.domain, guard, msg.sender);\n }\n }\n\n // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════\n\n /// @inheritdoc IStatementInbox\n function getReportsAmount() external view returns (uint256) {\n return _storedReports.length;\n }\n\n /// @inheritdoc IStatementInbox\n function getGuardReport(uint256 index)\n external\n view\n returns (bytes memory statementPayload, bytes memory reportSignature)\n {\n if (index \u003e= _storedReports.length) revert IndexOutOfRange();\n StoredReport memory storedReport = _storedReports[index];\n statementPayload = storedReport.statementPayload;\n reportSignature = _storedSignatures[storedReport.sigIndex];\n }\n\n /// @inheritdoc IStatementInbox\n function getStoredSignature(uint256 index) external view returns (bytes memory) {\n return _storedSignatures[index];\n }\n\n // ══════════════════════════════════════════════ INTERNAL LOGIC ═══════════════════════════════════════════════════\n\n /// @dev Saves the statement reported by Guard as invalid and the Guard Report signature.\n function _saveReport(bytes memory statementPayload, bytes memory reportSignature) internal {\n uint256 sigIndex = _saveSignature(reportSignature);\n _storedReports.push(StoredReport(sigIndex, statementPayload));\n }\n\n /// @dev Saves the signature and returns its index.\n function _saveSignature(bytes memory signature) internal returns (uint256 sigIndex) {\n sigIndex = _storedSignatures.length;\n _storedSignatures.push(signature);\n }\n\n // ═══════════════════════════════════════════════ AGENT CHECKS ════════════════════════════════════════════════════\n\n /**\n * @dev Recovers a signer from a hashed message, and a EIP-191 signature for it.\n * Will revert, if the signer is not a known agent.\n * @dev Agent flag could be any of these: Active/Unstaking/Resting/Fraudulent/Slashed\n * Further checks need to be performed in a caller function.\n * @param hashedStatement Hash of the statement that was signed by an Agent\n * @param signature Agent signature for the hashed statement\n * @return status Struct representing agent status:\n * - flag Unknown/Active/Unstaking/Resting/Fraudulent/Slashed\n * - domain Domain where agent is/was active\n * - index Index of agent in the Agent Merkle Tree\n * @return agent Agent that signed the statement\n */\n function _recoverAgent(bytes32 hashedStatement, bytes memory signature)\n internal\n view\n returns (AgentStatus memory status, address agent)\n {\n bytes32 ethSignedMsg = ECDSA.toEthSignedMessageHash(hashedStatement);\n agent = ECDSA.recover(ethSignedMsg, signature);\n status = IAgentManager(agentManager).agentStatus(agent);\n // Discard signature of unknown agents.\n // Further flag checks are supposed to be performed in a caller function.\n status.verifyKnown();\n }\n\n /// @dev Verifies that Notary signature is active on local domain.\n function _verifyNotaryDomain(uint32 notaryDomain) internal view {\n // Notary needs to be from the local domain (if contract is not deployed on Synapse Chain).\n // Or Notary could be from any domain (if contract is deployed on Synapse Chain).\n if (notaryDomain != localDomain \u0026\u0026 localDomain != synapseDomain) revert IncorrectAgentDomain();\n }\n\n // ════════════════════════════════════════ ATTESTATION RELATED CHECKS ═════════════════════════════════════════════\n\n /**\n * @dev Internal function to verify the signed attestation payload.\n * Reverts if any of these is true:\n * - Attestation signer is not a known Notary.\n * @param att Typed memory view over attestation payload\n * @param attSignature Notary signature for the attestation\n * @return status Struct representing agent status, see {_recoverAgent}\n * @return notary Notary that signed the snapshot\n */\n function _verifyAttestation(Attestation att, bytes memory attSignature)\n internal\n view\n returns (AgentStatus memory status, address notary)\n {\n // This will revert if signer is not a known agent\n (status, notary) = _recoverAgent(att.hashValid(), attSignature);\n // Attestation signer needs to be a Notary, not a Guard\n if (status.domain == 0) revert AgentNotNotary();\n }\n\n /**\n * @dev Internal function to verify the signed attestation report payload.\n * Reverts if any of these is true:\n * - Report signer is not a known Guard.\n * @param att Typed memory view over attestation payload that Guard reports as invalid\n * @param arSignature Guard signature for the \"invalid attestation\" report\n * @return status Struct representing guard status, see {_recoverAgent}\n * @return guard Guard that signed the report\n */\n function _verifyAttestationReport(Attestation att, bytes memory arSignature)\n internal\n view\n returns (AgentStatus memory status, address guard)\n {\n // This will revert if signer is not a known agent\n (status, guard) = _recoverAgent(att.hashInvalid(), arSignature);\n // Report signer needs to be a Guard, not a Notary\n if (status.domain != 0) revert AgentNotGuard();\n }\n\n // ══════════════════════════════════════════ RECEIPT RELATED CHECKS ═══════════════════════════════════════════════\n\n /**\n * @dev Internal function to verify the signed receipt payload.\n * Reverts if any of these is true:\n * - Receipt signer is not a known Notary.\n * @param rcpt Typed memory view over receipt payload\n * @param rcptSignature Notary signature for the receipt\n * @return status Struct representing agent status, see {_recoverAgent}\n * @return notary Notary that signed the snapshot\n */\n function _verifyReceipt(Receipt rcpt, bytes memory rcptSignature)\n internal\n view\n returns (AgentStatus memory status, address notary)\n {\n // This will revert if signer is not a known agent\n (status, notary) = _recoverAgent(rcpt.hashValid(), rcptSignature);\n // Receipt signer needs to be a Notary, not a Guard\n if (status.domain == 0) revert AgentNotNotary();\n }\n\n /**\n * @dev Internal function to verify the signed receipt report payload.\n * Reverts if any of these is true:\n * - Report signer is not a known Guard.\n * @param rcpt Typed memory view over receipt payload that Guard reports as invalid\n * @param rrSignature Guard signature for the \"invalid receipt\" report\n * @return status Struct representing guard status, see {_recoverAgent}\n * @return guard Guard that signed the report\n */\n function _verifyReceiptReport(Receipt rcpt, bytes memory rrSignature)\n internal\n view\n returns (AgentStatus memory status, address guard)\n {\n // This will revert if signer is not a known agent\n (status, guard) = _recoverAgent(rcpt.hashInvalid(), rrSignature);\n // Report signer needs to be a Guard, not a Notary\n if (status.domain != 0) revert AgentNotGuard();\n }\n\n // ═══════════════════════════════════════ STATE/SNAPSHOT RELATED CHECKS ═══════════════════════════════════════════\n\n /**\n * @dev Internal function to verify the signed snapshot report payload.\n * Reverts if any of these is true:\n * - Report signer is not a known Guard.\n * @param state Typed memory view over state payload that Guard reports as invalid\n * @param srSignature Guard signature for the report\n * @return status Struct representing guard status, see {_recoverAgent}\n * @return guard Guard that signed the report\n */\n function _verifyStateReport(State state, bytes memory srSignature)\n internal\n view\n returns (AgentStatus memory status, address guard)\n {\n // This will revert if signer is not a known agent\n (status, guard) = _recoverAgent(state.hashInvalid(), srSignature);\n // Report signer needs to be a Guard, not a Notary\n if (status.domain != 0) revert AgentNotGuard();\n }\n\n /**\n * @dev Internal function to verify the signed snapshot payload.\n * Reverts if any of these is true:\n * - Snapshot signer is not a known Agent.\n * - Snapshot signer is not a Notary (if verifyNotary is true).\n * @param snapshot Typed memory view over snapshot payload\n * @param snapSignature Agent signature for the snapshot\n * @param verifyNotary If true, snapshot signer needs to be a Notary, not a Guard\n * @return status Struct representing agent status, see {_recoverAgent}\n * @return agent Agent that signed the snapshot\n */\n function _verifySnapshot(Snapshot snapshot, bytes memory snapSignature, bool verifyNotary)\n internal\n view\n returns (AgentStatus memory status, address agent)\n {\n // This will revert if signer is not a known agent\n (status, agent) = _recoverAgent(snapshot.hashValid(), snapSignature);\n // If requested, snapshot signer needs to be a Notary, not a Guard\n if (verifyNotary \u0026\u0026 status.domain == 0) revert AgentNotNotary();\n }\n\n // ═══════════════════════════════════════════ MERKLE RELATED CHECKS ═══════════════════════════════════════════════\n\n /**\n * @dev Internal function to verify that snapshot roots match.\n * Reverts if any of these is true:\n * - Attestation root is not equal to Merkle Root derived from State and Snapshot Proof.\n * - Snapshot Proof's first element does not match the State metadata.\n * - Snapshot Proof length exceeds Snapshot tree Height.\n * - State index is out of range.\n * @param att Typed memory view over Attestation\n * @param stateIndex Index of state in the snapshot\n * @param state Typed memory view over the provided state payload\n * @param snapProof Raw payload with snapshot data\n */\n function _verifySnapshotMerkle(Attestation att, uint8 stateIndex, State state, bytes32[] memory snapProof)\n internal\n pure\n {\n // Snapshot proof first element should match State metadata (aka \"right sub-leaf\")\n (, bytes32 rightSubLeaf) = state.subLeafs();\n if (snapProof[0] != rightSubLeaf) revert IncorrectSnapshotProof();\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(state.root(), state.origin(), snapProof, stateIndex);\n // Snapshot root should match the attestation root\n if (att.snapRoot() != snapshotRoot) revert IncorrectSnapshotRoot();\n }\n}\n\n// contracts/inbox/Inbox.sol\n\n// ══════════════════════════════ LIBRARY IMPORTS ══════════════════════════════\n\n// ═════════════════════════════ INTERNAL IMPORTS ══════════════════════════════\n\n/// @notice `Inbox` is the child of `StatementInbox` contract, that is used on Synapse Chain.\n/// In addition to the functionality of `StatementInbox`, it also:\n/// - Accepts Guard and Notary Snapshots and passes them to `Summit` contract.\n/// - Accepts Notary-signed Receipts and passes them to `Summit` contract.\n/// - Accepts Receipt Reports to initiate a dispute between Guard and Notary.\n/// - Verifies Attestations and Attestation Reports, and slashes the signer if they are invalid.\ncontract Inbox is StatementInbox, InboxEvents, InterfaceInbox {\n using AttestationLib for bytes;\n using ReceiptLib for bytes;\n using SnapshotLib for bytes;\n\n // Struct to get around stack too deep error. TODO: revisit this\n struct ReceiptInfo {\n AgentStatus rcptNotaryStatus;\n address notary;\n uint32 attNonce;\n AgentStatus attNotaryStatus;\n }\n\n // ══════════════════════════════════════════════════ STORAGE ══════════════════════════════════════════════════════\n\n // The address of the Summit contract.\n address public summit;\n\n // ═════════════════════════════════════════ CONSTRUCTOR \u0026 INITIALIZER ═════════════════════════════════════════════\n\n constructor(uint32 synapseDomain_) MessagingBase(\"0.0.3\", synapseDomain_) {\n if (localDomain != synapseDomain) revert MustBeSynapseDomain();\n }\n\n /// @notice Initializes `Inbox` contract:\n /// - Sets `msg.sender` as the owner of the contract\n /// - Sets `agentManager`, `origin`, `destination` and `summit` addresses\n function initialize(address agentManager_, address origin_, address destination_, address summit_)\n external\n initializer\n {\n __StatementInbox_init(agentManager_, origin_, destination_);\n summit = summit_;\n }\n\n // ══════════════════════════════════════════ SUBMIT AGENT STATEMENTS ══════════════════════════════════════════════\n\n /// @inheritdoc InterfaceInbox\n function submitSnapshot(bytes memory snapPayload, bytes memory snapSignature)\n external\n returns (bytes memory attPayload, bytes32 agentRoot_, uint256[] memory snapGas)\n {\n // This will revert if payload is not a snapshot\n Snapshot snapshot = snapPayload.castToSnapshot();\n // This will revert if the signer is not a known Guard/Notary\n (AgentStatus memory status, address agent) =\n _verifySnapshot({snapshot: snapshot, snapSignature: snapSignature, verifyNotary: false});\n // Check that Agent is active\n status.verifyActive();\n // Store Agent signature for the Snapshot\n uint256 sigIndex = _saveSignature(snapSignature);\n if (status.domain == 0) {\n // Guard that is in Dispute could still submit new snapshots, so we don't check that\n InterfaceSummit(summit).acceptGuardSnapshot({\n guardIndex: status.index,\n sigIndex: sigIndex,\n snapPayload: snapPayload\n });\n } else {\n // Get current agentRoot from AgentManager\n agentRoot_ = IAgentManager(agentManager).agentRoot();\n // This will revert if Notary is in Dispute\n attPayload = InterfaceSummit(summit).acceptNotarySnapshot({\n notaryIndex: status.index,\n sigIndex: sigIndex,\n agentRoot: agentRoot_,\n snapPayload: snapPayload\n });\n ChainGas[] memory snapGas_ = snapshot.snapGas();\n // Pass created attestation to Destination to enable executing messages coming to Synapse Chain\n InterfaceDestination(destination).acceptAttestation(\n status.index, type(uint256).max, attPayload, agentRoot_, snapGas_\n );\n // Use assembly to cast ChainGas[] to uint256[] without copying. Highest bits are left zeroed.\n // solhint-disable-next-line no-inline-assembly\n assembly {\n snapGas := snapGas_\n }\n }\n emit SnapshotAccepted(status.domain, agent, snapPayload, snapSignature);\n }\n\n /// @inheritdoc InterfaceInbox\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 // Struct to get around stack too deep error.\n ReceiptInfo memory info;\n // This will revert if payload is not a receipt\n Receipt rcpt = rcptPayload.castToReceipt();\n // This will revert if the receipt signer is not a known Notary\n (info.rcptNotaryStatus, info.notary) = _verifyReceipt(rcpt, rcptSignature);\n // Receipt Notary needs to be Active\n info.rcptNotaryStatus.verifyActive();\n info.attNonce = IExecutionHub(destination).getAttestationNonce(rcpt.snapshotRoot());\n if (info.attNonce == 0) revert IncorrectSnapshotRoot();\n // Attestation Notary domain needs to match the destination domain\n info.attNotaryStatus = IAgentManager(agentManager).agentStatus(rcpt.attNotary());\n if (info.attNotaryStatus.domain != rcpt.destination()) revert IncorrectAgentDomain();\n // Check that the correct tip values for the message were provided\n _verifyReceiptTips(rcpt.messageHash(), paddedTips, headerHash, bodyHash);\n // Store Notary signature for the Receipt\n uint256 sigIndex = _saveSignature(rcptSignature);\n // This will revert if Receipt Notary is in Dispute\n wasAccepted = InterfaceSummit(summit).acceptReceipt({\n rcptNotaryIndex: info.rcptNotaryStatus.index,\n attNotaryIndex: info.attNotaryStatus.index,\n sigIndex: sigIndex,\n attNonce: info.attNonce,\n paddedTips: paddedTips,\n rcptPayload: rcptPayload\n });\n if (wasAccepted) {\n emit ReceiptAccepted(info.rcptNotaryStatus.domain, info.notary, rcptPayload, rcptSignature);\n }\n }\n\n /// @inheritdoc InterfaceInbox\n function submitReceiptReport(bytes memory rcptPayload, bytes memory rcptSignature, bytes memory rrSignature)\n external\n returns (bool wasAccepted)\n {\n // This will revert if payload is not a receipt\n Receipt rcpt = rcptPayload.castToReceipt();\n // This will revert if the receipt signer is not a known Guard\n (AgentStatus memory guardStatus,) = _verifyReceiptReport(rcpt, rrSignature);\n // Guard needs to be Active\n guardStatus.verifyActive();\n // This will revert if report signer is not a known Notary\n (AgentStatus memory notaryStatus,) = _verifyReceipt(rcpt, rcptSignature);\n // Notary needs to be Active/Unstaking\n notaryStatus.verifyActiveUnstaking();\n _saveReport(rcptPayload, rrSignature);\n // This will revert if either actor is already in dispute\n IAgentManager(agentManager).openDispute(guardStatus.index, notaryStatus.index);\n return true;\n }\n\n /// @inheritdoc InterfaceInbox\n function passReceipt(uint32 attNotaryIndex, uint32 attNonce, uint256 paddedTips, bytes memory rcptPayload)\n external\n returns (bool wasAccepted)\n {\n // Only Destination can pass receipts\n if (msg.sender != destination) revert CallerNotDestination();\n return InterfaceSummit(summit).acceptReceipt({\n rcptNotaryIndex: attNotaryIndex,\n attNotaryIndex: attNotaryIndex,\n sigIndex: type(uint256).max,\n attNonce: attNonce,\n paddedTips: paddedTips,\n rcptPayload: rcptPayload\n });\n }\n\n // ══════════════════════════════════════════ VERIFY AGENT STATEMENTS ══════════════════════════════════════════════\n\n /// @inheritdoc InterfaceInbox\n function verifyAttestation(bytes memory attPayload, bytes memory attSignature)\n external\n returns (bool isValidAttestation)\n {\n // This will revert if payload is not an attestation\n Attestation att = attPayload.castToAttestation();\n // This will revert if the attestation signer is not a known Notary\n (AgentStatus memory status, address notary) = _verifyAttestation(att, attSignature);\n // Notary needs to be Active/Unstaking\n status.verifyActiveUnstaking();\n isValidAttestation = ISnapshotHub(summit).isValidAttestation(attPayload);\n if (!isValidAttestation) {\n emit InvalidAttestation(attPayload, attSignature);\n IAgentManager(agentManager).slashAgent(status.domain, notary, msg.sender);\n }\n }\n\n /// @inheritdoc InterfaceInbox\n function verifyAttestationReport(bytes memory attPayload, bytes memory arSignature)\n external\n returns (bool isValidReport)\n {\n // This will revert if payload is not an attestation\n Attestation att = attPayload.castToAttestation();\n // This will revert if the report signer is not a known Guard\n (AgentStatus memory status, address guard) = _verifyAttestationReport(att, arSignature);\n // Guard needs to be Active/Unstaking\n status.verifyActiveUnstaking();\n // Report is valid IF AND ONLY IF the reported attestation in invalid\n isValidReport = !ISnapshotHub(summit).isValidAttestation(attPayload);\n if (!isValidReport) {\n emit InvalidAttestationReport(attPayload, arSignature);\n IAgentManager(agentManager).slashAgent(status.domain, guard, msg.sender);\n }\n }\n\n // ══════════════════════════════════════════════ INTERNAL VIEWS ═══════════════════════════════════════════════════\n\n /// @dev Verifies that tips proof matches the message hash.\n function _verifyReceiptTips(bytes32 msgHash, uint256 paddedTips, bytes32 headerHash, bytes32 bodyHash)\n internal\n pure\n {\n Tips tips = TipsLib.wrapPadded(paddedTips);\n // full message leaf is (header, baseMessage), while base message leaf is (tips, remainingBody).\n if (MerkleMath.getParent(headerHash, MerkleMath.getParent(tips.leaf(), bodyHash)) != msgHash) {\n revert IncorrectTipsProof();\n }\n }\n}\n","language":"Solidity","languageVersion":"0.8.17","compilerVersion":"0.8.17","compilerOptions":"--combined-json bin,bin-runtime,srcmap,srcmap-runtime,abi,userdoc,devdoc,metadata,hashes --optimize --optimize-runs 10000 --allow-paths ., ./, ../","srcMap":"42383:4887:0:-:0;;;;;;;;;;;;;;;-1:-1:-1;;;42383:4887:0;;;;;;;;;;;;;;;;;","srcMapRuntime":"42383: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/Inbox.sol\":\"NumberLib\"},\"evmVersion\":\"london\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\"},\"optimizer\":{\"enabled\":true,\"runs\":10000},\"remappings\":[]},\"sources\":{\"solidity/Inbox.sol\":{\"keccak256\":\"0x9b516081a036814c0169e20e484d4a5499066b7a6f48fada952b5e844a1ca3e5\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://32bde393b3f24ef4307d9626d4143f337b3c0bd34e17bb969fd5a15221d96987\",\"dweb:/ipfs/QmTkt2XZRtgsbSpmsVQUM3c4ebETQoDVYbmEV9yheBghnr\"]}},\"version\":1}"},"hashes":{}},"solidity/Inbox.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/InboxEvents.sol\n\nabstract contract InboxEvents {\n /**\n * @notice Emitted when a snapshot is accepted by the Summit contract.\n * @param domain Domain where the signed Agent is active (ZERO for Guards)\n * @param agent Agent who signed the snapshot\n * @param snapPayload Raw payload with snapshot data\n * @param snapSignature Agent signature for the snapshot\n */\n event SnapshotAccepted(uint32 indexed domain, address indexed agent, bytes snapPayload, bytes snapSignature);\n\n /**\n * @notice Emitted when a snapshot is accepted by the Summit contract.\n * @param domain Domain where the signed Notary is active\n * @param notary Notary who signed the attestation\n * @param rcptPayload Raw payload with receipt data\n * @param rcptSignature Notary signature for the receipt\n */\n event ReceiptAccepted(uint32 domain, address notary, bytes rcptPayload, bytes rcptSignature);\n\n /**\n * @notice Emitted when a proof of invalid attestation is submitted.\n * @param attPayload Raw payload with Attestation data\n * @param attSignature Notary signature for the attestation\n */\n event InvalidAttestation(bytes attPayload, bytes attSignature);\n\n /**\n * @notice Emitted when a proof of invalid attestation report is submitted.\n * @param arPayload Raw payload with report data\n * @param arSignature Guard signature for the report\n */\n event InvalidAttestationReport(bytes arPayload, bytes arSignature);\n}\n\n// contracts/events/StatementInboxEvents.sol\n\nabstract contract StatementInboxEvents {\n // ════════════════════════════════════════════ STATEMENT ACCEPTED ═════════════════════════════════════════════════\n\n /**\n * @notice Emitted when a snapshot is accepted by the Destination contract.\n * @param domain Domain where the signed Notary is active\n * @param notary Notary who signed the attestation\n * @param attPayload Raw payload with attestation data\n * @param attSignature Notary signature for the attestation\n */\n event AttestationAccepted(uint32 domain, address notary, bytes attPayload, bytes attSignature);\n\n // ═════════════════════════════════════════ INVALID STATEMENT PROVED ══════════════════════════════════════════════\n\n /**\n * @notice Emitted when a proof of invalid receipt statement is submitted.\n * @param rcptPayload Raw payload with the receipt statement\n * @param rcptSignature Notary signature for the receipt statement\n */\n event InvalidReceipt(bytes rcptPayload, bytes rcptSignature);\n\n /**\n * @notice Emitted when a proof of invalid receipt report is submitted.\n * @param rrPayload Raw payload with report data\n * @param rrSignature Guard signature for the report\n */\n event InvalidReceiptReport(bytes rrPayload, bytes rrSignature);\n\n /**\n * @notice Emitted when a proof of invalid state in the signed attestation is submitted.\n * @param stateIndex Index of invalid state in the snapshot\n * @param statePayload Raw payload with state data\n * @param attPayload Raw payload with Attestation data for snapshot\n * @param attSignature Notary signature for the attestation\n */\n event InvalidStateWithAttestation(uint8 stateIndex, bytes statePayload, bytes attPayload, bytes attSignature);\n\n /**\n * @notice Emitted when a proof of invalid state in the signed snapshot is submitted.\n * @param stateIndex Index of invalid state in the snapshot\n * @param snapPayload Raw payload with snapshot data\n * @param snapSignature Agent signature for the snapshot\n */\n event InvalidStateWithSnapshot(uint8 stateIndex, bytes snapPayload, bytes snapSignature);\n\n /**\n * @notice Emitted when a proof of invalid state report is submitted.\n * @param srPayload Raw payload with report data\n * @param srSignature Guard signature for the report\n */\n event InvalidStateReport(bytes srPayload, bytes srSignature);\n}\n\n// contracts/interfaces/ISnapshotHub.sol\n\ninterface ISnapshotHub {\n /**\n * @notice Check that a given attestation is valid: matches the historical attestation\n * derived from an accepted Notary snapshot.\n * @dev Will revert if any of these is true:\n * - Attestation payload is not properly formatted.\n * @param attPayload Raw payload with attestation data\n * @return isValid Whether the provided attestation is valid\n */\n function isValidAttestation(bytes memory attPayload) external view returns (bool isValid);\n\n /**\n * @notice Returns saved attestation with the given nonce.\n * @dev Reverts if attestation with given nonce hasn't been created yet.\n * @param attNonce Nonce for the attestation\n * @return attPayload Raw payload with formatted Attestation data\n * @return agentRoot Agent root hash used for the attestation\n * @return snapGas Snapshot gas data used for the attestation\n */\n function getAttestation(uint32 attNonce)\n external\n view\n returns (bytes memory attPayload, bytes32 agentRoot, uint256[] memory snapGas);\n\n /**\n * @notice Returns the state with the highest known nonce submitted by a given Agent.\n * @param origin Domain of origin chain\n * @param agent Agent address\n * @return statePayload Raw payload with agent's latest state for origin\n */\n function getLatestAgentState(uint32 origin, address agent) external view returns (bytes memory statePayload);\n\n /**\n * @notice Returns latest saved attestation for a Notary.\n * @param notary Notary address\n * @return attPayload Raw payload with formatted Attestation data\n * @return agentRoot Agent root hash used for the attestation\n * @return snapGas Snapshot gas data used for the attestation\n */\n function getLatestNotaryAttestation(address notary)\n external\n view\n returns (bytes memory attPayload, bytes32 agentRoot, uint256[] memory snapGas);\n\n /**\n * @notice Returns Guard snapshot from the list of all accepted Guard snapshots.\n * @dev Reverts if snapshot with given index hasn't been accepted yet.\n * @param index Snapshot index in the list of all Guard snapshots\n * @return snapPayload Raw payload with Guard snapshot\n * @return snapSignature Raw payload with Guard signature for snapshot\n */\n function getGuardSnapshot(uint256 index)\n external\n view\n returns (bytes memory snapPayload, bytes memory snapSignature);\n\n /**\n * @notice Returns Notary snapshot from the list of all accepted Guard snapshots.\n * @dev Reverts if snapshot with given index hasn't been accepted yet.\n * @param index Snapshot index in the list of all Notary snapshots\n * @return snapPayload Raw payload with Notary snapshot\n * @return snapSignature Raw payload with Notary signature for snapshot\n */\n function getNotarySnapshot(uint256 index)\n external\n view\n returns (bytes memory snapPayload, bytes memory snapSignature);\n\n /**\n * @notice Returns Notary snapshot that was used for creating a given attestation.\n * @dev Reverts if any of these is true:\n * - Attestation payload is not properly formatted.\n * - Attestation is invalid (doesn't have a matching Notary snapshot).\n * @param attPayload Raw payload with attestation data\n * @return snapPayload Raw payload with Notary snapshot\n * @return snapSignature Raw payload with Notary signature for snapshot\n */\n function getNotarySnapshot(bytes memory attPayload)\n external\n view\n returns (bytes memory snapPayload, bytes memory snapSignature);\n\n /**\n * @notice Returns proof of inclusion of (root, origin) fields of a given snapshot's state\n * into the Snapshot Merkle Tree for a given attestation.\n * @dev Reverts if any of these is true:\n * - Attestation with given nonce hasn't been created yet.\n * - State index is out of range of snapshot list.\n * @param attNonce Nonce for the attestation\n * @param stateIndex Index of state in the attestation's snapshot\n * @return snapProof The snapshot proof\n */\n function getSnapshotProof(uint32 attNonce, uint8 stateIndex) external view returns (bytes32[] memory snapProof);\n}\n\n// contracts/interfaces/IStateHub.sol\n\ninterface IStateHub {\n /**\n * @notice Check that a given state is valid: matches the historical state of Origin contract.\n * Note: any Agent including an invalid state in their snapshot will be slashed\n * upon providing the snapshot and agent signature for it to Origin contract.\n * @dev Will revert if any of these is true:\n * - State payload is not properly formatted.\n * @param statePayload Raw payload with state data\n * @return isValid Whether the provided state is valid\n */\n function isValidState(bytes memory statePayload) external view returns (bool isValid);\n\n /**\n * @notice Returns the amount of saved states so far.\n * @dev This includes the initial state of \"empty Origin Merkle Tree\".\n */\n function statesAmount() external view returns (uint256);\n\n /**\n * @notice Suggest the data (state after latest sent message) to sign for an Agent.\n * Note: signing the suggested state data will will never lead to slashing of the actor,\n * assuming they have confirmed that the block, which number is included in the data,\n * is not subject to reorganization (which is different for every observed chain).\n * @return statePayload Raw payload with the latest state data\n */\n function suggestLatestState() external view returns (bytes memory statePayload);\n\n /**\n * @notice Given the historical nonce, suggest the state data to sign for an Agent.\n * Note: signing the suggested state data will will never lead to slashing of the actor,\n * assuming they have confirmed that the block, which number is included in the data,\n * is not subject to reorganization (which is different for every observed chain).\n * @param nonce Historical nonce to form a state\n * @return statePayload Raw payload with historical state data\n */\n function suggestState(uint32 nonce) external view returns (bytes memory statePayload);\n}\n\n// contracts/interfaces/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/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// node_modules/@openzeppelin/contracts/utils/math/Math.sol\n\n// OpenZeppelin Contracts (last updated v4.9.0) (utils/math/Math.sol)\n\n/**\n * @dev Standard math utilities missing in the Solidity language.\n */\nlibrary Math {\n enum Rounding {\n Down, // Toward negative infinity\n Up, // Toward infinity\n Zero // Toward zero\n }\n\n /**\n * @dev Returns the largest of two numbers.\n */\n function max(uint256 a, uint256 b) internal pure returns (uint256) {\n return a \u003e b ? a : b;\n }\n\n /**\n * @dev Returns the smallest of two numbers.\n */\n function min(uint256 a, uint256 b) internal pure returns (uint256) {\n return a \u003c b ? a : b;\n }\n\n /**\n * @dev Returns the average of two numbers. The result is rounded towards\n * zero.\n */\n function average(uint256 a, uint256 b) internal pure returns (uint256) {\n // (a + b) / 2 can overflow.\n return (a \u0026 b) + (a ^ b) / 2;\n }\n\n /**\n * @dev Returns the ceiling of the division of two numbers.\n *\n * This differs from standard division with `/` in that it rounds up instead\n * of rounding down.\n */\n function ceilDiv(uint256 a, uint256 b) internal pure returns (uint256) {\n // (a + b - 1) / b can overflow on addition, so we distribute.\n return a == 0 ? 0 : (a - 1) / b + 1;\n }\n\n /**\n * @notice Calculates floor(x * y / denominator) with full precision. Throws if result overflows a uint256 or denominator == 0\n * @dev Original credit to Remco Bloemen under MIT license (https://xn--2-umb.com/21/muldiv)\n * with further edits by Uniswap Labs also under MIT license.\n */\n function mulDiv(uint256 x, uint256 y, uint256 denominator) internal pure returns (uint256 result) {\n unchecked {\n // 512-bit multiply [prod1 prod0] = x * y. Compute the product mod 2^256 and mod 2^256 - 1, then use\n // use the Chinese Remainder Theorem to reconstruct the 512 bit result. The result is stored in two 256\n // variables such that product = prod1 * 2^256 + prod0.\n uint256 prod0; // Least significant 256 bits of the product\n uint256 prod1; // Most significant 256 bits of the product\n assembly {\n let mm := mulmod(x, y, not(0))\n prod0 := mul(x, y)\n prod1 := sub(sub(mm, prod0), lt(mm, prod0))\n }\n\n // Handle non-overflow cases, 256 by 256 division.\n if (prod1 == 0) {\n // Solidity will revert if denominator == 0, unlike the div opcode on its own.\n // The surrounding unchecked block does not change this fact.\n // See https://docs.soliditylang.org/en/latest/control-structures.html#checked-or-unchecked-arithmetic.\n return prod0 / denominator;\n }\n\n // Make sure the result is less than 2^256. Also prevents denominator == 0.\n require(denominator \u003e prod1, \"Math: mulDiv overflow\");\n\n ///////////////////////////////////////////////\n // 512 by 256 division.\n ///////////////////////////////////////////////\n\n // Make division exact by subtracting the remainder from [prod1 prod0].\n uint256 remainder;\n assembly {\n // Compute remainder using mulmod.\n remainder := mulmod(x, y, denominator)\n\n // Subtract 256 bit number from 512 bit number.\n prod1 := sub(prod1, gt(remainder, prod0))\n prod0 := sub(prod0, remainder)\n }\n\n // Factor powers of two out of denominator and compute largest power of two divisor of denominator. Always \u003e= 1.\n // See https://cs.stackexchange.com/q/138556/92363.\n\n // Does not overflow because the denominator cannot be zero at this stage in the function.\n uint256 twos = denominator \u0026 (~denominator + 1);\n assembly {\n // Divide denominator by twos.\n denominator := div(denominator, twos)\n\n // Divide [prod1 prod0] by twos.\n prod0 := div(prod0, twos)\n\n // Flip twos such that it is 2^256 / twos. If twos is zero, then it becomes one.\n twos := add(div(sub(0, twos), twos), 1)\n }\n\n // Shift in bits from prod1 into prod0.\n prod0 |= prod1 * twos;\n\n // Invert denominator mod 2^256. Now that denominator is an odd number, it has an inverse modulo 2^256 such\n // that denominator * inv = 1 mod 2^256. Compute the inverse by starting with a seed that is correct for\n // four bits. That is, denominator * inv = 1 mod 2^4.\n uint256 inverse = (3 * denominator) ^ 2;\n\n // Use the Newton-Raphson iteration to improve the precision. Thanks to Hensel's lifting lemma, this also works\n // in modular arithmetic, doubling the correct bits in each step.\n inverse *= 2 - denominator * inverse; // inverse mod 2^8\n inverse *= 2 - denominator * inverse; // inverse mod 2^16\n inverse *= 2 - denominator * inverse; // inverse mod 2^32\n inverse *= 2 - denominator * inverse; // inverse mod 2^64\n inverse *= 2 - denominator * inverse; // inverse mod 2^128\n inverse *= 2 - denominator * inverse; // inverse mod 2^256\n\n // Because the division is now exact we can divide by multiplying with the modular inverse of denominator.\n // This will give us the correct result modulo 2^256. Since the preconditions guarantee that the outcome is\n // less than 2^256, this is the final result. We don't need to compute the high bits of the result and prod1\n // is no longer required.\n result = prod0 * inverse;\n return result;\n }\n }\n\n /**\n * @notice Calculates x * y / denominator with full precision, following the selected rounding direction.\n */\n function mulDiv(uint256 x, uint256 y, uint256 denominator, Rounding rounding) internal pure returns (uint256) {\n uint256 result = mulDiv(x, y, denominator);\n if (rounding == Rounding.Up \u0026\u0026 mulmod(x, y, denominator) \u003e 0) {\n result += 1;\n }\n return result;\n }\n\n /**\n * @dev Returns the square root of a number. If the number is not a perfect square, the value is rounded down.\n *\n * Inspired by Henry S. Warren, Jr.'s \"Hacker's Delight\" (Chapter 11).\n */\n function sqrt(uint256 a) internal pure returns (uint256) {\n if (a == 0) {\n return 0;\n }\n\n // For our first guess, we get the biggest power of 2 which is smaller than the square root of the target.\n //\n // We know that the \"msb\" (most significant bit) of our target number `a` is a power of 2 such that we have\n // `msb(a) \u003c= a \u003c 2*msb(a)`. This value can be written `msb(a)=2**k` with `k=log2(a)`.\n //\n // This can be rewritten `2**log2(a) \u003c= a \u003c 2**(log2(a) + 1)`\n // → `sqrt(2**k) \u003c= sqrt(a) \u003c sqrt(2**(k+1))`\n // → `2**(k/2) \u003c= sqrt(a) \u003c 2**((k+1)/2) \u003c= 2**(k/2 + 1)`\n //\n // Consequently, `2**(log2(a) / 2)` is a good first approximation of `sqrt(a)` with at least 1 correct bit.\n uint256 result = 1 \u003c\u003c (log2(a) \u003e\u003e 1);\n\n // At this point `result` is an estimation with one bit of precision. We know the true value is a uint128,\n // since it is the square root of a uint256. Newton's method converges quadratically (precision doubles at\n // every iteration). We thus need at most 7 iteration to turn our partial result with one bit of precision\n // into the expected uint128 result.\n unchecked {\n result = (result + a / result) \u003e\u003e 1;\n result = (result + a / result) \u003e\u003e 1;\n result = (result + a / result) \u003e\u003e 1;\n result = (result + a / result) \u003e\u003e 1;\n result = (result + a / result) \u003e\u003e 1;\n result = (result + a / result) \u003e\u003e 1;\n result = (result + a / result) \u003e\u003e 1;\n return min(result, a / result);\n }\n }\n\n /**\n * @notice Calculates sqrt(a), following the selected rounding direction.\n */\n function sqrt(uint256 a, Rounding rounding) internal pure returns (uint256) {\n unchecked {\n uint256 result = sqrt(a);\n return result + (rounding == Rounding.Up \u0026\u0026 result * result \u003c a ? 1 : 0);\n }\n }\n\n /**\n * @dev Return the log in base 2, rounded down, of a positive value.\n * Returns 0 if given 0.\n */\n function log2(uint256 value) internal pure returns (uint256) {\n uint256 result = 0;\n unchecked {\n if (value \u003e\u003e 128 \u003e 0) {\n value \u003e\u003e= 128;\n result += 128;\n }\n if (value \u003e\u003e 64 \u003e 0) {\n value \u003e\u003e= 64;\n result += 64;\n }\n if (value \u003e\u003e 32 \u003e 0) {\n value \u003e\u003e= 32;\n result += 32;\n }\n if (value \u003e\u003e 16 \u003e 0) {\n value \u003e\u003e= 16;\n result += 16;\n }\n if (value \u003e\u003e 8 \u003e 0) {\n value \u003e\u003e= 8;\n result += 8;\n }\n if (value \u003e\u003e 4 \u003e 0) {\n value \u003e\u003e= 4;\n result += 4;\n }\n if (value \u003e\u003e 2 \u003e 0) {\n value \u003e\u003e= 2;\n result += 2;\n }\n if (value \u003e\u003e 1 \u003e 0) {\n result += 1;\n }\n }\n return result;\n }\n\n /**\n * @dev Return the log in base 2, following the selected rounding direction, of a positive value.\n * Returns 0 if given 0.\n */\n function log2(uint256 value, Rounding rounding) internal pure returns (uint256) {\n unchecked {\n uint256 result = log2(value);\n return result + (rounding == Rounding.Up \u0026\u0026 1 \u003c\u003c result \u003c value ? 1 : 0);\n }\n }\n\n /**\n * @dev Return the log in base 10, rounded down, of a positive value.\n * Returns 0 if given 0.\n */\n function log10(uint256 value) internal pure returns (uint256) {\n uint256 result = 0;\n unchecked {\n if (value \u003e= 10 ** 64) {\n value /= 10 ** 64;\n result += 64;\n }\n if (value \u003e= 10 ** 32) {\n value /= 10 ** 32;\n result += 32;\n }\n if (value \u003e= 10 ** 16) {\n value /= 10 ** 16;\n result += 16;\n }\n if (value \u003e= 10 ** 8) {\n value /= 10 ** 8;\n result += 8;\n }\n if (value \u003e= 10 ** 4) {\n value /= 10 ** 4;\n result += 4;\n }\n if (value \u003e= 10 ** 2) {\n value /= 10 ** 2;\n result += 2;\n }\n if (value \u003e= 10 ** 1) {\n result += 1;\n }\n }\n return result;\n }\n\n /**\n * @dev Return the log in base 10, following the selected rounding direction, of a positive value.\n * Returns 0 if given 0.\n */\n function log10(uint256 value, Rounding rounding) internal pure returns (uint256) {\n unchecked {\n uint256 result = log10(value);\n return result + (rounding == Rounding.Up \u0026\u0026 10 ** result \u003c value ? 1 : 0);\n }\n }\n\n /**\n * @dev Return the log in base 256, rounded down, of a positive value.\n * Returns 0 if given 0.\n *\n * Adding one to the result gives the number of pairs of hex symbols needed to represent `value` as a hex string.\n */\n function log256(uint256 value) internal pure returns (uint256) {\n uint256 result = 0;\n unchecked {\n if (value \u003e\u003e 128 \u003e 0) {\n value \u003e\u003e= 128;\n result += 16;\n }\n if (value \u003e\u003e 64 \u003e 0) {\n value \u003e\u003e= 64;\n result += 8;\n }\n if (value \u003e\u003e 32 \u003e 0) {\n value \u003e\u003e= 32;\n result += 4;\n }\n if (value \u003e\u003e 16 \u003e 0) {\n value \u003e\u003e= 16;\n result += 2;\n }\n if (value \u003e\u003e 8 \u003e 0) {\n result += 1;\n }\n }\n return result;\n }\n\n /**\n * @dev Return the log in base 256, following the selected rounding direction, of a positive value.\n * Returns 0 if given 0.\n */\n function log256(uint256 value, Rounding rounding) internal pure returns (uint256) {\n unchecked {\n uint256 result = log256(value);\n return result + (rounding == Rounding.Up \u0026\u0026 1 \u003c\u003c (result \u003c\u003c 3) \u003c value ? 1 : 0);\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/utils/math/SignedMath.sol\n\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/math/SignedMath.sol)\n\n/**\n * @dev Standard signed math utilities missing in the Solidity language.\n */\nlibrary SignedMath {\n /**\n * @dev Returns the largest of two signed numbers.\n */\n function max(int256 a, int256 b) internal pure returns (int256) {\n return a \u003e b ? a : b;\n }\n\n /**\n * @dev Returns the smallest of two signed numbers.\n */\n function min(int256 a, int256 b) internal pure returns (int256) {\n return a \u003c b ? a : b;\n }\n\n /**\n * @dev Returns the average of two signed numbers without overflow.\n * The result is rounded towards zero.\n */\n function average(int256 a, int256 b) internal pure returns (int256) {\n // Formula from the book \"Hacker's Delight\"\n int256 x = (a \u0026 b) + ((a ^ b) \u003e\u003e 1);\n return x + (int256(uint256(x) \u003e\u003e 255) \u0026 (a ^ b));\n }\n\n /**\n * @dev Returns the absolute unsigned value of a signed value.\n */\n function abs(int256 n) internal pure returns (uint256) {\n unchecked {\n // must be unchecked in order to support `n = type(int256).min`\n return uint256(n \u003e= 0 ? n : -n);\n }\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// 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/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/InterfaceSummit.sol\n\ninterface InterfaceSummit {\n // ══════════════════════════════════════════ ACCEPT AGENT STATEMENTS ══════════════════════════════════════════════\n\n /**\n * @notice Accepts a receipt, which local `AgentManager` verified to have been signed by an active Notary.\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 * - Notary who signed the receipt is referenced as the \"Receipt Notary\".\n * - Notary who signed the attestation on destination chain is referenced as the \"Attestation Notary\".\n * \u003e Will revert if any of these is true:\n * \u003e - Called by anyone other than local `AgentManager`.\n * \u003e - Receipt body payload is not properly formatted.\n * \u003e - Receipt signer is in Dispute.\n * \u003e - Receipt's snapshot root is unknown.\n * @param rcptNotaryIndex Index of Receipt Notary in Agent Merkle Tree\n * @param attNotaryIndex Index of Attestation Notary in Agent Merkle Tree\n * @param sigIndex Index of stored Notary signature\n * @param attNonce Nonce of the attestation used for proving the executed message\n * @param paddedTips Padded encoded paid tips information\n * @param rcptPayload Raw payload with message execution receipt\n * @return wasAccepted Whether the receipt was accepted\n */\n function acceptReceipt(\n uint32 rcptNotaryIndex,\n uint32 attNotaryIndex,\n uint256 sigIndex,\n uint32 attNonce,\n uint256 paddedTips,\n bytes memory rcptPayload\n ) external returns (bool wasAccepted);\n\n /**\n * @notice Accepts a snapshot, which local `AgentManager` verified to have been signed by an active Guard.\n * \u003e Snapshot is a list of states for a set of Origin contracts residing on any of the chains.\n * All the states in the Guard-signed snapshot become available for Notary signing.\n * \u003e Will revert if any of these is true:\n * \u003e - Called by anyone other than local `AgentManager`.\n * \u003e - Snapshot payload is not properly formatted.\n * \u003e - Snapshot contains a state older then the Guard has previously submitted.\n * @param guardIndex Index of Guard in Agent Merkle Tree\n * @param sigIndex Index of stored Agent signature\n * @param snapPayload Raw payload with snapshot data\n */\n function acceptGuardSnapshot(uint32 guardIndex, uint256 sigIndex, bytes memory snapPayload) external;\n\n /**\n * @notice Accepts a snapshot, which local `AgentManager` verified to have been signed by an active Notary.\n * \u003e Snapshot is a list of states for a set of Origin contracts residing on any of the chains.\n * Snapshot Merkle Root is calculated and saved for valid snapshots, i.e.\n * snapshots which are only using states previously submitted by any of the Guards.\n * - Notary could use states singed by the same of different Guards 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 - Called by anyone other than local `AgentManager`.\n * \u003e - Snapshot payload is not properly formatted.\n * \u003e - Snapshot contains a state older then the Notary has previously submitted.\n * \u003e - Snapshot contains a state that no Guard has previously submitted.\n * @param notaryIndex Index of Notary in Agent Merkle Tree\n * @param sigIndex Index of stored Agent signature\n * @param agentRoot Current root of the Agent Merkle Tree\n * @param snapPayload Raw payload with snapshot data\n * @return attPayload Raw payload with data for attestation derived from Notary snapshot.\n */\n function acceptNotarySnapshot(uint32 notaryIndex, uint256 sigIndex, bytes32 agentRoot, bytes memory snapPayload)\n external\n returns (bytes memory attPayload);\n\n // ════════════════════════════════════════════════ TIPS LOGIC ═════════════════════════════════════════════════════\n\n /**\n * @notice Distributes tips using the first Receipt from the \"receipt quarantine queue\".\n * Possible scenarios:\n * - Receipt queue is empty =\u003e does nothing\n * - Receipt optimistic period is not over =\u003e does nothing\n * - Either of Notaries present in Receipt was slashed =\u003e receipt is deleted from the queue\n * - Either of Notaries present in Receipt in Dispute =\u003e receipt is moved to the end of queue\n * - None of the above =\u003e receipt tips are distributed\n * @dev Returned value makes it possible to do the following: `while (distributeTips()) {}`\n * @return queuePopped Whether the first element was popped from the queue\n */\n function distributeTips() external returns (bool queuePopped);\n\n /**\n * @notice Withdraws locked base message tips from requested domain Origin to the recipient.\n * This is done by a call to a local Origin contract, or by a manager message to the remote chain.\n * @dev This will revert, if the pending balance of origin tips (earned-claimed) is lower than requested.\n * @param origin Domain of chain to withdraw tips on\n * @param amount Amount of tips to withdraw\n */\n function withdrawTips(uint32 origin, uint256 amount) external;\n\n // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════\n\n /**\n * @notice Returns earned and claimed tips for the actor.\n * Note: Tips for address(0) belong to the Treasury.\n * @param actor Address of the actor\n * @param origin Domain where the tips were initially paid\n * @return earned Total amount of origin tips the actor has earned so far\n * @return claimed Total amount of origin tips the actor has claimed so far\n */\n function actorTips(address actor, uint32 origin) external view returns (uint128 earned, uint128 claimed);\n\n /**\n * @notice Returns the amount of receipts in the \"Receipt Quarantine Queue\".\n */\n function receiptQueueLength() external view returns (uint256);\n\n /**\n * @notice Returns the state with the highest known nonce\n * submitted by any of the currently active Guards.\n * @param origin Domain of origin chain\n * @return statePayload Raw payload with latest active Guard state for origin\n */\n function getLatestState(uint32 origin) external view returns (bytes memory statePayload);\n}\n\n// node_modules/@openzeppelin/contracts/utils/Strings.sol\n\n// OpenZeppelin Contracts (last updated v4.9.0) (utils/Strings.sol)\n\n/**\n * @dev String operations.\n */\nlibrary Strings {\n bytes16 private constant _SYMBOLS = \"0123456789abcdef\";\n uint8 private constant _ADDRESS_LENGTH = 20;\n\n /**\n * @dev Converts a `uint256` to its ASCII `string` decimal representation.\n */\n function toString(uint256 value) internal pure returns (string memory) {\n unchecked {\n uint256 length = Math.log10(value) + 1;\n string memory buffer = new string(length);\n uint256 ptr;\n /// @solidity memory-safe-assembly\n assembly {\n ptr := add(buffer, add(32, length))\n }\n while (true) {\n ptr--;\n /// @solidity memory-safe-assembly\n assembly {\n mstore8(ptr, byte(mod(value, 10), _SYMBOLS))\n }\n value /= 10;\n if (value == 0) break;\n }\n return buffer;\n }\n }\n\n /**\n * @dev Converts a `int256` to its ASCII `string` decimal representation.\n */\n function toString(int256 value) internal pure returns (string memory) {\n return string(abi.encodePacked(value \u003c 0 ? \"-\" : \"\", toString(SignedMath.abs(value))));\n }\n\n /**\n * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation.\n */\n function toHexString(uint256 value) internal pure returns (string memory) {\n unchecked {\n return toHexString(value, Math.log256(value) + 1);\n }\n }\n\n /**\n * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length.\n */\n function toHexString(uint256 value, uint256 length) internal pure returns (string memory) {\n bytes memory buffer = new bytes(2 * length + 2);\n buffer[0] = \"0\";\n buffer[1] = \"x\";\n for (uint256 i = 2 * length + 1; i \u003e 1; --i) {\n buffer[i] = _SYMBOLS[value \u0026 0xf];\n value \u003e\u003e= 4;\n }\n require(value == 0, \"Strings: hex length insufficient\");\n return string(buffer);\n }\n\n /**\n * @dev Converts an `address` with fixed length of 20 bytes to its not checksummed ASCII `string` hexadecimal representation.\n */\n function toHexString(address addr) internal pure returns (string memory) {\n return toHexString(uint256(uint160(addr)), _ADDRESS_LENGTH);\n }\n\n /**\n * @dev Returns true if the two strings are equal.\n */\n function equal(string memory a, string memory b) internal pure returns (bool) {\n return keccak256(bytes(a)) == keccak256(bytes(b));\n }\n}\n\n// node_modules/@openzeppelin/contracts-upgradeable/utils/ContextUpgradeable.sol\n\n// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)\n\n/**\n * @dev Provides information about the current execution context, including the\n * sender of the transaction and its data. While these are generally available\n * via msg.sender and msg.data, they should not be accessed in such a direct\n * manner, since when dealing with meta-transactions the account sending and\n * paying for execution may not be the actual sender (as far as an application\n * is concerned).\n *\n * This contract is only required for intermediate, library-like contracts.\n */\nabstract contract ContextUpgradeable is Initializable {\n function __Context_init() internal onlyInitializing {\n }\n\n function __Context_init_unchained() internal onlyInitializing {\n }\n function _msgSender() internal view virtual returns (address) {\n return msg.sender;\n }\n\n function _msgData() internal view virtual returns (bytes calldata) {\n return msg.data;\n }\n\n /**\n * @dev This empty reserved space is put in place to allow future versions to add new\n * variables without shifting down storage in the inheritance chain.\n * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\n */\n uint256[50] private __gap;\n}\n\n// contracts/libs/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/utils/cryptography/ECDSA.sol\n\n// OpenZeppelin Contracts (last updated v4.9.0) (utils/cryptography/ECDSA.sol)\n\n/**\n * @dev Elliptic Curve Digital Signature Algorithm (ECDSA) operations.\n *\n * These functions can be used to verify that a message was signed by the holder\n * of the private keys of a given address.\n */\nlibrary ECDSA {\n enum RecoverError {\n NoError,\n InvalidSignature,\n InvalidSignatureLength,\n InvalidSignatureS,\n InvalidSignatureV // Deprecated in v4.8\n }\n\n function _throwError(RecoverError error) private pure {\n if (error == RecoverError.NoError) {\n return; // no error: do nothing\n } else if (error == RecoverError.InvalidSignature) {\n revert(\"ECDSA: invalid signature\");\n } else if (error == RecoverError.InvalidSignatureLength) {\n revert(\"ECDSA: invalid signature length\");\n } else if (error == RecoverError.InvalidSignatureS) {\n revert(\"ECDSA: invalid signature 's' value\");\n }\n }\n\n /**\n * @dev Returns the address that signed a hashed message (`hash`) with\n * `signature` or error string. This address can then be used for verification purposes.\n *\n * The `ecrecover` EVM opcode allows for malleable (non-unique) signatures:\n * this function rejects them by requiring the `s` value to be in the lower\n * half order, and the `v` value to be either 27 or 28.\n *\n * IMPORTANT: `hash` _must_ be the result of a hash operation for the\n * verification to be secure: it is possible to craft signatures that\n * recover to arbitrary addresses for non-hashed data. A safe way to ensure\n * this is by receiving a hash of the original message (which may otherwise\n * be too long), and then calling {toEthSignedMessageHash} on it.\n *\n * Documentation for signature generation:\n * - with https://web3js.readthedocs.io/en/v1.3.4/web3-eth-accounts.html#sign[Web3.js]\n * - with https://docs.ethers.io/v5/api/signer/#Signer-signMessage[ethers]\n *\n * _Available since v4.3._\n */\n function tryRecover(bytes32 hash, bytes memory signature) internal pure returns (address, RecoverError) {\n if (signature.length == 65) {\n bytes32 r;\n bytes32 s;\n uint8 v;\n // ecrecover takes the signature parameters, and the only way to get them\n // currently is to use assembly.\n /// @solidity memory-safe-assembly\n assembly {\n r := mload(add(signature, 0x20))\n s := mload(add(signature, 0x40))\n v := byte(0, mload(add(signature, 0x60)))\n }\n return tryRecover(hash, v, r, s);\n } else {\n return (address(0), RecoverError.InvalidSignatureLength);\n }\n }\n\n /**\n * @dev Returns the address that signed a hashed message (`hash`) with\n * `signature`. This address can then be used for verification purposes.\n *\n * The `ecrecover` EVM opcode allows for malleable (non-unique) signatures:\n * this function rejects them by requiring the `s` value to be in the lower\n * half order, and the `v` value to be either 27 or 28.\n *\n * IMPORTANT: `hash` _must_ be the result of a hash operation for the\n * verification to be secure: it is possible to craft signatures that\n * recover to arbitrary addresses for non-hashed data. A safe way to ensure\n * this is by receiving a hash of the original message (which may otherwise\n * be too long), and then calling {toEthSignedMessageHash} on it.\n */\n function recover(bytes32 hash, bytes memory signature) internal pure returns (address) {\n (address recovered, RecoverError error) = tryRecover(hash, signature);\n _throwError(error);\n return recovered;\n }\n\n /**\n * @dev Overload of {ECDSA-tryRecover} that receives the `r` and `vs` short-signature fields separately.\n *\n * See https://eips.ethereum.org/EIPS/eip-2098[EIP-2098 short signatures]\n *\n * _Available since v4.3._\n */\n function tryRecover(bytes32 hash, bytes32 r, bytes32 vs) internal pure returns (address, RecoverError) {\n bytes32 s = vs \u0026 bytes32(0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff);\n uint8 v = uint8((uint256(vs) \u003e\u003e 255) + 27);\n return tryRecover(hash, v, r, s);\n }\n\n /**\n * @dev Overload of {ECDSA-recover} that receives the `r and `vs` short-signature fields separately.\n *\n * _Available since v4.2._\n */\n function recover(bytes32 hash, bytes32 r, bytes32 vs) internal pure returns (address) {\n (address recovered, RecoverError error) = tryRecover(hash, r, vs);\n _throwError(error);\n return recovered;\n }\n\n /**\n * @dev Overload of {ECDSA-tryRecover} that receives the `v`,\n * `r` and `s` signature fields separately.\n *\n * _Available since v4.3._\n */\n function tryRecover(bytes32 hash, uint8 v, bytes32 r, bytes32 s) internal pure returns (address, RecoverError) {\n // EIP-2 still allows signature malleability for ecrecover(). Remove this possibility and make the signature\n // unique. Appendix F in the Ethereum Yellow paper (https://ethereum.github.io/yellowpaper/paper.pdf), defines\n // the valid range for s in (301): 0 \u003c s \u003c secp256k1n ÷ 2 + 1, and for v in (302): v ∈ {27, 28}. Most\n // signatures from current libraries generate a unique signature with an s-value in the lower half order.\n //\n // If your library generates malleable signatures, such as s-values in the upper range, calculate a new s-value\n // with 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141 - s1 and flip v from 27 to 28 or\n // vice versa. If your library also generates signatures with 0/1 for v instead 27/28, add 27 to v to accept\n // these malleable signatures as well.\n if (uint256(s) \u003e 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0) {\n return (address(0), RecoverError.InvalidSignatureS);\n }\n\n // If the signature is valid (and not malleable), return the signer address\n address signer = ecrecover(hash, v, r, s);\n if (signer == address(0)) {\n return (address(0), RecoverError.InvalidSignature);\n }\n\n return (signer, RecoverError.NoError);\n }\n\n /**\n * @dev Overload of {ECDSA-recover} that receives the `v`,\n * `r` and `s` signature fields separately.\n */\n function recover(bytes32 hash, uint8 v, bytes32 r, bytes32 s) internal pure returns (address) {\n (address recovered, RecoverError error) = tryRecover(hash, v, r, s);\n _throwError(error);\n return recovered;\n }\n\n /**\n * @dev Returns an Ethereum Signed Message, created from a `hash`. This\n * produces hash corresponding to the one signed with the\n * https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`]\n * JSON-RPC method as part of EIP-191.\n *\n * See {recover}.\n */\n function toEthSignedMessageHash(bytes32 hash) internal pure returns (bytes32 message) {\n // 32 is the length in bytes of hash,\n // enforced by the type signature above\n /// @solidity memory-safe-assembly\n assembly {\n mstore(0x00, \"\\x19Ethereum Signed Message:\\n32\")\n mstore(0x1c, hash)\n message := keccak256(0x00, 0x3c)\n }\n }\n\n /**\n * @dev Returns an Ethereum Signed Message, created from `s`. This\n * produces hash corresponding to the one signed with the\n * https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`]\n * JSON-RPC method as part of EIP-191.\n *\n * See {recover}.\n */\n function toEthSignedMessageHash(bytes memory s) internal pure returns (bytes32) {\n return keccak256(abi.encodePacked(\"\\x19Ethereum Signed Message:\\n\", Strings.toString(s.length), s));\n }\n\n /**\n * @dev Returns an Ethereum Signed Typed Data, created from a\n * `domainSeparator` and a `structHash`. This produces hash corresponding\n * to the one signed with the\n * https://eips.ethereum.org/EIPS/eip-712[`eth_signTypedData`]\n * JSON-RPC method as part of EIP-712.\n *\n * See {recover}.\n */\n function toTypedDataHash(bytes32 domainSeparator, bytes32 structHash) internal pure returns (bytes32 data) {\n /// @solidity memory-safe-assembly\n assembly {\n let ptr := mload(0x40)\n mstore(ptr, \"\\x19\\x01\")\n mstore(add(ptr, 0x02), domainSeparator)\n mstore(add(ptr, 0x22), structHash)\n data := keccak256(ptr, 0x42)\n }\n }\n\n /**\n * @dev Returns an Ethereum Signed Data with intended validator, created from a\n * `validator` and `data` according to the version 0 of EIP-191.\n *\n * See {recover}.\n */\n function toDataWithIntendedValidatorHash(address validator, bytes memory data) internal pure returns (bytes32) {\n return keccak256(abi.encodePacked(\"\\x19\\x00\", validator, data));\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/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/inbox/StatementInbox.sol\n\n// ══════════════════════════════ LIBRARY IMPORTS ══════════════════════════════\n\n// ═════════════════════════════ INTERNAL IMPORTS ══════════════════════════════\n\n// ═════════════════════════════ EXTERNAL IMPORTS ══════════════════════════════\n\n/// @notice `StatementInbox` is the entry point for all agent-signed statements. It verifies the\n/// agent signatures, and passes the unsigned statements to the contract to consume it via `acceptX` functions. Is is\n/// also used to verify the agent-signed statements and initiate the agent slashing, should the statement be invalid.\n/// `StatementInbox` is responsible for the following:\n/// - Accepting State and Receipt Reports to initiate a dispute between Guard and Notary.\n/// - Storing all the Guard Reports with the Guard signature leading to a dispute.\n/// - Verifying State/State Reports referencing the local chain and slashing the signer if statement is invalid.\n/// - Verifying Receipt/Receipt Reports referencing the local chain and slashing the signer if statement is invalid.\nabstract contract StatementInbox is MessagingBase, StatementInboxEvents, IStatementInbox {\n using AttestationLib for bytes;\n using ReceiptLib for bytes;\n using StateLib for bytes;\n using SnapshotLib for bytes;\n\n struct StoredReport {\n uint256 sigIndex;\n bytes statementPayload;\n }\n\n // ══════════════════════════════════════════════════ STORAGE ══════════════════════════════════════════════════════\n\n address public agentManager;\n address public origin;\n address public destination;\n\n // TODO: optimize this\n bytes[] internal _storedSignatures;\n StoredReport[] internal _storedReports;\n\n /// @dev gap for upgrade safety\n uint256[45] private __GAP; // solhint-disable-line var-name-mixedcase\n\n // ════════════════════════════════════════════════ INITIALIZER ════════════════════════════════════════════════════\n\n /// @dev Initializes the contract:\n /// - Sets up `msg.sender` as the owner of the contract.\n /// - Sets up `agentManager`, `origin`, and `destination`.\n // solhint-disable-next-line func-name-mixedcase\n function __StatementInbox_init(address agentManager_, address origin_, address destination_)\n internal\n onlyInitializing\n {\n agentManager = agentManager_;\n origin = origin_;\n destination = destination_;\n __Ownable2Step_init();\n }\n\n // ══════════════════════════════════════════ SUBMIT AGENT STATEMENTS ══════════════════════════════════════════════\n\n /// @inheritdoc IStatementInbox\n // solhint-disable-next-line ordering\n function submitStateReportWithSnapshot(\n uint8 stateIndex,\n bytes memory srSignature,\n bytes memory snapPayload,\n bytes memory snapSignature\n ) external returns (bool wasAccepted) {\n // This will revert if payload is not a snapshot\n Snapshot snapshot = snapPayload.castToSnapshot();\n // This will revert if the snapshot signer is not a known Notary\n (AgentStatus memory notaryStatus,) =\n _verifySnapshot({snapshot: snapshot, snapSignature: snapSignature, verifyNotary: true});\n // Notary needs to be Active/Unstaking\n notaryStatus.verifyActiveUnstaking();\n // Check if Notary is active on this chain\n _verifyNotaryDomain(notaryStatus.domain);\n // This will revert if state index is out of range\n State state = snapshot.state(stateIndex);\n // This will revert if the report signer is not an known Guard\n (AgentStatus memory guardStatus,) = _verifyStateReport(state, srSignature);\n // Check that Guard is active\n guardStatus.verifyActive();\n _saveReport(state.unwrap().clone(), srSignature);\n // This will revert if either actor is already in dispute\n IAgentManager(agentManager).openDispute(guardStatus.index, notaryStatus.index);\n return true;\n }\n\n /// @inheritdoc IStatementInbox\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 // This will revert if payload is not a snapshot\n Snapshot snapshot = snapPayload.castToSnapshot();\n // This will revert if state index is out of range\n State state = snapshot.state(stateIndex);\n // This will revert if the report signer is not an known Guard\n (AgentStatus memory guardStatus,) = _verifyStateReport(state, srSignature);\n // Check that Guard is active\n guardStatus.verifyActive();\n // This will revert if payload is not an attestation\n Attestation att = attPayload.castToAttestation();\n // This will revert if signer is not an known Notary\n (AgentStatus memory notaryStatus,) = _verifyAttestation(att, attSignature);\n // Notary needs to be Active/Unstaking\n notaryStatus.verifyActiveUnstaking();\n // Check if Notary is active on this chain\n _verifyNotaryDomain(notaryStatus.domain);\n if (snapshot.calculateRoot() != att.snapRoot()) revert IncorrectSnapshotRoot();\n _saveReport(state.unwrap().clone(), srSignature);\n // This will revert if either actor is already in dispute\n IAgentManager(agentManager).openDispute(guardStatus.index, notaryStatus.index);\n return true;\n }\n\n /// @inheritdoc IStatementInbox\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 // This will revert if payload is not a state\n State state = statePayload.castToState();\n // This will revert if the report signer is not an known Guard\n (AgentStatus memory guardStatus,) = _verifyStateReport(state, srSignature);\n // Check that Guard is active\n guardStatus.verifyActive();\n // This will revert if payload is not an attestation\n Attestation att = attPayload.castToAttestation();\n // This will revert if signer is not a known Notary\n (AgentStatus memory notaryStatus,) = _verifyAttestation(att, attSignature);\n // Notary needs to be Active/Unstaking\n notaryStatus.verifyActiveUnstaking();\n // Check if Notary is active on this chain\n _verifyNotaryDomain(notaryStatus.domain);\n // This will revert if any of these is true:\n // - Attestation root is not equal to Merkle Root derived from State and Snapshot Proof.\n // - Snapshot Proof's first element does not match the State metadata.\n // - Snapshot Proof length exceeds Snapshot tree Height.\n // - State index is out of range.\n _verifySnapshotMerkle(att, stateIndex, state, snapProof);\n _saveReport(statePayload, srSignature);\n // This will revert if either actor is already in dispute\n IAgentManager(agentManager).openDispute(guardStatus.index, notaryStatus.index);\n return true;\n }\n\n // ══════════════════════════════════════════ VERIFY AGENT STATEMENTS ══════════════════════════════════════════════\n\n /// @inheritdoc IStatementInbox\n function verifyReceipt(bytes memory rcptPayload, bytes memory rcptSignature)\n external\n returns (bool isValidReceipt)\n {\n // This will revert if payload is not a receipt\n Receipt rcpt = rcptPayload.castToReceipt();\n // This will revert if the attestation signer is not a known Notary\n (AgentStatus memory status, address notary) = _verifyReceipt(rcpt, rcptSignature);\n // Notary needs to be Active/Unstaking\n status.verifyActiveUnstaking();\n isValidReceipt = IExecutionHub(destination).isValidReceipt(rcptPayload);\n if (!isValidReceipt) {\n emit InvalidReceipt(rcptPayload, rcptSignature);\n IAgentManager(agentManager).slashAgent(status.domain, notary, msg.sender);\n }\n }\n\n /// @inheritdoc IStatementInbox\n function verifyReceiptReport(bytes memory rcptPayload, bytes memory rrSignature)\n external\n returns (bool isValidReport)\n {\n // This will revert if payload is not a receipt\n Receipt rcpt = rcptPayload.castToReceipt();\n // This will revert if the report signer is not a known Guard\n (AgentStatus memory status, address guard) = _verifyReceiptReport(rcpt, rrSignature);\n // Guard needs to be Active/Unstaking\n status.verifyActiveUnstaking();\n // Report is valid IF AND ONLY IF the reported receipt in invalid\n isValidReport = !IExecutionHub(destination).isValidReceipt(rcptPayload);\n if (!isValidReport) {\n emit InvalidReceiptReport(rcptPayload, rrSignature);\n IAgentManager(agentManager).slashAgent(status.domain, guard, msg.sender);\n }\n }\n\n /// @inheritdoc IStatementInbox\n function verifyStateWithAttestation(\n uint8 stateIndex,\n bytes memory snapPayload,\n bytes memory attPayload,\n bytes memory attSignature\n ) external returns (bool isValidState) {\n // This will revert if payload is not an attestation\n Attestation att = attPayload.castToAttestation();\n // This will revert if the attestation signer is not a known Notary\n (AgentStatus memory status, address notary) = _verifyAttestation(att, attSignature);\n // Notary needs to be Active/Unstaking\n status.verifyActiveUnstaking();\n // This will revert if payload is not a snapshot\n Snapshot snapshot = snapPayload.castToSnapshot();\n if (snapshot.calculateRoot() != att.snapRoot()) revert IncorrectSnapshotRoot();\n // This will revert if state does not refer to this chain\n bytes memory statePayload = snapshot.state(stateIndex).unwrap().clone();\n isValidState = IStateHub(origin).isValidState(statePayload);\n if (!isValidState) {\n emit InvalidStateWithAttestation(stateIndex, statePayload, attPayload, attSignature);\n IAgentManager(agentManager).slashAgent(status.domain, notary, msg.sender);\n }\n }\n\n /// @inheritdoc IStatementInbox\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 // This will revert if payload is not an attestation\n Attestation att = attPayload.castToAttestation();\n // This will revert if the attestation signer is not a known Notary\n (AgentStatus memory status, address notary) = _verifyAttestation(att, attSignature);\n // Notary needs to be Active/Unstaking\n status.verifyActiveUnstaking();\n // This will revert if payload is not a state\n State state = statePayload.castToState();\n // This will revert if any of these is true:\n // - Attestation root is not equal to Merkle Root derived from State and Snapshot Proof.\n // - Snapshot Proof's first element does not match the State metadata.\n // - Snapshot Proof length exceeds Snapshot tree Height.\n // - State index is out of range.\n _verifySnapshotMerkle(att, stateIndex, state, snapProof);\n // This will revert if state does not refer to this chain\n isValidState = IStateHub(origin).isValidState(statePayload);\n if (!isValidState) {\n emit InvalidStateWithAttestation(stateIndex, statePayload, attPayload, attSignature);\n IAgentManager(agentManager).slashAgent(status.domain, notary, msg.sender);\n }\n }\n\n /// @inheritdoc IStatementInbox\n function verifyStateWithSnapshot(uint8 stateIndex, bytes memory snapPayload, bytes memory snapSignature)\n external\n returns (bool isValidState)\n {\n // This will revert if payload is not a snapshot\n Snapshot snapshot = snapPayload.castToSnapshot();\n // This will revert if the snapshot signer is not a known Guard/Notary\n (AgentStatus memory status, address agent) =\n _verifySnapshot({snapshot: snapshot, snapSignature: snapSignature, verifyNotary: false});\n // Agent needs to be Active/Unstaking\n status.verifyActiveUnstaking();\n // This will revert if state does not refer to this chain\n isValidState = IStateHub(origin).isValidState(snapshot.state(stateIndex).unwrap().clone());\n if (!isValidState) {\n emit InvalidStateWithSnapshot(stateIndex, snapPayload, snapSignature);\n IAgentManager(agentManager).slashAgent(status.domain, agent, msg.sender);\n }\n }\n\n /// @inheritdoc IStatementInbox\n function verifyStateReport(bytes memory statePayload, bytes memory srSignature)\n external\n returns (bool isValidReport)\n {\n // This will revert if payload is not a state\n State state = statePayload.castToState();\n // This will revert if the report signer is not a known Guard\n (AgentStatus memory status, address guard) = _verifyStateReport(state, srSignature);\n // Guard needs to be Active/Unstaking\n status.verifyActiveUnstaking();\n // Report is valid IF AND ONLY IF the reported state in invalid\n // This will revert if the reported state does not refer to this chain\n isValidReport = !IStateHub(origin).isValidState(statePayload);\n if (!isValidReport) {\n emit InvalidStateReport(statePayload, srSignature);\n IAgentManager(agentManager).slashAgent(status.domain, guard, msg.sender);\n }\n }\n\n // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════\n\n /// @inheritdoc IStatementInbox\n function getReportsAmount() external view returns (uint256) {\n return _storedReports.length;\n }\n\n /// @inheritdoc IStatementInbox\n function getGuardReport(uint256 index)\n external\n view\n returns (bytes memory statementPayload, bytes memory reportSignature)\n {\n if (index \u003e= _storedReports.length) revert IndexOutOfRange();\n StoredReport memory storedReport = _storedReports[index];\n statementPayload = storedReport.statementPayload;\n reportSignature = _storedSignatures[storedReport.sigIndex];\n }\n\n /// @inheritdoc IStatementInbox\n function getStoredSignature(uint256 index) external view returns (bytes memory) {\n return _storedSignatures[index];\n }\n\n // ══════════════════════════════════════════════ INTERNAL LOGIC ═══════════════════════════════════════════════════\n\n /// @dev Saves the statement reported by Guard as invalid and the Guard Report signature.\n function _saveReport(bytes memory statementPayload, bytes memory reportSignature) internal {\n uint256 sigIndex = _saveSignature(reportSignature);\n _storedReports.push(StoredReport(sigIndex, statementPayload));\n }\n\n /// @dev Saves the signature and returns its index.\n function _saveSignature(bytes memory signature) internal returns (uint256 sigIndex) {\n sigIndex = _storedSignatures.length;\n _storedSignatures.push(signature);\n }\n\n // ═══════════════════════════════════════════════ AGENT CHECKS ════════════════════════════════════════════════════\n\n /**\n * @dev Recovers a signer from a hashed message, and a EIP-191 signature for it.\n * Will revert, if the signer is not a known agent.\n * @dev Agent flag could be any of these: Active/Unstaking/Resting/Fraudulent/Slashed\n * Further checks need to be performed in a caller function.\n * @param hashedStatement Hash of the statement that was signed by an Agent\n * @param signature Agent signature for the hashed statement\n * @return status Struct representing agent status:\n * - flag Unknown/Active/Unstaking/Resting/Fraudulent/Slashed\n * - domain Domain where agent is/was active\n * - index Index of agent in the Agent Merkle Tree\n * @return agent Agent that signed the statement\n */\n function _recoverAgent(bytes32 hashedStatement, bytes memory signature)\n internal\n view\n returns (AgentStatus memory status, address agent)\n {\n bytes32 ethSignedMsg = ECDSA.toEthSignedMessageHash(hashedStatement);\n agent = ECDSA.recover(ethSignedMsg, signature);\n status = IAgentManager(agentManager).agentStatus(agent);\n // Discard signature of unknown agents.\n // Further flag checks are supposed to be performed in a caller function.\n status.verifyKnown();\n }\n\n /// @dev Verifies that Notary signature is active on local domain.\n function _verifyNotaryDomain(uint32 notaryDomain) internal view {\n // Notary needs to be from the local domain (if contract is not deployed on Synapse Chain).\n // Or Notary could be from any domain (if contract is deployed on Synapse Chain).\n if (notaryDomain != localDomain \u0026\u0026 localDomain != synapseDomain) revert IncorrectAgentDomain();\n }\n\n // ════════════════════════════════════════ ATTESTATION RELATED CHECKS ═════════════════════════════════════════════\n\n /**\n * @dev Internal function to verify the signed attestation payload.\n * Reverts if any of these is true:\n * - Attestation signer is not a known Notary.\n * @param att Typed memory view over attestation payload\n * @param attSignature Notary signature for the attestation\n * @return status Struct representing agent status, see {_recoverAgent}\n * @return notary Notary that signed the snapshot\n */\n function _verifyAttestation(Attestation att, bytes memory attSignature)\n internal\n view\n returns (AgentStatus memory status, address notary)\n {\n // This will revert if signer is not a known agent\n (status, notary) = _recoverAgent(att.hashValid(), attSignature);\n // Attestation signer needs to be a Notary, not a Guard\n if (status.domain == 0) revert AgentNotNotary();\n }\n\n /**\n * @dev Internal function to verify the signed attestation report payload.\n * Reverts if any of these is true:\n * - Report signer is not a known Guard.\n * @param att Typed memory view over attestation payload that Guard reports as invalid\n * @param arSignature Guard signature for the \"invalid attestation\" report\n * @return status Struct representing guard status, see {_recoverAgent}\n * @return guard Guard that signed the report\n */\n function _verifyAttestationReport(Attestation att, bytes memory arSignature)\n internal\n view\n returns (AgentStatus memory status, address guard)\n {\n // This will revert if signer is not a known agent\n (status, guard) = _recoverAgent(att.hashInvalid(), arSignature);\n // Report signer needs to be a Guard, not a Notary\n if (status.domain != 0) revert AgentNotGuard();\n }\n\n // ══════════════════════════════════════════ RECEIPT RELATED CHECKS ═══════════════════════════════════════════════\n\n /**\n * @dev Internal function to verify the signed receipt payload.\n * Reverts if any of these is true:\n * - Receipt signer is not a known Notary.\n * @param rcpt Typed memory view over receipt payload\n * @param rcptSignature Notary signature for the receipt\n * @return status Struct representing agent status, see {_recoverAgent}\n * @return notary Notary that signed the snapshot\n */\n function _verifyReceipt(Receipt rcpt, bytes memory rcptSignature)\n internal\n view\n returns (AgentStatus memory status, address notary)\n {\n // This will revert if signer is not a known agent\n (status, notary) = _recoverAgent(rcpt.hashValid(), rcptSignature);\n // Receipt signer needs to be a Notary, not a Guard\n if (status.domain == 0) revert AgentNotNotary();\n }\n\n /**\n * @dev Internal function to verify the signed receipt report payload.\n * Reverts if any of these is true:\n * - Report signer is not a known Guard.\n * @param rcpt Typed memory view over receipt payload that Guard reports as invalid\n * @param rrSignature Guard signature for the \"invalid receipt\" report\n * @return status Struct representing guard status, see {_recoverAgent}\n * @return guard Guard that signed the report\n */\n function _verifyReceiptReport(Receipt rcpt, bytes memory rrSignature)\n internal\n view\n returns (AgentStatus memory status, address guard)\n {\n // This will revert if signer is not a known agent\n (status, guard) = _recoverAgent(rcpt.hashInvalid(), rrSignature);\n // Report signer needs to be a Guard, not a Notary\n if (status.domain != 0) revert AgentNotGuard();\n }\n\n // ═══════════════════════════════════════ STATE/SNAPSHOT RELATED CHECKS ═══════════════════════════════════════════\n\n /**\n * @dev Internal function to verify the signed snapshot report payload.\n * Reverts if any of these is true:\n * - Report signer is not a known Guard.\n * @param state Typed memory view over state payload that Guard reports as invalid\n * @param srSignature Guard signature for the report\n * @return status Struct representing guard status, see {_recoverAgent}\n * @return guard Guard that signed the report\n */\n function _verifyStateReport(State state, bytes memory srSignature)\n internal\n view\n returns (AgentStatus memory status, address guard)\n {\n // This will revert if signer is not a known agent\n (status, guard) = _recoverAgent(state.hashInvalid(), srSignature);\n // Report signer needs to be a Guard, not a Notary\n if (status.domain != 0) revert AgentNotGuard();\n }\n\n /**\n * @dev Internal function to verify the signed snapshot payload.\n * Reverts if any of these is true:\n * - Snapshot signer is not a known Agent.\n * - Snapshot signer is not a Notary (if verifyNotary is true).\n * @param snapshot Typed memory view over snapshot payload\n * @param snapSignature Agent signature for the snapshot\n * @param verifyNotary If true, snapshot signer needs to be a Notary, not a Guard\n * @return status Struct representing agent status, see {_recoverAgent}\n * @return agent Agent that signed the snapshot\n */\n function _verifySnapshot(Snapshot snapshot, bytes memory snapSignature, bool verifyNotary)\n internal\n view\n returns (AgentStatus memory status, address agent)\n {\n // This will revert if signer is not a known agent\n (status, agent) = _recoverAgent(snapshot.hashValid(), snapSignature);\n // If requested, snapshot signer needs to be a Notary, not a Guard\n if (verifyNotary \u0026\u0026 status.domain == 0) revert AgentNotNotary();\n }\n\n // ═══════════════════════════════════════════ MERKLE RELATED CHECKS ═══════════════════════════════════════════════\n\n /**\n * @dev Internal function to verify that snapshot roots match.\n * Reverts if any of these is true:\n * - Attestation root is not equal to Merkle Root derived from State and Snapshot Proof.\n * - Snapshot Proof's first element does not match the State metadata.\n * - Snapshot Proof length exceeds Snapshot tree Height.\n * - State index is out of range.\n * @param att Typed memory view over Attestation\n * @param stateIndex Index of state in the snapshot\n * @param state Typed memory view over the provided state payload\n * @param snapProof Raw payload with snapshot data\n */\n function _verifySnapshotMerkle(Attestation att, uint8 stateIndex, State state, bytes32[] memory snapProof)\n internal\n pure\n {\n // Snapshot proof first element should match State metadata (aka \"right sub-leaf\")\n (, bytes32 rightSubLeaf) = state.subLeafs();\n if (snapProof[0] != rightSubLeaf) revert IncorrectSnapshotProof();\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(state.root(), state.origin(), snapProof, stateIndex);\n // Snapshot root should match the attestation root\n if (att.snapRoot() != snapshotRoot) revert IncorrectSnapshotRoot();\n }\n}\n\n// contracts/inbox/Inbox.sol\n\n// ══════════════════════════════ LIBRARY IMPORTS ══════════════════════════════\n\n// ═════════════════════════════ INTERNAL IMPORTS ══════════════════════════════\n\n/// @notice `Inbox` is the child of `StatementInbox` contract, that is used on Synapse Chain.\n/// In addition to the functionality of `StatementInbox`, it also:\n/// - Accepts Guard and Notary Snapshots and passes them to `Summit` contract.\n/// - Accepts Notary-signed Receipts and passes them to `Summit` contract.\n/// - Accepts Receipt Reports to initiate a dispute between Guard and Notary.\n/// - Verifies Attestations and Attestation Reports, and slashes the signer if they are invalid.\ncontract Inbox is StatementInbox, InboxEvents, InterfaceInbox {\n using AttestationLib for bytes;\n using ReceiptLib for bytes;\n using SnapshotLib for bytes;\n\n // Struct to get around stack too deep error. TODO: revisit this\n struct ReceiptInfo {\n AgentStatus rcptNotaryStatus;\n address notary;\n uint32 attNonce;\n AgentStatus attNotaryStatus;\n }\n\n // ══════════════════════════════════════════════════ STORAGE ══════════════════════════════════════════════════════\n\n // The address of the Summit contract.\n address public summit;\n\n // ═════════════════════════════════════════ CONSTRUCTOR \u0026 INITIALIZER ═════════════════════════════════════════════\n\n constructor(uint32 synapseDomain_) MessagingBase(\"0.0.3\", synapseDomain_) {\n if (localDomain != synapseDomain) revert MustBeSynapseDomain();\n }\n\n /// @notice Initializes `Inbox` contract:\n /// - Sets `msg.sender` as the owner of the contract\n /// - Sets `agentManager`, `origin`, `destination` and `summit` addresses\n function initialize(address agentManager_, address origin_, address destination_, address summit_)\n external\n initializer\n {\n __StatementInbox_init(agentManager_, origin_, destination_);\n summit = summit_;\n }\n\n // ══════════════════════════════════════════ SUBMIT AGENT STATEMENTS ══════════════════════════════════════════════\n\n /// @inheritdoc InterfaceInbox\n function submitSnapshot(bytes memory snapPayload, bytes memory snapSignature)\n external\n returns (bytes memory attPayload, bytes32 agentRoot_, uint256[] memory snapGas)\n {\n // This will revert if payload is not a snapshot\n Snapshot snapshot = snapPayload.castToSnapshot();\n // This will revert if the signer is not a known Guard/Notary\n (AgentStatus memory status, address agent) =\n _verifySnapshot({snapshot: snapshot, snapSignature: snapSignature, verifyNotary: false});\n // Check that Agent is active\n status.verifyActive();\n // Store Agent signature for the Snapshot\n uint256 sigIndex = _saveSignature(snapSignature);\n if (status.domain == 0) {\n // Guard that is in Dispute could still submit new snapshots, so we don't check that\n InterfaceSummit(summit).acceptGuardSnapshot({\n guardIndex: status.index,\n sigIndex: sigIndex,\n snapPayload: snapPayload\n });\n } else {\n // Get current agentRoot from AgentManager\n agentRoot_ = IAgentManager(agentManager).agentRoot();\n // This will revert if Notary is in Dispute\n attPayload = InterfaceSummit(summit).acceptNotarySnapshot({\n notaryIndex: status.index,\n sigIndex: sigIndex,\n agentRoot: agentRoot_,\n snapPayload: snapPayload\n });\n ChainGas[] memory snapGas_ = snapshot.snapGas();\n // Pass created attestation to Destination to enable executing messages coming to Synapse Chain\n InterfaceDestination(destination).acceptAttestation(\n status.index, type(uint256).max, attPayload, agentRoot_, snapGas_\n );\n // Use assembly to cast ChainGas[] to uint256[] without copying. Highest bits are left zeroed.\n // solhint-disable-next-line no-inline-assembly\n assembly {\n snapGas := snapGas_\n }\n }\n emit SnapshotAccepted(status.domain, agent, snapPayload, snapSignature);\n }\n\n /// @inheritdoc InterfaceInbox\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 // Struct to get around stack too deep error.\n ReceiptInfo memory info;\n // This will revert if payload is not a receipt\n Receipt rcpt = rcptPayload.castToReceipt();\n // This will revert if the receipt signer is not a known Notary\n (info.rcptNotaryStatus, info.notary) = _verifyReceipt(rcpt, rcptSignature);\n // Receipt Notary needs to be Active\n info.rcptNotaryStatus.verifyActive();\n info.attNonce = IExecutionHub(destination).getAttestationNonce(rcpt.snapshotRoot());\n if (info.attNonce == 0) revert IncorrectSnapshotRoot();\n // Attestation Notary domain needs to match the destination domain\n info.attNotaryStatus = IAgentManager(agentManager).agentStatus(rcpt.attNotary());\n if (info.attNotaryStatus.domain != rcpt.destination()) revert IncorrectAgentDomain();\n // Check that the correct tip values for the message were provided\n _verifyReceiptTips(rcpt.messageHash(), paddedTips, headerHash, bodyHash);\n // Store Notary signature for the Receipt\n uint256 sigIndex = _saveSignature(rcptSignature);\n // This will revert if Receipt Notary is in Dispute\n wasAccepted = InterfaceSummit(summit).acceptReceipt({\n rcptNotaryIndex: info.rcptNotaryStatus.index,\n attNotaryIndex: info.attNotaryStatus.index,\n sigIndex: sigIndex,\n attNonce: info.attNonce,\n paddedTips: paddedTips,\n rcptPayload: rcptPayload\n });\n if (wasAccepted) {\n emit ReceiptAccepted(info.rcptNotaryStatus.domain, info.notary, rcptPayload, rcptSignature);\n }\n }\n\n /// @inheritdoc InterfaceInbox\n function submitReceiptReport(bytes memory rcptPayload, bytes memory rcptSignature, bytes memory rrSignature)\n external\n returns (bool wasAccepted)\n {\n // This will revert if payload is not a receipt\n Receipt rcpt = rcptPayload.castToReceipt();\n // This will revert if the receipt signer is not a known Guard\n (AgentStatus memory guardStatus,) = _verifyReceiptReport(rcpt, rrSignature);\n // Guard needs to be Active\n guardStatus.verifyActive();\n // This will revert if report signer is not a known Notary\n (AgentStatus memory notaryStatus,) = _verifyReceipt(rcpt, rcptSignature);\n // Notary needs to be Active/Unstaking\n notaryStatus.verifyActiveUnstaking();\n _saveReport(rcptPayload, rrSignature);\n // This will revert if either actor is already in dispute\n IAgentManager(agentManager).openDispute(guardStatus.index, notaryStatus.index);\n return true;\n }\n\n /// @inheritdoc InterfaceInbox\n function passReceipt(uint32 attNotaryIndex, uint32 attNonce, uint256 paddedTips, bytes memory rcptPayload)\n external\n returns (bool wasAccepted)\n {\n // Only Destination can pass receipts\n if (msg.sender != destination) revert CallerNotDestination();\n return InterfaceSummit(summit).acceptReceipt({\n rcptNotaryIndex: attNotaryIndex,\n attNotaryIndex: attNotaryIndex,\n sigIndex: type(uint256).max,\n attNonce: attNonce,\n paddedTips: paddedTips,\n rcptPayload: rcptPayload\n });\n }\n\n // ══════════════════════════════════════════ VERIFY AGENT STATEMENTS ══════════════════════════════════════════════\n\n /// @inheritdoc InterfaceInbox\n function verifyAttestation(bytes memory attPayload, bytes memory attSignature)\n external\n returns (bool isValidAttestation)\n {\n // This will revert if payload is not an attestation\n Attestation att = attPayload.castToAttestation();\n // This will revert if the attestation signer is not a known Notary\n (AgentStatus memory status, address notary) = _verifyAttestation(att, attSignature);\n // Notary needs to be Active/Unstaking\n status.verifyActiveUnstaking();\n isValidAttestation = ISnapshotHub(summit).isValidAttestation(attPayload);\n if (!isValidAttestation) {\n emit InvalidAttestation(attPayload, attSignature);\n IAgentManager(agentManager).slashAgent(status.domain, notary, msg.sender);\n }\n }\n\n /// @inheritdoc InterfaceInbox\n function verifyAttestationReport(bytes memory attPayload, bytes memory arSignature)\n external\n returns (bool isValidReport)\n {\n // This will revert if payload is not an attestation\n Attestation att = attPayload.castToAttestation();\n // This will revert if the report signer is not a known Guard\n (AgentStatus memory status, address guard) = _verifyAttestationReport(att, arSignature);\n // Guard needs to be Active/Unstaking\n status.verifyActiveUnstaking();\n // Report is valid IF AND ONLY IF the reported attestation in invalid\n isValidReport = !ISnapshotHub(summit).isValidAttestation(attPayload);\n if (!isValidReport) {\n emit InvalidAttestationReport(attPayload, arSignature);\n IAgentManager(agentManager).slashAgent(status.domain, guard, msg.sender);\n }\n }\n\n // ══════════════════════════════════════════════ INTERNAL VIEWS ═══════════════════════════════════════════════════\n\n /// @dev Verifies that tips proof matches the message hash.\n function _verifyReceiptTips(bytes32 msgHash, uint256 paddedTips, bytes32 headerHash, bytes32 bodyHash)\n internal\n pure\n {\n Tips tips = TipsLib.wrapPadded(paddedTips);\n // full message leaf is (header, baseMessage), while base message leaf is (tips, remainingBody).\n if (MerkleMath.getParent(headerHash, MerkleMath.getParent(tips.leaf(), bodyHash)) != msgHash) {\n revert IncorrectTipsProof();\n }\n }\n}\n","language":"Solidity","languageVersion":"0.8.17","compilerVersion":"0.8.17","compilerOptions":"--combined-json bin,bin-runtime,srcmap,srcmap-runtime,abi,userdoc,devdoc,metadata,hashes --optimize --optimize-runs 10000 --allow-paths ., ./, ../","srcMap":"","srcMapRuntime":"","abiDefinition":[{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint8","name":"version","type":"uint8"}],"name":"Initialized","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferStarted","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"inputs":[],"name":"acceptOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"pendingOwner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"}],"userDoc":{"kind":"user","methods":{},"version":1},"developerDoc":{"details":"Contract module which provides access control mechanism, where there is an account (an owner) that can be granted exclusive access to specific functions. By default, the owner account will be the one that deploys the contract. This can later be changed with {transferOwnership} and {acceptOwnership}. This module is used through inheritance. It will make available all functions from parent (Ownable).","kind":"dev","methods":{"acceptOwnership()":{"details":"The new owner accepts the ownership transfer."},"owner()":{"details":"Returns the address of the current owner."},"pendingOwner()":{"details":"Returns the address of the pending owner."},"renounceOwnership()":{"details":"Leaves the contract without owner. It will not be possible to call `onlyOwner` functions. Can only be called by the current owner. NOTE: Renouncing ownership will leave the contract without an owner, thereby disabling any functionality that is only available to the owner."},"transferOwnership(address)":{"details":"Starts the ownership transfer of the contract to a new account. Replaces the pending transfer if there is one. Can only be called by the current owner."}},"stateVariables":{"__gap":{"details":"This empty reserved space is put in place to allow future versions to add new variables without shifting down storage in the inheritance chain. See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps"}},"version":1},"metadata":"{\"compiler\":{\"version\":\"0.8.17+commit.8df45f5f\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint8\",\"name\":\"version\",\"type\":\"uint8\"}],\"name\":\"Initialized\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"previousOwner\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"OwnershipTransferStarted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"previousOwner\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"OwnershipTransferred\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"acceptOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"pendingOwner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"renounceOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}],\"devdoc\":{\"details\":\"Contract module which provides access control mechanism, where there is an account (an owner) that can be granted exclusive access to specific functions. By default, the owner account will be the one that deploys the contract. This can later be changed with {transferOwnership} and {acceptOwnership}. This module is used through inheritance. It will make available all functions from parent (Ownable).\",\"kind\":\"dev\",\"methods\":{\"acceptOwnership()\":{\"details\":\"The new owner accepts the ownership transfer.\"},\"owner()\":{\"details\":\"Returns the address of the current owner.\"},\"pendingOwner()\":{\"details\":\"Returns the address of the pending owner.\"},\"renounceOwnership()\":{\"details\":\"Leaves the contract without owner. It will not be possible to call `onlyOwner` functions. Can only be called by the current owner. NOTE: Renouncing ownership will leave the contract without an owner, thereby disabling any functionality that is only available to the owner.\"},\"transferOwnership(address)\":{\"details\":\"Starts the ownership transfer of the contract to a new account. Replaces the pending transfer if there is one. Can only be called by the current owner.\"}},\"stateVariables\":{\"__gap\":{\"details\":\"This empty reserved space is put in place to allow future versions to add new variables without shifting down storage in the inheritance chain. See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\"}},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"solidity/Inbox.sol\":\"Ownable2StepUpgradeable\"},\"evmVersion\":\"london\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\"},\"optimizer\":{\"enabled\":true,\"runs\":10000},\"remappings\":[]},\"sources\":{\"solidity/Inbox.sol\":{\"keccak256\":\"0x9b516081a036814c0169e20e484d4a5499066b7a6f48fada952b5e844a1ca3e5\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://32bde393b3f24ef4307d9626d4143f337b3c0bd34e17bb969fd5a15221d96987\",\"dweb:/ipfs/QmTkt2XZRtgsbSpmsVQUM3c4ebETQoDVYbmEV9yheBghnr\"]}},\"version\":1}"},"hashes":{"acceptOwnership()":"79ba5097","owner()":"8da5cb5b","pendingOwner()":"e30c3978","renounceOwnership()":"715018a6","transferOwnership(address)":"f2fde38b"}},"solidity/Inbox.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/InboxEvents.sol\n\nabstract contract InboxEvents {\n /**\n * @notice Emitted when a snapshot is accepted by the Summit contract.\n * @param domain Domain where the signed Agent is active (ZERO for Guards)\n * @param agent Agent who signed the snapshot\n * @param snapPayload Raw payload with snapshot data\n * @param snapSignature Agent signature for the snapshot\n */\n event SnapshotAccepted(uint32 indexed domain, address indexed agent, bytes snapPayload, bytes snapSignature);\n\n /**\n * @notice Emitted when a snapshot is accepted by the Summit contract.\n * @param domain Domain where the signed Notary is active\n * @param notary Notary who signed the attestation\n * @param rcptPayload Raw payload with receipt data\n * @param rcptSignature Notary signature for the receipt\n */\n event ReceiptAccepted(uint32 domain, address notary, bytes rcptPayload, bytes rcptSignature);\n\n /**\n * @notice Emitted when a proof of invalid attestation is submitted.\n * @param attPayload Raw payload with Attestation data\n * @param attSignature Notary signature for the attestation\n */\n event InvalidAttestation(bytes attPayload, bytes attSignature);\n\n /**\n * @notice Emitted when a proof of invalid attestation report is submitted.\n * @param arPayload Raw payload with report data\n * @param arSignature Guard signature for the report\n */\n event InvalidAttestationReport(bytes arPayload, bytes arSignature);\n}\n\n// contracts/events/StatementInboxEvents.sol\n\nabstract contract StatementInboxEvents {\n // ════════════════════════════════════════════ STATEMENT ACCEPTED ═════════════════════════════════════════════════\n\n /**\n * @notice Emitted when a snapshot is accepted by the Destination contract.\n * @param domain Domain where the signed Notary is active\n * @param notary Notary who signed the attestation\n * @param attPayload Raw payload with attestation data\n * @param attSignature Notary signature for the attestation\n */\n event AttestationAccepted(uint32 domain, address notary, bytes attPayload, bytes attSignature);\n\n // ═════════════════════════════════════════ INVALID STATEMENT PROVED ══════════════════════════════════════════════\n\n /**\n * @notice Emitted when a proof of invalid receipt statement is submitted.\n * @param rcptPayload Raw payload with the receipt statement\n * @param rcptSignature Notary signature for the receipt statement\n */\n event InvalidReceipt(bytes rcptPayload, bytes rcptSignature);\n\n /**\n * @notice Emitted when a proof of invalid receipt report is submitted.\n * @param rrPayload Raw payload with report data\n * @param rrSignature Guard signature for the report\n */\n event InvalidReceiptReport(bytes rrPayload, bytes rrSignature);\n\n /**\n * @notice Emitted when a proof of invalid state in the signed attestation is submitted.\n * @param stateIndex Index of invalid state in the snapshot\n * @param statePayload Raw payload with state data\n * @param attPayload Raw payload with Attestation data for snapshot\n * @param attSignature Notary signature for the attestation\n */\n event InvalidStateWithAttestation(uint8 stateIndex, bytes statePayload, bytes attPayload, bytes attSignature);\n\n /**\n * @notice Emitted when a proof of invalid state in the signed snapshot is submitted.\n * @param stateIndex Index of invalid state in the snapshot\n * @param snapPayload Raw payload with snapshot data\n * @param snapSignature Agent signature for the snapshot\n */\n event InvalidStateWithSnapshot(uint8 stateIndex, bytes snapPayload, bytes snapSignature);\n\n /**\n * @notice Emitted when a proof of invalid state report is submitted.\n * @param srPayload Raw payload with report data\n * @param srSignature Guard signature for the report\n */\n event InvalidStateReport(bytes srPayload, bytes srSignature);\n}\n\n// contracts/interfaces/ISnapshotHub.sol\n\ninterface ISnapshotHub {\n /**\n * @notice Check that a given attestation is valid: matches the historical attestation\n * derived from an accepted Notary snapshot.\n * @dev Will revert if any of these is true:\n * - Attestation payload is not properly formatted.\n * @param attPayload Raw payload with attestation data\n * @return isValid Whether the provided attestation is valid\n */\n function isValidAttestation(bytes memory attPayload) external view returns (bool isValid);\n\n /**\n * @notice Returns saved attestation with the given nonce.\n * @dev Reverts if attestation with given nonce hasn't been created yet.\n * @param attNonce Nonce for the attestation\n * @return attPayload Raw payload with formatted Attestation data\n * @return agentRoot Agent root hash used for the attestation\n * @return snapGas Snapshot gas data used for the attestation\n */\n function getAttestation(uint32 attNonce)\n external\n view\n returns (bytes memory attPayload, bytes32 agentRoot, uint256[] memory snapGas);\n\n /**\n * @notice Returns the state with the highest known nonce submitted by a given Agent.\n * @param origin Domain of origin chain\n * @param agent Agent address\n * @return statePayload Raw payload with agent's latest state for origin\n */\n function getLatestAgentState(uint32 origin, address agent) external view returns (bytes memory statePayload);\n\n /**\n * @notice Returns latest saved attestation for a Notary.\n * @param notary Notary address\n * @return attPayload Raw payload with formatted Attestation data\n * @return agentRoot Agent root hash used for the attestation\n * @return snapGas Snapshot gas data used for the attestation\n */\n function getLatestNotaryAttestation(address notary)\n external\n view\n returns (bytes memory attPayload, bytes32 agentRoot, uint256[] memory snapGas);\n\n /**\n * @notice Returns Guard snapshot from the list of all accepted Guard snapshots.\n * @dev Reverts if snapshot with given index hasn't been accepted yet.\n * @param index Snapshot index in the list of all Guard snapshots\n * @return snapPayload Raw payload with Guard snapshot\n * @return snapSignature Raw payload with Guard signature for snapshot\n */\n function getGuardSnapshot(uint256 index)\n external\n view\n returns (bytes memory snapPayload, bytes memory snapSignature);\n\n /**\n * @notice Returns Notary snapshot from the list of all accepted Guard snapshots.\n * @dev Reverts if snapshot with given index hasn't been accepted yet.\n * @param index Snapshot index in the list of all Notary snapshots\n * @return snapPayload Raw payload with Notary snapshot\n * @return snapSignature Raw payload with Notary signature for snapshot\n */\n function getNotarySnapshot(uint256 index)\n external\n view\n returns (bytes memory snapPayload, bytes memory snapSignature);\n\n /**\n * @notice Returns Notary snapshot that was used for creating a given attestation.\n * @dev Reverts if any of these is true:\n * - Attestation payload is not properly formatted.\n * - Attestation is invalid (doesn't have a matching Notary snapshot).\n * @param attPayload Raw payload with attestation data\n * @return snapPayload Raw payload with Notary snapshot\n * @return snapSignature Raw payload with Notary signature for snapshot\n */\n function getNotarySnapshot(bytes memory attPayload)\n external\n view\n returns (bytes memory snapPayload, bytes memory snapSignature);\n\n /**\n * @notice Returns proof of inclusion of (root, origin) fields of a given snapshot's state\n * into the Snapshot Merkle Tree for a given attestation.\n * @dev Reverts if any of these is true:\n * - Attestation with given nonce hasn't been created yet.\n * - State index is out of range of snapshot list.\n * @param attNonce Nonce for the attestation\n * @param stateIndex Index of state in the attestation's snapshot\n * @return snapProof The snapshot proof\n */\n function getSnapshotProof(uint32 attNonce, uint8 stateIndex) external view returns (bytes32[] memory snapProof);\n}\n\n// contracts/interfaces/IStateHub.sol\n\ninterface IStateHub {\n /**\n * @notice Check that a given state is valid: matches the historical state of Origin contract.\n * Note: any Agent including an invalid state in their snapshot will be slashed\n * upon providing the snapshot and agent signature for it to Origin contract.\n * @dev Will revert if any of these is true:\n * - State payload is not properly formatted.\n * @param statePayload Raw payload with state data\n * @return isValid Whether the provided state is valid\n */\n function isValidState(bytes memory statePayload) external view returns (bool isValid);\n\n /**\n * @notice Returns the amount of saved states so far.\n * @dev This includes the initial state of \"empty Origin Merkle Tree\".\n */\n function statesAmount() external view returns (uint256);\n\n /**\n * @notice Suggest the data (state after latest sent message) to sign for an Agent.\n * Note: signing the suggested state data will will never lead to slashing of the actor,\n * assuming they have confirmed that the block, which number is included in the data,\n * is not subject to reorganization (which is different for every observed chain).\n * @return statePayload Raw payload with the latest state data\n */\n function suggestLatestState() external view returns (bytes memory statePayload);\n\n /**\n * @notice Given the historical nonce, suggest the state data to sign for an Agent.\n * Note: signing the suggested state data will will never lead to slashing of the actor,\n * assuming they have confirmed that the block, which number is included in the data,\n * is not subject to reorganization (which is different for every observed chain).\n * @param nonce Historical nonce to form a state\n * @return statePayload Raw payload with historical state data\n */\n function suggestState(uint32 nonce) external view returns (bytes memory statePayload);\n}\n\n// contracts/interfaces/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/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// node_modules/@openzeppelin/contracts/utils/math/Math.sol\n\n// OpenZeppelin Contracts (last updated v4.9.0) (utils/math/Math.sol)\n\n/**\n * @dev Standard math utilities missing in the Solidity language.\n */\nlibrary Math {\n enum Rounding {\n Down, // Toward negative infinity\n Up, // Toward infinity\n Zero // Toward zero\n }\n\n /**\n * @dev Returns the largest of two numbers.\n */\n function max(uint256 a, uint256 b) internal pure returns (uint256) {\n return a \u003e b ? a : b;\n }\n\n /**\n * @dev Returns the smallest of two numbers.\n */\n function min(uint256 a, uint256 b) internal pure returns (uint256) {\n return a \u003c b ? a : b;\n }\n\n /**\n * @dev Returns the average of two numbers. The result is rounded towards\n * zero.\n */\n function average(uint256 a, uint256 b) internal pure returns (uint256) {\n // (a + b) / 2 can overflow.\n return (a \u0026 b) + (a ^ b) / 2;\n }\n\n /**\n * @dev Returns the ceiling of the division of two numbers.\n *\n * This differs from standard division with `/` in that it rounds up instead\n * of rounding down.\n */\n function ceilDiv(uint256 a, uint256 b) internal pure returns (uint256) {\n // (a + b - 1) / b can overflow on addition, so we distribute.\n return a == 0 ? 0 : (a - 1) / b + 1;\n }\n\n /**\n * @notice Calculates floor(x * y / denominator) with full precision. Throws if result overflows a uint256 or denominator == 0\n * @dev Original credit to Remco Bloemen under MIT license (https://xn--2-umb.com/21/muldiv)\n * with further edits by Uniswap Labs also under MIT license.\n */\n function mulDiv(uint256 x, uint256 y, uint256 denominator) internal pure returns (uint256 result) {\n unchecked {\n // 512-bit multiply [prod1 prod0] = x * y. Compute the product mod 2^256 and mod 2^256 - 1, then use\n // use the Chinese Remainder Theorem to reconstruct the 512 bit result. The result is stored in two 256\n // variables such that product = prod1 * 2^256 + prod0.\n uint256 prod0; // Least significant 256 bits of the product\n uint256 prod1; // Most significant 256 bits of the product\n assembly {\n let mm := mulmod(x, y, not(0))\n prod0 := mul(x, y)\n prod1 := sub(sub(mm, prod0), lt(mm, prod0))\n }\n\n // Handle non-overflow cases, 256 by 256 division.\n if (prod1 == 0) {\n // Solidity will revert if denominator == 0, unlike the div opcode on its own.\n // The surrounding unchecked block does not change this fact.\n // See https://docs.soliditylang.org/en/latest/control-structures.html#checked-or-unchecked-arithmetic.\n return prod0 / denominator;\n }\n\n // Make sure the result is less than 2^256. Also prevents denominator == 0.\n require(denominator \u003e prod1, \"Math: mulDiv overflow\");\n\n ///////////////////////////////////////////////\n // 512 by 256 division.\n ///////////////////////////////////////////////\n\n // Make division exact by subtracting the remainder from [prod1 prod0].\n uint256 remainder;\n assembly {\n // Compute remainder using mulmod.\n remainder := mulmod(x, y, denominator)\n\n // Subtract 256 bit number from 512 bit number.\n prod1 := sub(prod1, gt(remainder, prod0))\n prod0 := sub(prod0, remainder)\n }\n\n // Factor powers of two out of denominator and compute largest power of two divisor of denominator. Always \u003e= 1.\n // See https://cs.stackexchange.com/q/138556/92363.\n\n // Does not overflow because the denominator cannot be zero at this stage in the function.\n uint256 twos = denominator \u0026 (~denominator + 1);\n assembly {\n // Divide denominator by twos.\n denominator := div(denominator, twos)\n\n // Divide [prod1 prod0] by twos.\n prod0 := div(prod0, twos)\n\n // Flip twos such that it is 2^256 / twos. If twos is zero, then it becomes one.\n twos := add(div(sub(0, twos), twos), 1)\n }\n\n // Shift in bits from prod1 into prod0.\n prod0 |= prod1 * twos;\n\n // Invert denominator mod 2^256. Now that denominator is an odd number, it has an inverse modulo 2^256 such\n // that denominator * inv = 1 mod 2^256. Compute the inverse by starting with a seed that is correct for\n // four bits. That is, denominator * inv = 1 mod 2^4.\n uint256 inverse = (3 * denominator) ^ 2;\n\n // Use the Newton-Raphson iteration to improve the precision. Thanks to Hensel's lifting lemma, this also works\n // in modular arithmetic, doubling the correct bits in each step.\n inverse *= 2 - denominator * inverse; // inverse mod 2^8\n inverse *= 2 - denominator * inverse; // inverse mod 2^16\n inverse *= 2 - denominator * inverse; // inverse mod 2^32\n inverse *= 2 - denominator * inverse; // inverse mod 2^64\n inverse *= 2 - denominator * inverse; // inverse mod 2^128\n inverse *= 2 - denominator * inverse; // inverse mod 2^256\n\n // Because the division is now exact we can divide by multiplying with the modular inverse of denominator.\n // This will give us the correct result modulo 2^256. Since the preconditions guarantee that the outcome is\n // less than 2^256, this is the final result. We don't need to compute the high bits of the result and prod1\n // is no longer required.\n result = prod0 * inverse;\n return result;\n }\n }\n\n /**\n * @notice Calculates x * y / denominator with full precision, following the selected rounding direction.\n */\n function mulDiv(uint256 x, uint256 y, uint256 denominator, Rounding rounding) internal pure returns (uint256) {\n uint256 result = mulDiv(x, y, denominator);\n if (rounding == Rounding.Up \u0026\u0026 mulmod(x, y, denominator) \u003e 0) {\n result += 1;\n }\n return result;\n }\n\n /**\n * @dev Returns the square root of a number. If the number is not a perfect square, the value is rounded down.\n *\n * Inspired by Henry S. Warren, Jr.'s \"Hacker's Delight\" (Chapter 11).\n */\n function sqrt(uint256 a) internal pure returns (uint256) {\n if (a == 0) {\n return 0;\n }\n\n // For our first guess, we get the biggest power of 2 which is smaller than the square root of the target.\n //\n // We know that the \"msb\" (most significant bit) of our target number `a` is a power of 2 such that we have\n // `msb(a) \u003c= a \u003c 2*msb(a)`. This value can be written `msb(a)=2**k` with `k=log2(a)`.\n //\n // This can be rewritten `2**log2(a) \u003c= a \u003c 2**(log2(a) + 1)`\n // → `sqrt(2**k) \u003c= sqrt(a) \u003c sqrt(2**(k+1))`\n // → `2**(k/2) \u003c= sqrt(a) \u003c 2**((k+1)/2) \u003c= 2**(k/2 + 1)`\n //\n // Consequently, `2**(log2(a) / 2)` is a good first approximation of `sqrt(a)` with at least 1 correct bit.\n uint256 result = 1 \u003c\u003c (log2(a) \u003e\u003e 1);\n\n // At this point `result` is an estimation with one bit of precision. We know the true value is a uint128,\n // since it is the square root of a uint256. Newton's method converges quadratically (precision doubles at\n // every iteration). We thus need at most 7 iteration to turn our partial result with one bit of precision\n // into the expected uint128 result.\n unchecked {\n result = (result + a / result) \u003e\u003e 1;\n result = (result + a / result) \u003e\u003e 1;\n result = (result + a / result) \u003e\u003e 1;\n result = (result + a / result) \u003e\u003e 1;\n result = (result + a / result) \u003e\u003e 1;\n result = (result + a / result) \u003e\u003e 1;\n result = (result + a / result) \u003e\u003e 1;\n return min(result, a / result);\n }\n }\n\n /**\n * @notice Calculates sqrt(a), following the selected rounding direction.\n */\n function sqrt(uint256 a, Rounding rounding) internal pure returns (uint256) {\n unchecked {\n uint256 result = sqrt(a);\n return result + (rounding == Rounding.Up \u0026\u0026 result * result \u003c a ? 1 : 0);\n }\n }\n\n /**\n * @dev Return the log in base 2, rounded down, of a positive value.\n * Returns 0 if given 0.\n */\n function log2(uint256 value) internal pure returns (uint256) {\n uint256 result = 0;\n unchecked {\n if (value \u003e\u003e 128 \u003e 0) {\n value \u003e\u003e= 128;\n result += 128;\n }\n if (value \u003e\u003e 64 \u003e 0) {\n value \u003e\u003e= 64;\n result += 64;\n }\n if (value \u003e\u003e 32 \u003e 0) {\n value \u003e\u003e= 32;\n result += 32;\n }\n if (value \u003e\u003e 16 \u003e 0) {\n value \u003e\u003e= 16;\n result += 16;\n }\n if (value \u003e\u003e 8 \u003e 0) {\n value \u003e\u003e= 8;\n result += 8;\n }\n if (value \u003e\u003e 4 \u003e 0) {\n value \u003e\u003e= 4;\n result += 4;\n }\n if (value \u003e\u003e 2 \u003e 0) {\n value \u003e\u003e= 2;\n result += 2;\n }\n if (value \u003e\u003e 1 \u003e 0) {\n result += 1;\n }\n }\n return result;\n }\n\n /**\n * @dev Return the log in base 2, following the selected rounding direction, of a positive value.\n * Returns 0 if given 0.\n */\n function log2(uint256 value, Rounding rounding) internal pure returns (uint256) {\n unchecked {\n uint256 result = log2(value);\n return result + (rounding == Rounding.Up \u0026\u0026 1 \u003c\u003c result \u003c value ? 1 : 0);\n }\n }\n\n /**\n * @dev Return the log in base 10, rounded down, of a positive value.\n * Returns 0 if given 0.\n */\n function log10(uint256 value) internal pure returns (uint256) {\n uint256 result = 0;\n unchecked {\n if (value \u003e= 10 ** 64) {\n value /= 10 ** 64;\n result += 64;\n }\n if (value \u003e= 10 ** 32) {\n value /= 10 ** 32;\n result += 32;\n }\n if (value \u003e= 10 ** 16) {\n value /= 10 ** 16;\n result += 16;\n }\n if (value \u003e= 10 ** 8) {\n value /= 10 ** 8;\n result += 8;\n }\n if (value \u003e= 10 ** 4) {\n value /= 10 ** 4;\n result += 4;\n }\n if (value \u003e= 10 ** 2) {\n value /= 10 ** 2;\n result += 2;\n }\n if (value \u003e= 10 ** 1) {\n result += 1;\n }\n }\n return result;\n }\n\n /**\n * @dev Return the log in base 10, following the selected rounding direction, of a positive value.\n * Returns 0 if given 0.\n */\n function log10(uint256 value, Rounding rounding) internal pure returns (uint256) {\n unchecked {\n uint256 result = log10(value);\n return result + (rounding == Rounding.Up \u0026\u0026 10 ** result \u003c value ? 1 : 0);\n }\n }\n\n /**\n * @dev Return the log in base 256, rounded down, of a positive value.\n * Returns 0 if given 0.\n *\n * Adding one to the result gives the number of pairs of hex symbols needed to represent `value` as a hex string.\n */\n function log256(uint256 value) internal pure returns (uint256) {\n uint256 result = 0;\n unchecked {\n if (value \u003e\u003e 128 \u003e 0) {\n value \u003e\u003e= 128;\n result += 16;\n }\n if (value \u003e\u003e 64 \u003e 0) {\n value \u003e\u003e= 64;\n result += 8;\n }\n if (value \u003e\u003e 32 \u003e 0) {\n value \u003e\u003e= 32;\n result += 4;\n }\n if (value \u003e\u003e 16 \u003e 0) {\n value \u003e\u003e= 16;\n result += 2;\n }\n if (value \u003e\u003e 8 \u003e 0) {\n result += 1;\n }\n }\n return result;\n }\n\n /**\n * @dev Return the log in base 256, following the selected rounding direction, of a positive value.\n * Returns 0 if given 0.\n */\n function log256(uint256 value, Rounding rounding) internal pure returns (uint256) {\n unchecked {\n uint256 result = log256(value);\n return result + (rounding == Rounding.Up \u0026\u0026 1 \u003c\u003c (result \u003c\u003c 3) \u003c value ? 1 : 0);\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/utils/math/SignedMath.sol\n\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/math/SignedMath.sol)\n\n/**\n * @dev Standard signed math utilities missing in the Solidity language.\n */\nlibrary SignedMath {\n /**\n * @dev Returns the largest of two signed numbers.\n */\n function max(int256 a, int256 b) internal pure returns (int256) {\n return a \u003e b ? a : b;\n }\n\n /**\n * @dev Returns the smallest of two signed numbers.\n */\n function min(int256 a, int256 b) internal pure returns (int256) {\n return a \u003c b ? a : b;\n }\n\n /**\n * @dev Returns the average of two signed numbers without overflow.\n * The result is rounded towards zero.\n */\n function average(int256 a, int256 b) internal pure returns (int256) {\n // Formula from the book \"Hacker's Delight\"\n int256 x = (a \u0026 b) + ((a ^ b) \u003e\u003e 1);\n return x + (int256(uint256(x) \u003e\u003e 255) \u0026 (a ^ b));\n }\n\n /**\n * @dev Returns the absolute unsigned value of a signed value.\n */\n function abs(int256 n) internal pure returns (uint256) {\n unchecked {\n // must be unchecked in order to support `n = type(int256).min`\n return uint256(n \u003e= 0 ? n : -n);\n }\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// 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/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/InterfaceSummit.sol\n\ninterface InterfaceSummit {\n // ══════════════════════════════════════════ ACCEPT AGENT STATEMENTS ══════════════════════════════════════════════\n\n /**\n * @notice Accepts a receipt, which local `AgentManager` verified to have been signed by an active Notary.\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 * - Notary who signed the receipt is referenced as the \"Receipt Notary\".\n * - Notary who signed the attestation on destination chain is referenced as the \"Attestation Notary\".\n * \u003e Will revert if any of these is true:\n * \u003e - Called by anyone other than local `AgentManager`.\n * \u003e - Receipt body payload is not properly formatted.\n * \u003e - Receipt signer is in Dispute.\n * \u003e - Receipt's snapshot root is unknown.\n * @param rcptNotaryIndex Index of Receipt Notary in Agent Merkle Tree\n * @param attNotaryIndex Index of Attestation Notary in Agent Merkle Tree\n * @param sigIndex Index of stored Notary signature\n * @param attNonce Nonce of the attestation used for proving the executed message\n * @param paddedTips Padded encoded paid tips information\n * @param rcptPayload Raw payload with message execution receipt\n * @return wasAccepted Whether the receipt was accepted\n */\n function acceptReceipt(\n uint32 rcptNotaryIndex,\n uint32 attNotaryIndex,\n uint256 sigIndex,\n uint32 attNonce,\n uint256 paddedTips,\n bytes memory rcptPayload\n ) external returns (bool wasAccepted);\n\n /**\n * @notice Accepts a snapshot, which local `AgentManager` verified to have been signed by an active Guard.\n * \u003e Snapshot is a list of states for a set of Origin contracts residing on any of the chains.\n * All the states in the Guard-signed snapshot become available for Notary signing.\n * \u003e Will revert if any of these is true:\n * \u003e - Called by anyone other than local `AgentManager`.\n * \u003e - Snapshot payload is not properly formatted.\n * \u003e - Snapshot contains a state older then the Guard has previously submitted.\n * @param guardIndex Index of Guard in Agent Merkle Tree\n * @param sigIndex Index of stored Agent signature\n * @param snapPayload Raw payload with snapshot data\n */\n function acceptGuardSnapshot(uint32 guardIndex, uint256 sigIndex, bytes memory snapPayload) external;\n\n /**\n * @notice Accepts a snapshot, which local `AgentManager` verified to have been signed by an active Notary.\n * \u003e Snapshot is a list of states for a set of Origin contracts residing on any of the chains.\n * Snapshot Merkle Root is calculated and saved for valid snapshots, i.e.\n * snapshots which are only using states previously submitted by any of the Guards.\n * - Notary could use states singed by the same of different Guards 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 - Called by anyone other than local `AgentManager`.\n * \u003e - Snapshot payload is not properly formatted.\n * \u003e - Snapshot contains a state older then the Notary has previously submitted.\n * \u003e - Snapshot contains a state that no Guard has previously submitted.\n * @param notaryIndex Index of Notary in Agent Merkle Tree\n * @param sigIndex Index of stored Agent signature\n * @param agentRoot Current root of the Agent Merkle Tree\n * @param snapPayload Raw payload with snapshot data\n * @return attPayload Raw payload with data for attestation derived from Notary snapshot.\n */\n function acceptNotarySnapshot(uint32 notaryIndex, uint256 sigIndex, bytes32 agentRoot, bytes memory snapPayload)\n external\n returns (bytes memory attPayload);\n\n // ════════════════════════════════════════════════ TIPS LOGIC ═════════════════════════════════════════════════════\n\n /**\n * @notice Distributes tips using the first Receipt from the \"receipt quarantine queue\".\n * Possible scenarios:\n * - Receipt queue is empty =\u003e does nothing\n * - Receipt optimistic period is not over =\u003e does nothing\n * - Either of Notaries present in Receipt was slashed =\u003e receipt is deleted from the queue\n * - Either of Notaries present in Receipt in Dispute =\u003e receipt is moved to the end of queue\n * - None of the above =\u003e receipt tips are distributed\n * @dev Returned value makes it possible to do the following: `while (distributeTips()) {}`\n * @return queuePopped Whether the first element was popped from the queue\n */\n function distributeTips() external returns (bool queuePopped);\n\n /**\n * @notice Withdraws locked base message tips from requested domain Origin to the recipient.\n * This is done by a call to a local Origin contract, or by a manager message to the remote chain.\n * @dev This will revert, if the pending balance of origin tips (earned-claimed) is lower than requested.\n * @param origin Domain of chain to withdraw tips on\n * @param amount Amount of tips to withdraw\n */\n function withdrawTips(uint32 origin, uint256 amount) external;\n\n // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════\n\n /**\n * @notice Returns earned and claimed tips for the actor.\n * Note: Tips for address(0) belong to the Treasury.\n * @param actor Address of the actor\n * @param origin Domain where the tips were initially paid\n * @return earned Total amount of origin tips the actor has earned so far\n * @return claimed Total amount of origin tips the actor has claimed so far\n */\n function actorTips(address actor, uint32 origin) external view returns (uint128 earned, uint128 claimed);\n\n /**\n * @notice Returns the amount of receipts in the \"Receipt Quarantine Queue\".\n */\n function receiptQueueLength() external view returns (uint256);\n\n /**\n * @notice Returns the state with the highest known nonce\n * submitted by any of the currently active Guards.\n * @param origin Domain of origin chain\n * @return statePayload Raw payload with latest active Guard state for origin\n */\n function getLatestState(uint32 origin) external view returns (bytes memory statePayload);\n}\n\n// node_modules/@openzeppelin/contracts/utils/Strings.sol\n\n// OpenZeppelin Contracts (last updated v4.9.0) (utils/Strings.sol)\n\n/**\n * @dev String operations.\n */\nlibrary Strings {\n bytes16 private constant _SYMBOLS = \"0123456789abcdef\";\n uint8 private constant _ADDRESS_LENGTH = 20;\n\n /**\n * @dev Converts a `uint256` to its ASCII `string` decimal representation.\n */\n function toString(uint256 value) internal pure returns (string memory) {\n unchecked {\n uint256 length = Math.log10(value) + 1;\n string memory buffer = new string(length);\n uint256 ptr;\n /// @solidity memory-safe-assembly\n assembly {\n ptr := add(buffer, add(32, length))\n }\n while (true) {\n ptr--;\n /// @solidity memory-safe-assembly\n assembly {\n mstore8(ptr, byte(mod(value, 10), _SYMBOLS))\n }\n value /= 10;\n if (value == 0) break;\n }\n return buffer;\n }\n }\n\n /**\n * @dev Converts a `int256` to its ASCII `string` decimal representation.\n */\n function toString(int256 value) internal pure returns (string memory) {\n return string(abi.encodePacked(value \u003c 0 ? \"-\" : \"\", toString(SignedMath.abs(value))));\n }\n\n /**\n * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation.\n */\n function toHexString(uint256 value) internal pure returns (string memory) {\n unchecked {\n return toHexString(value, Math.log256(value) + 1);\n }\n }\n\n /**\n * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length.\n */\n function toHexString(uint256 value, uint256 length) internal pure returns (string memory) {\n bytes memory buffer = new bytes(2 * length + 2);\n buffer[0] = \"0\";\n buffer[1] = \"x\";\n for (uint256 i = 2 * length + 1; i \u003e 1; --i) {\n buffer[i] = _SYMBOLS[value \u0026 0xf];\n value \u003e\u003e= 4;\n }\n require(value == 0, \"Strings: hex length insufficient\");\n return string(buffer);\n }\n\n /**\n * @dev Converts an `address` with fixed length of 20 bytes to its not checksummed ASCII `string` hexadecimal representation.\n */\n function toHexString(address addr) internal pure returns (string memory) {\n return toHexString(uint256(uint160(addr)), _ADDRESS_LENGTH);\n }\n\n /**\n * @dev Returns true if the two strings are equal.\n */\n function equal(string memory a, string memory b) internal pure returns (bool) {\n return keccak256(bytes(a)) == keccak256(bytes(b));\n }\n}\n\n// node_modules/@openzeppelin/contracts-upgradeable/utils/ContextUpgradeable.sol\n\n// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)\n\n/**\n * @dev Provides information about the current execution context, including the\n * sender of the transaction and its data. While these are generally available\n * via msg.sender and msg.data, they should not be accessed in such a direct\n * manner, since when dealing with meta-transactions the account sending and\n * paying for execution may not be the actual sender (as far as an application\n * is concerned).\n *\n * This contract is only required for intermediate, library-like contracts.\n */\nabstract contract ContextUpgradeable is Initializable {\n function __Context_init() internal onlyInitializing {\n }\n\n function __Context_init_unchained() internal onlyInitializing {\n }\n function _msgSender() internal view virtual returns (address) {\n return msg.sender;\n }\n\n function _msgData() internal view virtual returns (bytes calldata) {\n return msg.data;\n }\n\n /**\n * @dev This empty reserved space is put in place to allow future versions to add new\n * variables without shifting down storage in the inheritance chain.\n * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\n */\n uint256[50] private __gap;\n}\n\n// contracts/libs/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/utils/cryptography/ECDSA.sol\n\n// OpenZeppelin Contracts (last updated v4.9.0) (utils/cryptography/ECDSA.sol)\n\n/**\n * @dev Elliptic Curve Digital Signature Algorithm (ECDSA) operations.\n *\n * These functions can be used to verify that a message was signed by the holder\n * of the private keys of a given address.\n */\nlibrary ECDSA {\n enum RecoverError {\n NoError,\n InvalidSignature,\n InvalidSignatureLength,\n InvalidSignatureS,\n InvalidSignatureV // Deprecated in v4.8\n }\n\n function _throwError(RecoverError error) private pure {\n if (error == RecoverError.NoError) {\n return; // no error: do nothing\n } else if (error == RecoverError.InvalidSignature) {\n revert(\"ECDSA: invalid signature\");\n } else if (error == RecoverError.InvalidSignatureLength) {\n revert(\"ECDSA: invalid signature length\");\n } else if (error == RecoverError.InvalidSignatureS) {\n revert(\"ECDSA: invalid signature 's' value\");\n }\n }\n\n /**\n * @dev Returns the address that signed a hashed message (`hash`) with\n * `signature` or error string. This address can then be used for verification purposes.\n *\n * The `ecrecover` EVM opcode allows for malleable (non-unique) signatures:\n * this function rejects them by requiring the `s` value to be in the lower\n * half order, and the `v` value to be either 27 or 28.\n *\n * IMPORTANT: `hash` _must_ be the result of a hash operation for the\n * verification to be secure: it is possible to craft signatures that\n * recover to arbitrary addresses for non-hashed data. A safe way to ensure\n * this is by receiving a hash of the original message (which may otherwise\n * be too long), and then calling {toEthSignedMessageHash} on it.\n *\n * Documentation for signature generation:\n * - with https://web3js.readthedocs.io/en/v1.3.4/web3-eth-accounts.html#sign[Web3.js]\n * - with https://docs.ethers.io/v5/api/signer/#Signer-signMessage[ethers]\n *\n * _Available since v4.3._\n */\n function tryRecover(bytes32 hash, bytes memory signature) internal pure returns (address, RecoverError) {\n if (signature.length == 65) {\n bytes32 r;\n bytes32 s;\n uint8 v;\n // ecrecover takes the signature parameters, and the only way to get them\n // currently is to use assembly.\n /// @solidity memory-safe-assembly\n assembly {\n r := mload(add(signature, 0x20))\n s := mload(add(signature, 0x40))\n v := byte(0, mload(add(signature, 0x60)))\n }\n return tryRecover(hash, v, r, s);\n } else {\n return (address(0), RecoverError.InvalidSignatureLength);\n }\n }\n\n /**\n * @dev Returns the address that signed a hashed message (`hash`) with\n * `signature`. This address can then be used for verification purposes.\n *\n * The `ecrecover` EVM opcode allows for malleable (non-unique) signatures:\n * this function rejects them by requiring the `s` value to be in the lower\n * half order, and the `v` value to be either 27 or 28.\n *\n * IMPORTANT: `hash` _must_ be the result of a hash operation for the\n * verification to be secure: it is possible to craft signatures that\n * recover to arbitrary addresses for non-hashed data. A safe way to ensure\n * this is by receiving a hash of the original message (which may otherwise\n * be too long), and then calling {toEthSignedMessageHash} on it.\n */\n function recover(bytes32 hash, bytes memory signature) internal pure returns (address) {\n (address recovered, RecoverError error) = tryRecover(hash, signature);\n _throwError(error);\n return recovered;\n }\n\n /**\n * @dev Overload of {ECDSA-tryRecover} that receives the `r` and `vs` short-signature fields separately.\n *\n * See https://eips.ethereum.org/EIPS/eip-2098[EIP-2098 short signatures]\n *\n * _Available since v4.3._\n */\n function tryRecover(bytes32 hash, bytes32 r, bytes32 vs) internal pure returns (address, RecoverError) {\n bytes32 s = vs \u0026 bytes32(0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff);\n uint8 v = uint8((uint256(vs) \u003e\u003e 255) + 27);\n return tryRecover(hash, v, r, s);\n }\n\n /**\n * @dev Overload of {ECDSA-recover} that receives the `r and `vs` short-signature fields separately.\n *\n * _Available since v4.2._\n */\n function recover(bytes32 hash, bytes32 r, bytes32 vs) internal pure returns (address) {\n (address recovered, RecoverError error) = tryRecover(hash, r, vs);\n _throwError(error);\n return recovered;\n }\n\n /**\n * @dev Overload of {ECDSA-tryRecover} that receives the `v`,\n * `r` and `s` signature fields separately.\n *\n * _Available since v4.3._\n */\n function tryRecover(bytes32 hash, uint8 v, bytes32 r, bytes32 s) internal pure returns (address, RecoverError) {\n // EIP-2 still allows signature malleability for ecrecover(). Remove this possibility and make the signature\n // unique. Appendix F in the Ethereum Yellow paper (https://ethereum.github.io/yellowpaper/paper.pdf), defines\n // the valid range for s in (301): 0 \u003c s \u003c secp256k1n ÷ 2 + 1, and for v in (302): v ∈ {27, 28}. Most\n // signatures from current libraries generate a unique signature with an s-value in the lower half order.\n //\n // If your library generates malleable signatures, such as s-values in the upper range, calculate a new s-value\n // with 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141 - s1 and flip v from 27 to 28 or\n // vice versa. If your library also generates signatures with 0/1 for v instead 27/28, add 27 to v to accept\n // these malleable signatures as well.\n if (uint256(s) \u003e 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0) {\n return (address(0), RecoverError.InvalidSignatureS);\n }\n\n // If the signature is valid (and not malleable), return the signer address\n address signer = ecrecover(hash, v, r, s);\n if (signer == address(0)) {\n return (address(0), RecoverError.InvalidSignature);\n }\n\n return (signer, RecoverError.NoError);\n }\n\n /**\n * @dev Overload of {ECDSA-recover} that receives the `v`,\n * `r` and `s` signature fields separately.\n */\n function recover(bytes32 hash, uint8 v, bytes32 r, bytes32 s) internal pure returns (address) {\n (address recovered, RecoverError error) = tryRecover(hash, v, r, s);\n _throwError(error);\n return recovered;\n }\n\n /**\n * @dev Returns an Ethereum Signed Message, created from a `hash`. This\n * produces hash corresponding to the one signed with the\n * https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`]\n * JSON-RPC method as part of EIP-191.\n *\n * See {recover}.\n */\n function toEthSignedMessageHash(bytes32 hash) internal pure returns (bytes32 message) {\n // 32 is the length in bytes of hash,\n // enforced by the type signature above\n /// @solidity memory-safe-assembly\n assembly {\n mstore(0x00, \"\\x19Ethereum Signed Message:\\n32\")\n mstore(0x1c, hash)\n message := keccak256(0x00, 0x3c)\n }\n }\n\n /**\n * @dev Returns an Ethereum Signed Message, created from `s`. This\n * produces hash corresponding to the one signed with the\n * https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`]\n * JSON-RPC method as part of EIP-191.\n *\n * See {recover}.\n */\n function toEthSignedMessageHash(bytes memory s) internal pure returns (bytes32) {\n return keccak256(abi.encodePacked(\"\\x19Ethereum Signed Message:\\n\", Strings.toString(s.length), s));\n }\n\n /**\n * @dev Returns an Ethereum Signed Typed Data, created from a\n * `domainSeparator` and a `structHash`. This produces hash corresponding\n * to the one signed with the\n * https://eips.ethereum.org/EIPS/eip-712[`eth_signTypedData`]\n * JSON-RPC method as part of EIP-712.\n *\n * See {recover}.\n */\n function toTypedDataHash(bytes32 domainSeparator, bytes32 structHash) internal pure returns (bytes32 data) {\n /// @solidity memory-safe-assembly\n assembly {\n let ptr := mload(0x40)\n mstore(ptr, \"\\x19\\x01\")\n mstore(add(ptr, 0x02), domainSeparator)\n mstore(add(ptr, 0x22), structHash)\n data := keccak256(ptr, 0x42)\n }\n }\n\n /**\n * @dev Returns an Ethereum Signed Data with intended validator, created from a\n * `validator` and `data` according to the version 0 of EIP-191.\n *\n * See {recover}.\n */\n function toDataWithIntendedValidatorHash(address validator, bytes memory data) internal pure returns (bytes32) {\n return keccak256(abi.encodePacked(\"\\x19\\x00\", validator, data));\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/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/inbox/StatementInbox.sol\n\n// ══════════════════════════════ LIBRARY IMPORTS ══════════════════════════════\n\n// ═════════════════════════════ INTERNAL IMPORTS ══════════════════════════════\n\n// ═════════════════════════════ EXTERNAL IMPORTS ══════════════════════════════\n\n/// @notice `StatementInbox` is the entry point for all agent-signed statements. It verifies the\n/// agent signatures, and passes the unsigned statements to the contract to consume it via `acceptX` functions. Is is\n/// also used to verify the agent-signed statements and initiate the agent slashing, should the statement be invalid.\n/// `StatementInbox` is responsible for the following:\n/// - Accepting State and Receipt Reports to initiate a dispute between Guard and Notary.\n/// - Storing all the Guard Reports with the Guard signature leading to a dispute.\n/// - Verifying State/State Reports referencing the local chain and slashing the signer if statement is invalid.\n/// - Verifying Receipt/Receipt Reports referencing the local chain and slashing the signer if statement is invalid.\nabstract contract StatementInbox is MessagingBase, StatementInboxEvents, IStatementInbox {\n using AttestationLib for bytes;\n using ReceiptLib for bytes;\n using StateLib for bytes;\n using SnapshotLib for bytes;\n\n struct StoredReport {\n uint256 sigIndex;\n bytes statementPayload;\n }\n\n // ══════════════════════════════════════════════════ STORAGE ══════════════════════════════════════════════════════\n\n address public agentManager;\n address public origin;\n address public destination;\n\n // TODO: optimize this\n bytes[] internal _storedSignatures;\n StoredReport[] internal _storedReports;\n\n /// @dev gap for upgrade safety\n uint256[45] private __GAP; // solhint-disable-line var-name-mixedcase\n\n // ════════════════════════════════════════════════ INITIALIZER ════════════════════════════════════════════════════\n\n /// @dev Initializes the contract:\n /// - Sets up `msg.sender` as the owner of the contract.\n /// - Sets up `agentManager`, `origin`, and `destination`.\n // solhint-disable-next-line func-name-mixedcase\n function __StatementInbox_init(address agentManager_, address origin_, address destination_)\n internal\n onlyInitializing\n {\n agentManager = agentManager_;\n origin = origin_;\n destination = destination_;\n __Ownable2Step_init();\n }\n\n // ══════════════════════════════════════════ SUBMIT AGENT STATEMENTS ══════════════════════════════════════════════\n\n /// @inheritdoc IStatementInbox\n // solhint-disable-next-line ordering\n function submitStateReportWithSnapshot(\n uint8 stateIndex,\n bytes memory srSignature,\n bytes memory snapPayload,\n bytes memory snapSignature\n ) external returns (bool wasAccepted) {\n // This will revert if payload is not a snapshot\n Snapshot snapshot = snapPayload.castToSnapshot();\n // This will revert if the snapshot signer is not a known Notary\n (AgentStatus memory notaryStatus,) =\n _verifySnapshot({snapshot: snapshot, snapSignature: snapSignature, verifyNotary: true});\n // Notary needs to be Active/Unstaking\n notaryStatus.verifyActiveUnstaking();\n // Check if Notary is active on this chain\n _verifyNotaryDomain(notaryStatus.domain);\n // This will revert if state index is out of range\n State state = snapshot.state(stateIndex);\n // This will revert if the report signer is not an known Guard\n (AgentStatus memory guardStatus,) = _verifyStateReport(state, srSignature);\n // Check that Guard is active\n guardStatus.verifyActive();\n _saveReport(state.unwrap().clone(), srSignature);\n // This will revert if either actor is already in dispute\n IAgentManager(agentManager).openDispute(guardStatus.index, notaryStatus.index);\n return true;\n }\n\n /// @inheritdoc IStatementInbox\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 // This will revert if payload is not a snapshot\n Snapshot snapshot = snapPayload.castToSnapshot();\n // This will revert if state index is out of range\n State state = snapshot.state(stateIndex);\n // This will revert if the report signer is not an known Guard\n (AgentStatus memory guardStatus,) = _verifyStateReport(state, srSignature);\n // Check that Guard is active\n guardStatus.verifyActive();\n // This will revert if payload is not an attestation\n Attestation att = attPayload.castToAttestation();\n // This will revert if signer is not an known Notary\n (AgentStatus memory notaryStatus,) = _verifyAttestation(att, attSignature);\n // Notary needs to be Active/Unstaking\n notaryStatus.verifyActiveUnstaking();\n // Check if Notary is active on this chain\n _verifyNotaryDomain(notaryStatus.domain);\n if (snapshot.calculateRoot() != att.snapRoot()) revert IncorrectSnapshotRoot();\n _saveReport(state.unwrap().clone(), srSignature);\n // This will revert if either actor is already in dispute\n IAgentManager(agentManager).openDispute(guardStatus.index, notaryStatus.index);\n return true;\n }\n\n /// @inheritdoc IStatementInbox\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 // This will revert if payload is not a state\n State state = statePayload.castToState();\n // This will revert if the report signer is not an known Guard\n (AgentStatus memory guardStatus,) = _verifyStateReport(state, srSignature);\n // Check that Guard is active\n guardStatus.verifyActive();\n // This will revert if payload is not an attestation\n Attestation att = attPayload.castToAttestation();\n // This will revert if signer is not a known Notary\n (AgentStatus memory notaryStatus,) = _verifyAttestation(att, attSignature);\n // Notary needs to be Active/Unstaking\n notaryStatus.verifyActiveUnstaking();\n // Check if Notary is active on this chain\n _verifyNotaryDomain(notaryStatus.domain);\n // This will revert if any of these is true:\n // - Attestation root is not equal to Merkle Root derived from State and Snapshot Proof.\n // - Snapshot Proof's first element does not match the State metadata.\n // - Snapshot Proof length exceeds Snapshot tree Height.\n // - State index is out of range.\n _verifySnapshotMerkle(att, stateIndex, state, snapProof);\n _saveReport(statePayload, srSignature);\n // This will revert if either actor is already in dispute\n IAgentManager(agentManager).openDispute(guardStatus.index, notaryStatus.index);\n return true;\n }\n\n // ══════════════════════════════════════════ VERIFY AGENT STATEMENTS ══════════════════════════════════════════════\n\n /// @inheritdoc IStatementInbox\n function verifyReceipt(bytes memory rcptPayload, bytes memory rcptSignature)\n external\n returns (bool isValidReceipt)\n {\n // This will revert if payload is not a receipt\n Receipt rcpt = rcptPayload.castToReceipt();\n // This will revert if the attestation signer is not a known Notary\n (AgentStatus memory status, address notary) = _verifyReceipt(rcpt, rcptSignature);\n // Notary needs to be Active/Unstaking\n status.verifyActiveUnstaking();\n isValidReceipt = IExecutionHub(destination).isValidReceipt(rcptPayload);\n if (!isValidReceipt) {\n emit InvalidReceipt(rcptPayload, rcptSignature);\n IAgentManager(agentManager).slashAgent(status.domain, notary, msg.sender);\n }\n }\n\n /// @inheritdoc IStatementInbox\n function verifyReceiptReport(bytes memory rcptPayload, bytes memory rrSignature)\n external\n returns (bool isValidReport)\n {\n // This will revert if payload is not a receipt\n Receipt rcpt = rcptPayload.castToReceipt();\n // This will revert if the report signer is not a known Guard\n (AgentStatus memory status, address guard) = _verifyReceiptReport(rcpt, rrSignature);\n // Guard needs to be Active/Unstaking\n status.verifyActiveUnstaking();\n // Report is valid IF AND ONLY IF the reported receipt in invalid\n isValidReport = !IExecutionHub(destination).isValidReceipt(rcptPayload);\n if (!isValidReport) {\n emit InvalidReceiptReport(rcptPayload, rrSignature);\n IAgentManager(agentManager).slashAgent(status.domain, guard, msg.sender);\n }\n }\n\n /// @inheritdoc IStatementInbox\n function verifyStateWithAttestation(\n uint8 stateIndex,\n bytes memory snapPayload,\n bytes memory attPayload,\n bytes memory attSignature\n ) external returns (bool isValidState) {\n // This will revert if payload is not an attestation\n Attestation att = attPayload.castToAttestation();\n // This will revert if the attestation signer is not a known Notary\n (AgentStatus memory status, address notary) = _verifyAttestation(att, attSignature);\n // Notary needs to be Active/Unstaking\n status.verifyActiveUnstaking();\n // This will revert if payload is not a snapshot\n Snapshot snapshot = snapPayload.castToSnapshot();\n if (snapshot.calculateRoot() != att.snapRoot()) revert IncorrectSnapshotRoot();\n // This will revert if state does not refer to this chain\n bytes memory statePayload = snapshot.state(stateIndex).unwrap().clone();\n isValidState = IStateHub(origin).isValidState(statePayload);\n if (!isValidState) {\n emit InvalidStateWithAttestation(stateIndex, statePayload, attPayload, attSignature);\n IAgentManager(agentManager).slashAgent(status.domain, notary, msg.sender);\n }\n }\n\n /// @inheritdoc IStatementInbox\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 // This will revert if payload is not an attestation\n Attestation att = attPayload.castToAttestation();\n // This will revert if the attestation signer is not a known Notary\n (AgentStatus memory status, address notary) = _verifyAttestation(att, attSignature);\n // Notary needs to be Active/Unstaking\n status.verifyActiveUnstaking();\n // This will revert if payload is not a state\n State state = statePayload.castToState();\n // This will revert if any of these is true:\n // - Attestation root is not equal to Merkle Root derived from State and Snapshot Proof.\n // - Snapshot Proof's first element does not match the State metadata.\n // - Snapshot Proof length exceeds Snapshot tree Height.\n // - State index is out of range.\n _verifySnapshotMerkle(att, stateIndex, state, snapProof);\n // This will revert if state does not refer to this chain\n isValidState = IStateHub(origin).isValidState(statePayload);\n if (!isValidState) {\n emit InvalidStateWithAttestation(stateIndex, statePayload, attPayload, attSignature);\n IAgentManager(agentManager).slashAgent(status.domain, notary, msg.sender);\n }\n }\n\n /// @inheritdoc IStatementInbox\n function verifyStateWithSnapshot(uint8 stateIndex, bytes memory snapPayload, bytes memory snapSignature)\n external\n returns (bool isValidState)\n {\n // This will revert if payload is not a snapshot\n Snapshot snapshot = snapPayload.castToSnapshot();\n // This will revert if the snapshot signer is not a known Guard/Notary\n (AgentStatus memory status, address agent) =\n _verifySnapshot({snapshot: snapshot, snapSignature: snapSignature, verifyNotary: false});\n // Agent needs to be Active/Unstaking\n status.verifyActiveUnstaking();\n // This will revert if state does not refer to this chain\n isValidState = IStateHub(origin).isValidState(snapshot.state(stateIndex).unwrap().clone());\n if (!isValidState) {\n emit InvalidStateWithSnapshot(stateIndex, snapPayload, snapSignature);\n IAgentManager(agentManager).slashAgent(status.domain, agent, msg.sender);\n }\n }\n\n /// @inheritdoc IStatementInbox\n function verifyStateReport(bytes memory statePayload, bytes memory srSignature)\n external\n returns (bool isValidReport)\n {\n // This will revert if payload is not a state\n State state = statePayload.castToState();\n // This will revert if the report signer is not a known Guard\n (AgentStatus memory status, address guard) = _verifyStateReport(state, srSignature);\n // Guard needs to be Active/Unstaking\n status.verifyActiveUnstaking();\n // Report is valid IF AND ONLY IF the reported state in invalid\n // This will revert if the reported state does not refer to this chain\n isValidReport = !IStateHub(origin).isValidState(statePayload);\n if (!isValidReport) {\n emit InvalidStateReport(statePayload, srSignature);\n IAgentManager(agentManager).slashAgent(status.domain, guard, msg.sender);\n }\n }\n\n // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════\n\n /// @inheritdoc IStatementInbox\n function getReportsAmount() external view returns (uint256) {\n return _storedReports.length;\n }\n\n /// @inheritdoc IStatementInbox\n function getGuardReport(uint256 index)\n external\n view\n returns (bytes memory statementPayload, bytes memory reportSignature)\n {\n if (index \u003e= _storedReports.length) revert IndexOutOfRange();\n StoredReport memory storedReport = _storedReports[index];\n statementPayload = storedReport.statementPayload;\n reportSignature = _storedSignatures[storedReport.sigIndex];\n }\n\n /// @inheritdoc IStatementInbox\n function getStoredSignature(uint256 index) external view returns (bytes memory) {\n return _storedSignatures[index];\n }\n\n // ══════════════════════════════════════════════ INTERNAL LOGIC ═══════════════════════════════════════════════════\n\n /// @dev Saves the statement reported by Guard as invalid and the Guard Report signature.\n function _saveReport(bytes memory statementPayload, bytes memory reportSignature) internal {\n uint256 sigIndex = _saveSignature(reportSignature);\n _storedReports.push(StoredReport(sigIndex, statementPayload));\n }\n\n /// @dev Saves the signature and returns its index.\n function _saveSignature(bytes memory signature) internal returns (uint256 sigIndex) {\n sigIndex = _storedSignatures.length;\n _storedSignatures.push(signature);\n }\n\n // ═══════════════════════════════════════════════ AGENT CHECKS ════════════════════════════════════════════════════\n\n /**\n * @dev Recovers a signer from a hashed message, and a EIP-191 signature for it.\n * Will revert, if the signer is not a known agent.\n * @dev Agent flag could be any of these: Active/Unstaking/Resting/Fraudulent/Slashed\n * Further checks need to be performed in a caller function.\n * @param hashedStatement Hash of the statement that was signed by an Agent\n * @param signature Agent signature for the hashed statement\n * @return status Struct representing agent status:\n * - flag Unknown/Active/Unstaking/Resting/Fraudulent/Slashed\n * - domain Domain where agent is/was active\n * - index Index of agent in the Agent Merkle Tree\n * @return agent Agent that signed the statement\n */\n function _recoverAgent(bytes32 hashedStatement, bytes memory signature)\n internal\n view\n returns (AgentStatus memory status, address agent)\n {\n bytes32 ethSignedMsg = ECDSA.toEthSignedMessageHash(hashedStatement);\n agent = ECDSA.recover(ethSignedMsg, signature);\n status = IAgentManager(agentManager).agentStatus(agent);\n // Discard signature of unknown agents.\n // Further flag checks are supposed to be performed in a caller function.\n status.verifyKnown();\n }\n\n /// @dev Verifies that Notary signature is active on local domain.\n function _verifyNotaryDomain(uint32 notaryDomain) internal view {\n // Notary needs to be from the local domain (if contract is not deployed on Synapse Chain).\n // Or Notary could be from any domain (if contract is deployed on Synapse Chain).\n if (notaryDomain != localDomain \u0026\u0026 localDomain != synapseDomain) revert IncorrectAgentDomain();\n }\n\n // ════════════════════════════════════════ ATTESTATION RELATED CHECKS ═════════════════════════════════════════════\n\n /**\n * @dev Internal function to verify the signed attestation payload.\n * Reverts if any of these is true:\n * - Attestation signer is not a known Notary.\n * @param att Typed memory view over attestation payload\n * @param attSignature Notary signature for the attestation\n * @return status Struct representing agent status, see {_recoverAgent}\n * @return notary Notary that signed the snapshot\n */\n function _verifyAttestation(Attestation att, bytes memory attSignature)\n internal\n view\n returns (AgentStatus memory status, address notary)\n {\n // This will revert if signer is not a known agent\n (status, notary) = _recoverAgent(att.hashValid(), attSignature);\n // Attestation signer needs to be a Notary, not a Guard\n if (status.domain == 0) revert AgentNotNotary();\n }\n\n /**\n * @dev Internal function to verify the signed attestation report payload.\n * Reverts if any of these is true:\n * - Report signer is not a known Guard.\n * @param att Typed memory view over attestation payload that Guard reports as invalid\n * @param arSignature Guard signature for the \"invalid attestation\" report\n * @return status Struct representing guard status, see {_recoverAgent}\n * @return guard Guard that signed the report\n */\n function _verifyAttestationReport(Attestation att, bytes memory arSignature)\n internal\n view\n returns (AgentStatus memory status, address guard)\n {\n // This will revert if signer is not a known agent\n (status, guard) = _recoverAgent(att.hashInvalid(), arSignature);\n // Report signer needs to be a Guard, not a Notary\n if (status.domain != 0) revert AgentNotGuard();\n }\n\n // ══════════════════════════════════════════ RECEIPT RELATED CHECKS ═══════════════════════════════════════════════\n\n /**\n * @dev Internal function to verify the signed receipt payload.\n * Reverts if any of these is true:\n * - Receipt signer is not a known Notary.\n * @param rcpt Typed memory view over receipt payload\n * @param rcptSignature Notary signature for the receipt\n * @return status Struct representing agent status, see {_recoverAgent}\n * @return notary Notary that signed the snapshot\n */\n function _verifyReceipt(Receipt rcpt, bytes memory rcptSignature)\n internal\n view\n returns (AgentStatus memory status, address notary)\n {\n // This will revert if signer is not a known agent\n (status, notary) = _recoverAgent(rcpt.hashValid(), rcptSignature);\n // Receipt signer needs to be a Notary, not a Guard\n if (status.domain == 0) revert AgentNotNotary();\n }\n\n /**\n * @dev Internal function to verify the signed receipt report payload.\n * Reverts if any of these is true:\n * - Report signer is not a known Guard.\n * @param rcpt Typed memory view over receipt payload that Guard reports as invalid\n * @param rrSignature Guard signature for the \"invalid receipt\" report\n * @return status Struct representing guard status, see {_recoverAgent}\n * @return guard Guard that signed the report\n */\n function _verifyReceiptReport(Receipt rcpt, bytes memory rrSignature)\n internal\n view\n returns (AgentStatus memory status, address guard)\n {\n // This will revert if signer is not a known agent\n (status, guard) = _recoverAgent(rcpt.hashInvalid(), rrSignature);\n // Report signer needs to be a Guard, not a Notary\n if (status.domain != 0) revert AgentNotGuard();\n }\n\n // ═══════════════════════════════════════ STATE/SNAPSHOT RELATED CHECKS ═══════════════════════════════════════════\n\n /**\n * @dev Internal function to verify the signed snapshot report payload.\n * Reverts if any of these is true:\n * - Report signer is not a known Guard.\n * @param state Typed memory view over state payload that Guard reports as invalid\n * @param srSignature Guard signature for the report\n * @return status Struct representing guard status, see {_recoverAgent}\n * @return guard Guard that signed the report\n */\n function _verifyStateReport(State state, bytes memory srSignature)\n internal\n view\n returns (AgentStatus memory status, address guard)\n {\n // This will revert if signer is not a known agent\n (status, guard) = _recoverAgent(state.hashInvalid(), srSignature);\n // Report signer needs to be a Guard, not a Notary\n if (status.domain != 0) revert AgentNotGuard();\n }\n\n /**\n * @dev Internal function to verify the signed snapshot payload.\n * Reverts if any of these is true:\n * - Snapshot signer is not a known Agent.\n * - Snapshot signer is not a Notary (if verifyNotary is true).\n * @param snapshot Typed memory view over snapshot payload\n * @param snapSignature Agent signature for the snapshot\n * @param verifyNotary If true, snapshot signer needs to be a Notary, not a Guard\n * @return status Struct representing agent status, see {_recoverAgent}\n * @return agent Agent that signed the snapshot\n */\n function _verifySnapshot(Snapshot snapshot, bytes memory snapSignature, bool verifyNotary)\n internal\n view\n returns (AgentStatus memory status, address agent)\n {\n // This will revert if signer is not a known agent\n (status, agent) = _recoverAgent(snapshot.hashValid(), snapSignature);\n // If requested, snapshot signer needs to be a Notary, not a Guard\n if (verifyNotary \u0026\u0026 status.domain == 0) revert AgentNotNotary();\n }\n\n // ═══════════════════════════════════════════ MERKLE RELATED CHECKS ═══════════════════════════════════════════════\n\n /**\n * @dev Internal function to verify that snapshot roots match.\n * Reverts if any of these is true:\n * - Attestation root is not equal to Merkle Root derived from State and Snapshot Proof.\n * - Snapshot Proof's first element does not match the State metadata.\n * - Snapshot Proof length exceeds Snapshot tree Height.\n * - State index is out of range.\n * @param att Typed memory view over Attestation\n * @param stateIndex Index of state in the snapshot\n * @param state Typed memory view over the provided state payload\n * @param snapProof Raw payload with snapshot data\n */\n function _verifySnapshotMerkle(Attestation att, uint8 stateIndex, State state, bytes32[] memory snapProof)\n internal\n pure\n {\n // Snapshot proof first element should match State metadata (aka \"right sub-leaf\")\n (, bytes32 rightSubLeaf) = state.subLeafs();\n if (snapProof[0] != rightSubLeaf) revert IncorrectSnapshotProof();\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(state.root(), state.origin(), snapProof, stateIndex);\n // Snapshot root should match the attestation root\n if (att.snapRoot() != snapshotRoot) revert IncorrectSnapshotRoot();\n }\n}\n\n// contracts/inbox/Inbox.sol\n\n// ══════════════════════════════ LIBRARY IMPORTS ══════════════════════════════\n\n// ═════════════════════════════ INTERNAL IMPORTS ══════════════════════════════\n\n/// @notice `Inbox` is the child of `StatementInbox` contract, that is used on Synapse Chain.\n/// In addition to the functionality of `StatementInbox`, it also:\n/// - Accepts Guard and Notary Snapshots and passes them to `Summit` contract.\n/// - Accepts Notary-signed Receipts and passes them to `Summit` contract.\n/// - Accepts Receipt Reports to initiate a dispute between Guard and Notary.\n/// - Verifies Attestations and Attestation Reports, and slashes the signer if they are invalid.\ncontract Inbox is StatementInbox, InboxEvents, InterfaceInbox {\n using AttestationLib for bytes;\n using ReceiptLib for bytes;\n using SnapshotLib for bytes;\n\n // Struct to get around stack too deep error. TODO: revisit this\n struct ReceiptInfo {\n AgentStatus rcptNotaryStatus;\n address notary;\n uint32 attNonce;\n AgentStatus attNotaryStatus;\n }\n\n // ══════════════════════════════════════════════════ STORAGE ══════════════════════════════════════════════════════\n\n // The address of the Summit contract.\n address public summit;\n\n // ═════════════════════════════════════════ CONSTRUCTOR \u0026 INITIALIZER ═════════════════════════════════════════════\n\n constructor(uint32 synapseDomain_) MessagingBase(\"0.0.3\", synapseDomain_) {\n if (localDomain != synapseDomain) revert MustBeSynapseDomain();\n }\n\n /// @notice Initializes `Inbox` contract:\n /// - Sets `msg.sender` as the owner of the contract\n /// - Sets `agentManager`, `origin`, `destination` and `summit` addresses\n function initialize(address agentManager_, address origin_, address destination_, address summit_)\n external\n initializer\n {\n __StatementInbox_init(agentManager_, origin_, destination_);\n summit = summit_;\n }\n\n // ══════════════════════════════════════════ SUBMIT AGENT STATEMENTS ══════════════════════════════════════════════\n\n /// @inheritdoc InterfaceInbox\n function submitSnapshot(bytes memory snapPayload, bytes memory snapSignature)\n external\n returns (bytes memory attPayload, bytes32 agentRoot_, uint256[] memory snapGas)\n {\n // This will revert if payload is not a snapshot\n Snapshot snapshot = snapPayload.castToSnapshot();\n // This will revert if the signer is not a known Guard/Notary\n (AgentStatus memory status, address agent) =\n _verifySnapshot({snapshot: snapshot, snapSignature: snapSignature, verifyNotary: false});\n // Check that Agent is active\n status.verifyActive();\n // Store Agent signature for the Snapshot\n uint256 sigIndex = _saveSignature(snapSignature);\n if (status.domain == 0) {\n // Guard that is in Dispute could still submit new snapshots, so we don't check that\n InterfaceSummit(summit).acceptGuardSnapshot({\n guardIndex: status.index,\n sigIndex: sigIndex,\n snapPayload: snapPayload\n });\n } else {\n // Get current agentRoot from AgentManager\n agentRoot_ = IAgentManager(agentManager).agentRoot();\n // This will revert if Notary is in Dispute\n attPayload = InterfaceSummit(summit).acceptNotarySnapshot({\n notaryIndex: status.index,\n sigIndex: sigIndex,\n agentRoot: agentRoot_,\n snapPayload: snapPayload\n });\n ChainGas[] memory snapGas_ = snapshot.snapGas();\n // Pass created attestation to Destination to enable executing messages coming to Synapse Chain\n InterfaceDestination(destination).acceptAttestation(\n status.index, type(uint256).max, attPayload, agentRoot_, snapGas_\n );\n // Use assembly to cast ChainGas[] to uint256[] without copying. Highest bits are left zeroed.\n // solhint-disable-next-line no-inline-assembly\n assembly {\n snapGas := snapGas_\n }\n }\n emit SnapshotAccepted(status.domain, agent, snapPayload, snapSignature);\n }\n\n /// @inheritdoc InterfaceInbox\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 // Struct to get around stack too deep error.\n ReceiptInfo memory info;\n // This will revert if payload is not a receipt\n Receipt rcpt = rcptPayload.castToReceipt();\n // This will revert if the receipt signer is not a known Notary\n (info.rcptNotaryStatus, info.notary) = _verifyReceipt(rcpt, rcptSignature);\n // Receipt Notary needs to be Active\n info.rcptNotaryStatus.verifyActive();\n info.attNonce = IExecutionHub(destination).getAttestationNonce(rcpt.snapshotRoot());\n if (info.attNonce == 0) revert IncorrectSnapshotRoot();\n // Attestation Notary domain needs to match the destination domain\n info.attNotaryStatus = IAgentManager(agentManager).agentStatus(rcpt.attNotary());\n if (info.attNotaryStatus.domain != rcpt.destination()) revert IncorrectAgentDomain();\n // Check that the correct tip values for the message were provided\n _verifyReceiptTips(rcpt.messageHash(), paddedTips, headerHash, bodyHash);\n // Store Notary signature for the Receipt\n uint256 sigIndex = _saveSignature(rcptSignature);\n // This will revert if Receipt Notary is in Dispute\n wasAccepted = InterfaceSummit(summit).acceptReceipt({\n rcptNotaryIndex: info.rcptNotaryStatus.index,\n attNotaryIndex: info.attNotaryStatus.index,\n sigIndex: sigIndex,\n attNonce: info.attNonce,\n paddedTips: paddedTips,\n rcptPayload: rcptPayload\n });\n if (wasAccepted) {\n emit ReceiptAccepted(info.rcptNotaryStatus.domain, info.notary, rcptPayload, rcptSignature);\n }\n }\n\n /// @inheritdoc InterfaceInbox\n function submitReceiptReport(bytes memory rcptPayload, bytes memory rcptSignature, bytes memory rrSignature)\n external\n returns (bool wasAccepted)\n {\n // This will revert if payload is not a receipt\n Receipt rcpt = rcptPayload.castToReceipt();\n // This will revert if the receipt signer is not a known Guard\n (AgentStatus memory guardStatus,) = _verifyReceiptReport(rcpt, rrSignature);\n // Guard needs to be Active\n guardStatus.verifyActive();\n // This will revert if report signer is not a known Notary\n (AgentStatus memory notaryStatus,) = _verifyReceipt(rcpt, rcptSignature);\n // Notary needs to be Active/Unstaking\n notaryStatus.verifyActiveUnstaking();\n _saveReport(rcptPayload, rrSignature);\n // This will revert if either actor is already in dispute\n IAgentManager(agentManager).openDispute(guardStatus.index, notaryStatus.index);\n return true;\n }\n\n /// @inheritdoc InterfaceInbox\n function passReceipt(uint32 attNotaryIndex, uint32 attNonce, uint256 paddedTips, bytes memory rcptPayload)\n external\n returns (bool wasAccepted)\n {\n // Only Destination can pass receipts\n if (msg.sender != destination) revert CallerNotDestination();\n return InterfaceSummit(summit).acceptReceipt({\n rcptNotaryIndex: attNotaryIndex,\n attNotaryIndex: attNotaryIndex,\n sigIndex: type(uint256).max,\n attNonce: attNonce,\n paddedTips: paddedTips,\n rcptPayload: rcptPayload\n });\n }\n\n // ══════════════════════════════════════════ VERIFY AGENT STATEMENTS ══════════════════════════════════════════════\n\n /// @inheritdoc InterfaceInbox\n function verifyAttestation(bytes memory attPayload, bytes memory attSignature)\n external\n returns (bool isValidAttestation)\n {\n // This will revert if payload is not an attestation\n Attestation att = attPayload.castToAttestation();\n // This will revert if the attestation signer is not a known Notary\n (AgentStatus memory status, address notary) = _verifyAttestation(att, attSignature);\n // Notary needs to be Active/Unstaking\n status.verifyActiveUnstaking();\n isValidAttestation = ISnapshotHub(summit).isValidAttestation(attPayload);\n if (!isValidAttestation) {\n emit InvalidAttestation(attPayload, attSignature);\n IAgentManager(agentManager).slashAgent(status.domain, notary, msg.sender);\n }\n }\n\n /// @inheritdoc InterfaceInbox\n function verifyAttestationReport(bytes memory attPayload, bytes memory arSignature)\n external\n returns (bool isValidReport)\n {\n // This will revert if payload is not an attestation\n Attestation att = attPayload.castToAttestation();\n // This will revert if the report signer is not a known Guard\n (AgentStatus memory status, address guard) = _verifyAttestationReport(att, arSignature);\n // Guard needs to be Active/Unstaking\n status.verifyActiveUnstaking();\n // Report is valid IF AND ONLY IF the reported attestation in invalid\n isValidReport = !ISnapshotHub(summit).isValidAttestation(attPayload);\n if (!isValidReport) {\n emit InvalidAttestationReport(attPayload, arSignature);\n IAgentManager(agentManager).slashAgent(status.domain, guard, msg.sender);\n }\n }\n\n // ══════════════════════════════════════════════ INTERNAL VIEWS ═══════════════════════════════════════════════════\n\n /// @dev Verifies that tips proof matches the message hash.\n function _verifyReceiptTips(bytes32 msgHash, uint256 paddedTips, bytes32 headerHash, bytes32 bodyHash)\n internal\n pure\n {\n Tips tips = TipsLib.wrapPadded(paddedTips);\n // full message leaf is (header, baseMessage), while base message leaf is (tips, remainingBody).\n if (MerkleMath.getParent(headerHash, MerkleMath.getParent(tips.leaf(), bodyHash)) != msgHash) {\n revert IncorrectTipsProof();\n }\n }\n}\n","language":"Solidity","languageVersion":"0.8.17","compilerVersion":"0.8.17","compilerOptions":"--combined-json bin,bin-runtime,srcmap,srcmap-runtime,abi,userdoc,devdoc,metadata,hashes --optimize --optimize-runs 10000 --allow-paths ., ./, ../","srcMap":"","srcMapRuntime":"","abiDefinition":[{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint8","name":"version","type":"uint8"}],"name":"Initialized","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"}],"userDoc":{"kind":"user","methods":{},"version":1},"developerDoc":{"details":"Contract module which provides a basic access control mechanism, where there is an account (an owner) that can be granted exclusive access to specific functions. By default, the owner account will be the one that deploys the contract. This can later be changed with {transferOwnership}. This module is used through inheritance. It will make available the modifier `onlyOwner`, which can be applied to your functions to restrict their use to the owner.","kind":"dev","methods":{"owner()":{"details":"Returns the address of the current owner."},"renounceOwnership()":{"details":"Leaves the contract without owner. It will not be possible to call `onlyOwner` functions. Can only be called by the current owner. NOTE: Renouncing ownership will leave the contract without an owner, thereby disabling any functionality that is only available to the owner."},"transferOwnership(address)":{"details":"Transfers ownership of the contract to a new account (`newOwner`). Can only be called by the current owner."}},"stateVariables":{"__gap":{"details":"This empty reserved space is put in place to allow future versions to add new variables without shifting down storage in the inheritance chain. See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps"}},"version":1},"metadata":"{\"compiler\":{\"version\":\"0.8.17+commit.8df45f5f\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint8\",\"name\":\"version\",\"type\":\"uint8\"}],\"name\":\"Initialized\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"previousOwner\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"OwnershipTransferred\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"renounceOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}],\"devdoc\":{\"details\":\"Contract module which provides a basic access control mechanism, where there is an account (an owner) that can be granted exclusive access to specific functions. By default, the owner account will be the one that deploys the contract. This can later be changed with {transferOwnership}. This module is used through inheritance. It will make available the modifier `onlyOwner`, which can be applied to your functions to restrict their use to the owner.\",\"kind\":\"dev\",\"methods\":{\"owner()\":{\"details\":\"Returns the address of the current owner.\"},\"renounceOwnership()\":{\"details\":\"Leaves the contract without owner. It will not be possible to call `onlyOwner` functions. Can only be called by the current owner. NOTE: Renouncing ownership will leave the contract without an owner, thereby disabling any functionality that is only available to the owner.\"},\"transferOwnership(address)\":{\"details\":\"Transfers ownership of the contract to a new account (`newOwner`). Can only be called by the current owner.\"}},\"stateVariables\":{\"__gap\":{\"details\":\"This empty reserved space is put in place to allow future versions to add new variables without shifting down storage in the inheritance chain. See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\"}},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"solidity/Inbox.sol\":\"OwnableUpgradeable\"},\"evmVersion\":\"london\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\"},\"optimizer\":{\"enabled\":true,\"runs\":10000},\"remappings\":[]},\"sources\":{\"solidity/Inbox.sol\":{\"keccak256\":\"0x9b516081a036814c0169e20e484d4a5499066b7a6f48fada952b5e844a1ca3e5\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://32bde393b3f24ef4307d9626d4143f337b3c0bd34e17bb969fd5a15221d96987\",\"dweb:/ipfs/QmTkt2XZRtgsbSpmsVQUM3c4ebETQoDVYbmEV9yheBghnr\"]}},\"version\":1}"},"hashes":{"owner()":"8da5cb5b","renounceOwnership()":"715018a6","transferOwnership(address)":"f2fde38b"}},"solidity/Inbox.sol:ReceiptLib":{"code":"0x60566037600b82828239805160001a607314602a57634e487b7160e01b600052600060045260246000fd5b30600052607381538281f3fe73000000000000000000000000000000000000000030146080604052600080fdfea26469706673582212203e3ed32f65ccedda6cde6b0c882d0275a7fbe6cb92f2e882c04bd72a31db69ba64736f6c63430008110033","runtime-code":"0x73000000000000000000000000000000000000000030146080604052600080fdfea26469706673582212203e3ed32f65ccedda6cde6b0c882d0275a7fbe6cb92f2e882c04bd72a31db69ba64736f6c63430008110033","info":{"source":"// SPDX-License-Identifier: MIT\npragma solidity =0.8.17 ^0.8.0 ^0.8.1 ^0.8.2;\n\n// contracts/events/InboxEvents.sol\n\nabstract contract InboxEvents {\n /**\n * @notice Emitted when a snapshot is accepted by the Summit contract.\n * @param domain Domain where the signed Agent is active (ZERO for Guards)\n * @param agent Agent who signed the snapshot\n * @param snapPayload Raw payload with snapshot data\n * @param snapSignature Agent signature for the snapshot\n */\n event SnapshotAccepted(uint32 indexed domain, address indexed agent, bytes snapPayload, bytes snapSignature);\n\n /**\n * @notice Emitted when a snapshot is accepted by the Summit contract.\n * @param domain Domain where the signed Notary is active\n * @param notary Notary who signed the attestation\n * @param rcptPayload Raw payload with receipt data\n * @param rcptSignature Notary signature for the receipt\n */\n event ReceiptAccepted(uint32 domain, address notary, bytes rcptPayload, bytes rcptSignature);\n\n /**\n * @notice Emitted when a proof of invalid attestation is submitted.\n * @param attPayload Raw payload with Attestation data\n * @param attSignature Notary signature for the attestation\n */\n event InvalidAttestation(bytes attPayload, bytes attSignature);\n\n /**\n * @notice Emitted when a proof of invalid attestation report is submitted.\n * @param arPayload Raw payload with report data\n * @param arSignature Guard signature for the report\n */\n event InvalidAttestationReport(bytes arPayload, bytes arSignature);\n}\n\n// contracts/events/StatementInboxEvents.sol\n\nabstract contract StatementInboxEvents {\n // ════════════════════════════════════════════ STATEMENT ACCEPTED ═════════════════════════════════════════════════\n\n /**\n * @notice Emitted when a snapshot is accepted by the Destination contract.\n * @param domain Domain where the signed Notary is active\n * @param notary Notary who signed the attestation\n * @param attPayload Raw payload with attestation data\n * @param attSignature Notary signature for the attestation\n */\n event AttestationAccepted(uint32 domain, address notary, bytes attPayload, bytes attSignature);\n\n // ═════════════════════════════════════════ INVALID STATEMENT PROVED ══════════════════════════════════════════════\n\n /**\n * @notice Emitted when a proof of invalid receipt statement is submitted.\n * @param rcptPayload Raw payload with the receipt statement\n * @param rcptSignature Notary signature for the receipt statement\n */\n event InvalidReceipt(bytes rcptPayload, bytes rcptSignature);\n\n /**\n * @notice Emitted when a proof of invalid receipt report is submitted.\n * @param rrPayload Raw payload with report data\n * @param rrSignature Guard signature for the report\n */\n event InvalidReceiptReport(bytes rrPayload, bytes rrSignature);\n\n /**\n * @notice Emitted when a proof of invalid state in the signed attestation is submitted.\n * @param stateIndex Index of invalid state in the snapshot\n * @param statePayload Raw payload with state data\n * @param attPayload Raw payload with Attestation data for snapshot\n * @param attSignature Notary signature for the attestation\n */\n event InvalidStateWithAttestation(uint8 stateIndex, bytes statePayload, bytes attPayload, bytes attSignature);\n\n /**\n * @notice Emitted when a proof of invalid state in the signed snapshot is submitted.\n * @param stateIndex Index of invalid state in the snapshot\n * @param snapPayload Raw payload with snapshot data\n * @param snapSignature Agent signature for the snapshot\n */\n event InvalidStateWithSnapshot(uint8 stateIndex, bytes snapPayload, bytes snapSignature);\n\n /**\n * @notice Emitted when a proof of invalid state report is submitted.\n * @param srPayload Raw payload with report data\n * @param srSignature Guard signature for the report\n */\n event InvalidStateReport(bytes srPayload, bytes srSignature);\n}\n\n// contracts/interfaces/ISnapshotHub.sol\n\ninterface ISnapshotHub {\n /**\n * @notice Check that a given attestation is valid: matches the historical attestation\n * derived from an accepted Notary snapshot.\n * @dev Will revert if any of these is true:\n * - Attestation payload is not properly formatted.\n * @param attPayload Raw payload with attestation data\n * @return isValid Whether the provided attestation is valid\n */\n function isValidAttestation(bytes memory attPayload) external view returns (bool isValid);\n\n /**\n * @notice Returns saved attestation with the given nonce.\n * @dev Reverts if attestation with given nonce hasn't been created yet.\n * @param attNonce Nonce for the attestation\n * @return attPayload Raw payload with formatted Attestation data\n * @return agentRoot Agent root hash used for the attestation\n * @return snapGas Snapshot gas data used for the attestation\n */\n function getAttestation(uint32 attNonce)\n external\n view\n returns (bytes memory attPayload, bytes32 agentRoot, uint256[] memory snapGas);\n\n /**\n * @notice Returns the state with the highest known nonce submitted by a given Agent.\n * @param origin Domain of origin chain\n * @param agent Agent address\n * @return statePayload Raw payload with agent's latest state for origin\n */\n function getLatestAgentState(uint32 origin, address agent) external view returns (bytes memory statePayload);\n\n /**\n * @notice Returns latest saved attestation for a Notary.\n * @param notary Notary address\n * @return attPayload Raw payload with formatted Attestation data\n * @return agentRoot Agent root hash used for the attestation\n * @return snapGas Snapshot gas data used for the attestation\n */\n function getLatestNotaryAttestation(address notary)\n external\n view\n returns (bytes memory attPayload, bytes32 agentRoot, uint256[] memory snapGas);\n\n /**\n * @notice Returns Guard snapshot from the list of all accepted Guard snapshots.\n * @dev Reverts if snapshot with given index hasn't been accepted yet.\n * @param index Snapshot index in the list of all Guard snapshots\n * @return snapPayload Raw payload with Guard snapshot\n * @return snapSignature Raw payload with Guard signature for snapshot\n */\n function getGuardSnapshot(uint256 index)\n external\n view\n returns (bytes memory snapPayload, bytes memory snapSignature);\n\n /**\n * @notice Returns Notary snapshot from the list of all accepted Guard snapshots.\n * @dev Reverts if snapshot with given index hasn't been accepted yet.\n * @param index Snapshot index in the list of all Notary snapshots\n * @return snapPayload Raw payload with Notary snapshot\n * @return snapSignature Raw payload with Notary signature for snapshot\n */\n function getNotarySnapshot(uint256 index)\n external\n view\n returns (bytes memory snapPayload, bytes memory snapSignature);\n\n /**\n * @notice Returns Notary snapshot that was used for creating a given attestation.\n * @dev Reverts if any of these is true:\n * - Attestation payload is not properly formatted.\n * - Attestation is invalid (doesn't have a matching Notary snapshot).\n * @param attPayload Raw payload with attestation data\n * @return snapPayload Raw payload with Notary snapshot\n * @return snapSignature Raw payload with Notary signature for snapshot\n */\n function getNotarySnapshot(bytes memory attPayload)\n external\n view\n returns (bytes memory snapPayload, bytes memory snapSignature);\n\n /**\n * @notice Returns proof of inclusion of (root, origin) fields of a given snapshot's state\n * into the Snapshot Merkle Tree for a given attestation.\n * @dev Reverts if any of these is true:\n * - Attestation with given nonce hasn't been created yet.\n * - State index is out of range of snapshot list.\n * @param attNonce Nonce for the attestation\n * @param stateIndex Index of state in the attestation's snapshot\n * @return snapProof The snapshot proof\n */\n function getSnapshotProof(uint32 attNonce, uint8 stateIndex) external view returns (bytes32[] memory snapProof);\n}\n\n// contracts/interfaces/IStateHub.sol\n\ninterface IStateHub {\n /**\n * @notice Check that a given state is valid: matches the historical state of Origin contract.\n * Note: any Agent including an invalid state in their snapshot will be slashed\n * upon providing the snapshot and agent signature for it to Origin contract.\n * @dev Will revert if any of these is true:\n * - State payload is not properly formatted.\n * @param statePayload Raw payload with state data\n * @return isValid Whether the provided state is valid\n */\n function isValidState(bytes memory statePayload) external view returns (bool isValid);\n\n /**\n * @notice Returns the amount of saved states so far.\n * @dev This includes the initial state of \"empty Origin Merkle Tree\".\n */\n function statesAmount() external view returns (uint256);\n\n /**\n * @notice Suggest the data (state after latest sent message) to sign for an Agent.\n * Note: signing the suggested state data will will never lead to slashing of the actor,\n * assuming they have confirmed that the block, which number is included in the data,\n * is not subject to reorganization (which is different for every observed chain).\n * @return statePayload Raw payload with the latest state data\n */\n function suggestLatestState() external view returns (bytes memory statePayload);\n\n /**\n * @notice Given the historical nonce, suggest the state data to sign for an Agent.\n * Note: signing the suggested state data will will never lead to slashing of the actor,\n * assuming they have confirmed that the block, which number is included in the data,\n * is not subject to reorganization (which is different for every observed chain).\n * @param nonce Historical nonce to form a state\n * @return statePayload Raw payload with historical state data\n */\n function suggestState(uint32 nonce) external view returns (bytes memory statePayload);\n}\n\n// contracts/interfaces/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/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// node_modules/@openzeppelin/contracts/utils/math/Math.sol\n\n// OpenZeppelin Contracts (last updated v4.9.0) (utils/math/Math.sol)\n\n/**\n * @dev Standard math utilities missing in the Solidity language.\n */\nlibrary Math {\n enum Rounding {\n Down, // Toward negative infinity\n Up, // Toward infinity\n Zero // Toward zero\n }\n\n /**\n * @dev Returns the largest of two numbers.\n */\n function max(uint256 a, uint256 b) internal pure returns (uint256) {\n return a \u003e b ? a : b;\n }\n\n /**\n * @dev Returns the smallest of two numbers.\n */\n function min(uint256 a, uint256 b) internal pure returns (uint256) {\n return a \u003c b ? a : b;\n }\n\n /**\n * @dev Returns the average of two numbers. The result is rounded towards\n * zero.\n */\n function average(uint256 a, uint256 b) internal pure returns (uint256) {\n // (a + b) / 2 can overflow.\n return (a \u0026 b) + (a ^ b) / 2;\n }\n\n /**\n * @dev Returns the ceiling of the division of two numbers.\n *\n * This differs from standard division with `/` in that it rounds up instead\n * of rounding down.\n */\n function ceilDiv(uint256 a, uint256 b) internal pure returns (uint256) {\n // (a + b - 1) / b can overflow on addition, so we distribute.\n return a == 0 ? 0 : (a - 1) / b + 1;\n }\n\n /**\n * @notice Calculates floor(x * y / denominator) with full precision. Throws if result overflows a uint256 or denominator == 0\n * @dev Original credit to Remco Bloemen under MIT license (https://xn--2-umb.com/21/muldiv)\n * with further edits by Uniswap Labs also under MIT license.\n */\n function mulDiv(uint256 x, uint256 y, uint256 denominator) internal pure returns (uint256 result) {\n unchecked {\n // 512-bit multiply [prod1 prod0] = x * y. Compute the product mod 2^256 and mod 2^256 - 1, then use\n // use the Chinese Remainder Theorem to reconstruct the 512 bit result. The result is stored in two 256\n // variables such that product = prod1 * 2^256 + prod0.\n uint256 prod0; // Least significant 256 bits of the product\n uint256 prod1; // Most significant 256 bits of the product\n assembly {\n let mm := mulmod(x, y, not(0))\n prod0 := mul(x, y)\n prod1 := sub(sub(mm, prod0), lt(mm, prod0))\n }\n\n // Handle non-overflow cases, 256 by 256 division.\n if (prod1 == 0) {\n // Solidity will revert if denominator == 0, unlike the div opcode on its own.\n // The surrounding unchecked block does not change this fact.\n // See https://docs.soliditylang.org/en/latest/control-structures.html#checked-or-unchecked-arithmetic.\n return prod0 / denominator;\n }\n\n // Make sure the result is less than 2^256. Also prevents denominator == 0.\n require(denominator \u003e prod1, \"Math: mulDiv overflow\");\n\n ///////////////////////////////////////////////\n // 512 by 256 division.\n ///////////////////////////////////////////////\n\n // Make division exact by subtracting the remainder from [prod1 prod0].\n uint256 remainder;\n assembly {\n // Compute remainder using mulmod.\n remainder := mulmod(x, y, denominator)\n\n // Subtract 256 bit number from 512 bit number.\n prod1 := sub(prod1, gt(remainder, prod0))\n prod0 := sub(prod0, remainder)\n }\n\n // Factor powers of two out of denominator and compute largest power of two divisor of denominator. Always \u003e= 1.\n // See https://cs.stackexchange.com/q/138556/92363.\n\n // Does not overflow because the denominator cannot be zero at this stage in the function.\n uint256 twos = denominator \u0026 (~denominator + 1);\n assembly {\n // Divide denominator by twos.\n denominator := div(denominator, twos)\n\n // Divide [prod1 prod0] by twos.\n prod0 := div(prod0, twos)\n\n // Flip twos such that it is 2^256 / twos. If twos is zero, then it becomes one.\n twos := add(div(sub(0, twos), twos), 1)\n }\n\n // Shift in bits from prod1 into prod0.\n prod0 |= prod1 * twos;\n\n // Invert denominator mod 2^256. Now that denominator is an odd number, it has an inverse modulo 2^256 such\n // that denominator * inv = 1 mod 2^256. Compute the inverse by starting with a seed that is correct for\n // four bits. That is, denominator * inv = 1 mod 2^4.\n uint256 inverse = (3 * denominator) ^ 2;\n\n // Use the Newton-Raphson iteration to improve the precision. Thanks to Hensel's lifting lemma, this also works\n // in modular arithmetic, doubling the correct bits in each step.\n inverse *= 2 - denominator * inverse; // inverse mod 2^8\n inverse *= 2 - denominator * inverse; // inverse mod 2^16\n inverse *= 2 - denominator * inverse; // inverse mod 2^32\n inverse *= 2 - denominator * inverse; // inverse mod 2^64\n inverse *= 2 - denominator * inverse; // inverse mod 2^128\n inverse *= 2 - denominator * inverse; // inverse mod 2^256\n\n // Because the division is now exact we can divide by multiplying with the modular inverse of denominator.\n // This will give us the correct result modulo 2^256. Since the preconditions guarantee that the outcome is\n // less than 2^256, this is the final result. We don't need to compute the high bits of the result and prod1\n // is no longer required.\n result = prod0 * inverse;\n return result;\n }\n }\n\n /**\n * @notice Calculates x * y / denominator with full precision, following the selected rounding direction.\n */\n function mulDiv(uint256 x, uint256 y, uint256 denominator, Rounding rounding) internal pure returns (uint256) {\n uint256 result = mulDiv(x, y, denominator);\n if (rounding == Rounding.Up \u0026\u0026 mulmod(x, y, denominator) \u003e 0) {\n result += 1;\n }\n return result;\n }\n\n /**\n * @dev Returns the square root of a number. If the number is not a perfect square, the value is rounded down.\n *\n * Inspired by Henry S. Warren, Jr.'s \"Hacker's Delight\" (Chapter 11).\n */\n function sqrt(uint256 a) internal pure returns (uint256) {\n if (a == 0) {\n return 0;\n }\n\n // For our first guess, we get the biggest power of 2 which is smaller than the square root of the target.\n //\n // We know that the \"msb\" (most significant bit) of our target number `a` is a power of 2 such that we have\n // `msb(a) \u003c= a \u003c 2*msb(a)`. This value can be written `msb(a)=2**k` with `k=log2(a)`.\n //\n // This can be rewritten `2**log2(a) \u003c= a \u003c 2**(log2(a) + 1)`\n // → `sqrt(2**k) \u003c= sqrt(a) \u003c sqrt(2**(k+1))`\n // → `2**(k/2) \u003c= sqrt(a) \u003c 2**((k+1)/2) \u003c= 2**(k/2 + 1)`\n //\n // Consequently, `2**(log2(a) / 2)` is a good first approximation of `sqrt(a)` with at least 1 correct bit.\n uint256 result = 1 \u003c\u003c (log2(a) \u003e\u003e 1);\n\n // At this point `result` is an estimation with one bit of precision. We know the true value is a uint128,\n // since it is the square root of a uint256. Newton's method converges quadratically (precision doubles at\n // every iteration). We thus need at most 7 iteration to turn our partial result with one bit of precision\n // into the expected uint128 result.\n unchecked {\n result = (result + a / result) \u003e\u003e 1;\n result = (result + a / result) \u003e\u003e 1;\n result = (result + a / result) \u003e\u003e 1;\n result = (result + a / result) \u003e\u003e 1;\n result = (result + a / result) \u003e\u003e 1;\n result = (result + a / result) \u003e\u003e 1;\n result = (result + a / result) \u003e\u003e 1;\n return min(result, a / result);\n }\n }\n\n /**\n * @notice Calculates sqrt(a), following the selected rounding direction.\n */\n function sqrt(uint256 a, Rounding rounding) internal pure returns (uint256) {\n unchecked {\n uint256 result = sqrt(a);\n return result + (rounding == Rounding.Up \u0026\u0026 result * result \u003c a ? 1 : 0);\n }\n }\n\n /**\n * @dev Return the log in base 2, rounded down, of a positive value.\n * Returns 0 if given 0.\n */\n function log2(uint256 value) internal pure returns (uint256) {\n uint256 result = 0;\n unchecked {\n if (value \u003e\u003e 128 \u003e 0) {\n value \u003e\u003e= 128;\n result += 128;\n }\n if (value \u003e\u003e 64 \u003e 0) {\n value \u003e\u003e= 64;\n result += 64;\n }\n if (value \u003e\u003e 32 \u003e 0) {\n value \u003e\u003e= 32;\n result += 32;\n }\n if (value \u003e\u003e 16 \u003e 0) {\n value \u003e\u003e= 16;\n result += 16;\n }\n if (value \u003e\u003e 8 \u003e 0) {\n value \u003e\u003e= 8;\n result += 8;\n }\n if (value \u003e\u003e 4 \u003e 0) {\n value \u003e\u003e= 4;\n result += 4;\n }\n if (value \u003e\u003e 2 \u003e 0) {\n value \u003e\u003e= 2;\n result += 2;\n }\n if (value \u003e\u003e 1 \u003e 0) {\n result += 1;\n }\n }\n return result;\n }\n\n /**\n * @dev Return the log in base 2, following the selected rounding direction, of a positive value.\n * Returns 0 if given 0.\n */\n function log2(uint256 value, Rounding rounding) internal pure returns (uint256) {\n unchecked {\n uint256 result = log2(value);\n return result + (rounding == Rounding.Up \u0026\u0026 1 \u003c\u003c result \u003c value ? 1 : 0);\n }\n }\n\n /**\n * @dev Return the log in base 10, rounded down, of a positive value.\n * Returns 0 if given 0.\n */\n function log10(uint256 value) internal pure returns (uint256) {\n uint256 result = 0;\n unchecked {\n if (value \u003e= 10 ** 64) {\n value /= 10 ** 64;\n result += 64;\n }\n if (value \u003e= 10 ** 32) {\n value /= 10 ** 32;\n result += 32;\n }\n if (value \u003e= 10 ** 16) {\n value /= 10 ** 16;\n result += 16;\n }\n if (value \u003e= 10 ** 8) {\n value /= 10 ** 8;\n result += 8;\n }\n if (value \u003e= 10 ** 4) {\n value /= 10 ** 4;\n result += 4;\n }\n if (value \u003e= 10 ** 2) {\n value /= 10 ** 2;\n result += 2;\n }\n if (value \u003e= 10 ** 1) {\n result += 1;\n }\n }\n return result;\n }\n\n /**\n * @dev Return the log in base 10, following the selected rounding direction, of a positive value.\n * Returns 0 if given 0.\n */\n function log10(uint256 value, Rounding rounding) internal pure returns (uint256) {\n unchecked {\n uint256 result = log10(value);\n return result + (rounding == Rounding.Up \u0026\u0026 10 ** result \u003c value ? 1 : 0);\n }\n }\n\n /**\n * @dev Return the log in base 256, rounded down, of a positive value.\n * Returns 0 if given 0.\n *\n * Adding one to the result gives the number of pairs of hex symbols needed to represent `value` as a hex string.\n */\n function log256(uint256 value) internal pure returns (uint256) {\n uint256 result = 0;\n unchecked {\n if (value \u003e\u003e 128 \u003e 0) {\n value \u003e\u003e= 128;\n result += 16;\n }\n if (value \u003e\u003e 64 \u003e 0) {\n value \u003e\u003e= 64;\n result += 8;\n }\n if (value \u003e\u003e 32 \u003e 0) {\n value \u003e\u003e= 32;\n result += 4;\n }\n if (value \u003e\u003e 16 \u003e 0) {\n value \u003e\u003e= 16;\n result += 2;\n }\n if (value \u003e\u003e 8 \u003e 0) {\n result += 1;\n }\n }\n return result;\n }\n\n /**\n * @dev Return the log in base 256, following the selected rounding direction, of a positive value.\n * Returns 0 if given 0.\n */\n function log256(uint256 value, Rounding rounding) internal pure returns (uint256) {\n unchecked {\n uint256 result = log256(value);\n return result + (rounding == Rounding.Up \u0026\u0026 1 \u003c\u003c (result \u003c\u003c 3) \u003c value ? 1 : 0);\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/utils/math/SignedMath.sol\n\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/math/SignedMath.sol)\n\n/**\n * @dev Standard signed math utilities missing in the Solidity language.\n */\nlibrary SignedMath {\n /**\n * @dev Returns the largest of two signed numbers.\n */\n function max(int256 a, int256 b) internal pure returns (int256) {\n return a \u003e b ? a : b;\n }\n\n /**\n * @dev Returns the smallest of two signed numbers.\n */\n function min(int256 a, int256 b) internal pure returns (int256) {\n return a \u003c b ? a : b;\n }\n\n /**\n * @dev Returns the average of two signed numbers without overflow.\n * The result is rounded towards zero.\n */\n function average(int256 a, int256 b) internal pure returns (int256) {\n // Formula from the book \"Hacker's Delight\"\n int256 x = (a \u0026 b) + ((a ^ b) \u003e\u003e 1);\n return x + (int256(uint256(x) \u003e\u003e 255) \u0026 (a ^ b));\n }\n\n /**\n * @dev Returns the absolute unsigned value of a signed value.\n */\n function abs(int256 n) internal pure returns (uint256) {\n unchecked {\n // must be unchecked in order to support `n = type(int256).min`\n return uint256(n \u003e= 0 ? n : -n);\n }\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// 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/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/InterfaceSummit.sol\n\ninterface InterfaceSummit {\n // ══════════════════════════════════════════ ACCEPT AGENT STATEMENTS ══════════════════════════════════════════════\n\n /**\n * @notice Accepts a receipt, which local `AgentManager` verified to have been signed by an active Notary.\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 * - Notary who signed the receipt is referenced as the \"Receipt Notary\".\n * - Notary who signed the attestation on destination chain is referenced as the \"Attestation Notary\".\n * \u003e Will revert if any of these is true:\n * \u003e - Called by anyone other than local `AgentManager`.\n * \u003e - Receipt body payload is not properly formatted.\n * \u003e - Receipt signer is in Dispute.\n * \u003e - Receipt's snapshot root is unknown.\n * @param rcptNotaryIndex Index of Receipt Notary in Agent Merkle Tree\n * @param attNotaryIndex Index of Attestation Notary in Agent Merkle Tree\n * @param sigIndex Index of stored Notary signature\n * @param attNonce Nonce of the attestation used for proving the executed message\n * @param paddedTips Padded encoded paid tips information\n * @param rcptPayload Raw payload with message execution receipt\n * @return wasAccepted Whether the receipt was accepted\n */\n function acceptReceipt(\n uint32 rcptNotaryIndex,\n uint32 attNotaryIndex,\n uint256 sigIndex,\n uint32 attNonce,\n uint256 paddedTips,\n bytes memory rcptPayload\n ) external returns (bool wasAccepted);\n\n /**\n * @notice Accepts a snapshot, which local `AgentManager` verified to have been signed by an active Guard.\n * \u003e Snapshot is a list of states for a set of Origin contracts residing on any of the chains.\n * All the states in the Guard-signed snapshot become available for Notary signing.\n * \u003e Will revert if any of these is true:\n * \u003e - Called by anyone other than local `AgentManager`.\n * \u003e - Snapshot payload is not properly formatted.\n * \u003e - Snapshot contains a state older then the Guard has previously submitted.\n * @param guardIndex Index of Guard in Agent Merkle Tree\n * @param sigIndex Index of stored Agent signature\n * @param snapPayload Raw payload with snapshot data\n */\n function acceptGuardSnapshot(uint32 guardIndex, uint256 sigIndex, bytes memory snapPayload) external;\n\n /**\n * @notice Accepts a snapshot, which local `AgentManager` verified to have been signed by an active Notary.\n * \u003e Snapshot is a list of states for a set of Origin contracts residing on any of the chains.\n * Snapshot Merkle Root is calculated and saved for valid snapshots, i.e.\n * snapshots which are only using states previously submitted by any of the Guards.\n * - Notary could use states singed by the same of different Guards 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 - Called by anyone other than local `AgentManager`.\n * \u003e - Snapshot payload is not properly formatted.\n * \u003e - Snapshot contains a state older then the Notary has previously submitted.\n * \u003e - Snapshot contains a state that no Guard has previously submitted.\n * @param notaryIndex Index of Notary in Agent Merkle Tree\n * @param sigIndex Index of stored Agent signature\n * @param agentRoot Current root of the Agent Merkle Tree\n * @param snapPayload Raw payload with snapshot data\n * @return attPayload Raw payload with data for attestation derived from Notary snapshot.\n */\n function acceptNotarySnapshot(uint32 notaryIndex, uint256 sigIndex, bytes32 agentRoot, bytes memory snapPayload)\n external\n returns (bytes memory attPayload);\n\n // ════════════════════════════════════════════════ TIPS LOGIC ═════════════════════════════════════════════════════\n\n /**\n * @notice Distributes tips using the first Receipt from the \"receipt quarantine queue\".\n * Possible scenarios:\n * - Receipt queue is empty =\u003e does nothing\n * - Receipt optimistic period is not over =\u003e does nothing\n * - Either of Notaries present in Receipt was slashed =\u003e receipt is deleted from the queue\n * - Either of Notaries present in Receipt in Dispute =\u003e receipt is moved to the end of queue\n * - None of the above =\u003e receipt tips are distributed\n * @dev Returned value makes it possible to do the following: `while (distributeTips()) {}`\n * @return queuePopped Whether the first element was popped from the queue\n */\n function distributeTips() external returns (bool queuePopped);\n\n /**\n * @notice Withdraws locked base message tips from requested domain Origin to the recipient.\n * This is done by a call to a local Origin contract, or by a manager message to the remote chain.\n * @dev This will revert, if the pending balance of origin tips (earned-claimed) is lower than requested.\n * @param origin Domain of chain to withdraw tips on\n * @param amount Amount of tips to withdraw\n */\n function withdrawTips(uint32 origin, uint256 amount) external;\n\n // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════\n\n /**\n * @notice Returns earned and claimed tips for the actor.\n * Note: Tips for address(0) belong to the Treasury.\n * @param actor Address of the actor\n * @param origin Domain where the tips were initially paid\n * @return earned Total amount of origin tips the actor has earned so far\n * @return claimed Total amount of origin tips the actor has claimed so far\n */\n function actorTips(address actor, uint32 origin) external view returns (uint128 earned, uint128 claimed);\n\n /**\n * @notice Returns the amount of receipts in the \"Receipt Quarantine Queue\".\n */\n function receiptQueueLength() external view returns (uint256);\n\n /**\n * @notice Returns the state with the highest known nonce\n * submitted by any of the currently active Guards.\n * @param origin Domain of origin chain\n * @return statePayload Raw payload with latest active Guard state for origin\n */\n function getLatestState(uint32 origin) external view returns (bytes memory statePayload);\n}\n\n// node_modules/@openzeppelin/contracts/utils/Strings.sol\n\n// OpenZeppelin Contracts (last updated v4.9.0) (utils/Strings.sol)\n\n/**\n * @dev String operations.\n */\nlibrary Strings {\n bytes16 private constant _SYMBOLS = \"0123456789abcdef\";\n uint8 private constant _ADDRESS_LENGTH = 20;\n\n /**\n * @dev Converts a `uint256` to its ASCII `string` decimal representation.\n */\n function toString(uint256 value) internal pure returns (string memory) {\n unchecked {\n uint256 length = Math.log10(value) + 1;\n string memory buffer = new string(length);\n uint256 ptr;\n /// @solidity memory-safe-assembly\n assembly {\n ptr := add(buffer, add(32, length))\n }\n while (true) {\n ptr--;\n /// @solidity memory-safe-assembly\n assembly {\n mstore8(ptr, byte(mod(value, 10), _SYMBOLS))\n }\n value /= 10;\n if (value == 0) break;\n }\n return buffer;\n }\n }\n\n /**\n * @dev Converts a `int256` to its ASCII `string` decimal representation.\n */\n function toString(int256 value) internal pure returns (string memory) {\n return string(abi.encodePacked(value \u003c 0 ? \"-\" : \"\", toString(SignedMath.abs(value))));\n }\n\n /**\n * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation.\n */\n function toHexString(uint256 value) internal pure returns (string memory) {\n unchecked {\n return toHexString(value, Math.log256(value) + 1);\n }\n }\n\n /**\n * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length.\n */\n function toHexString(uint256 value, uint256 length) internal pure returns (string memory) {\n bytes memory buffer = new bytes(2 * length + 2);\n buffer[0] = \"0\";\n buffer[1] = \"x\";\n for (uint256 i = 2 * length + 1; i \u003e 1; --i) {\n buffer[i] = _SYMBOLS[value \u0026 0xf];\n value \u003e\u003e= 4;\n }\n require(value == 0, \"Strings: hex length insufficient\");\n return string(buffer);\n }\n\n /**\n * @dev Converts an `address` with fixed length of 20 bytes to its not checksummed ASCII `string` hexadecimal representation.\n */\n function toHexString(address addr) internal pure returns (string memory) {\n return toHexString(uint256(uint160(addr)), _ADDRESS_LENGTH);\n }\n\n /**\n * @dev Returns true if the two strings are equal.\n */\n function equal(string memory a, string memory b) internal pure returns (bool) {\n return keccak256(bytes(a)) == keccak256(bytes(b));\n }\n}\n\n// node_modules/@openzeppelin/contracts-upgradeable/utils/ContextUpgradeable.sol\n\n// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)\n\n/**\n * @dev Provides information about the current execution context, including the\n * sender of the transaction and its data. While these are generally available\n * via msg.sender and msg.data, they should not be accessed in such a direct\n * manner, since when dealing with meta-transactions the account sending and\n * paying for execution may not be the actual sender (as far as an application\n * is concerned).\n *\n * This contract is only required for intermediate, library-like contracts.\n */\nabstract contract ContextUpgradeable is Initializable {\n function __Context_init() internal onlyInitializing {\n }\n\n function __Context_init_unchained() internal onlyInitializing {\n }\n function _msgSender() internal view virtual returns (address) {\n return msg.sender;\n }\n\n function _msgData() internal view virtual returns (bytes calldata) {\n return msg.data;\n }\n\n /**\n * @dev This empty reserved space is put in place to allow future versions to add new\n * variables without shifting down storage in the inheritance chain.\n * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\n */\n uint256[50] private __gap;\n}\n\n// contracts/libs/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/utils/cryptography/ECDSA.sol\n\n// OpenZeppelin Contracts (last updated v4.9.0) (utils/cryptography/ECDSA.sol)\n\n/**\n * @dev Elliptic Curve Digital Signature Algorithm (ECDSA) operations.\n *\n * These functions can be used to verify that a message was signed by the holder\n * of the private keys of a given address.\n */\nlibrary ECDSA {\n enum RecoverError {\n NoError,\n InvalidSignature,\n InvalidSignatureLength,\n InvalidSignatureS,\n InvalidSignatureV // Deprecated in v4.8\n }\n\n function _throwError(RecoverError error) private pure {\n if (error == RecoverError.NoError) {\n return; // no error: do nothing\n } else if (error == RecoverError.InvalidSignature) {\n revert(\"ECDSA: invalid signature\");\n } else if (error == RecoverError.InvalidSignatureLength) {\n revert(\"ECDSA: invalid signature length\");\n } else if (error == RecoverError.InvalidSignatureS) {\n revert(\"ECDSA: invalid signature 's' value\");\n }\n }\n\n /**\n * @dev Returns the address that signed a hashed message (`hash`) with\n * `signature` or error string. This address can then be used for verification purposes.\n *\n * The `ecrecover` EVM opcode allows for malleable (non-unique) signatures:\n * this function rejects them by requiring the `s` value to be in the lower\n * half order, and the `v` value to be either 27 or 28.\n *\n * IMPORTANT: `hash` _must_ be the result of a hash operation for the\n * verification to be secure: it is possible to craft signatures that\n * recover to arbitrary addresses for non-hashed data. A safe way to ensure\n * this is by receiving a hash of the original message (which may otherwise\n * be too long), and then calling {toEthSignedMessageHash} on it.\n *\n * Documentation for signature generation:\n * - with https://web3js.readthedocs.io/en/v1.3.4/web3-eth-accounts.html#sign[Web3.js]\n * - with https://docs.ethers.io/v5/api/signer/#Signer-signMessage[ethers]\n *\n * _Available since v4.3._\n */\n function tryRecover(bytes32 hash, bytes memory signature) internal pure returns (address, RecoverError) {\n if (signature.length == 65) {\n bytes32 r;\n bytes32 s;\n uint8 v;\n // ecrecover takes the signature parameters, and the only way to get them\n // currently is to use assembly.\n /// @solidity memory-safe-assembly\n assembly {\n r := mload(add(signature, 0x20))\n s := mload(add(signature, 0x40))\n v := byte(0, mload(add(signature, 0x60)))\n }\n return tryRecover(hash, v, r, s);\n } else {\n return (address(0), RecoverError.InvalidSignatureLength);\n }\n }\n\n /**\n * @dev Returns the address that signed a hashed message (`hash`) with\n * `signature`. This address can then be used for verification purposes.\n *\n * The `ecrecover` EVM opcode allows for malleable (non-unique) signatures:\n * this function rejects them by requiring the `s` value to be in the lower\n * half order, and the `v` value to be either 27 or 28.\n *\n * IMPORTANT: `hash` _must_ be the result of a hash operation for the\n * verification to be secure: it is possible to craft signatures that\n * recover to arbitrary addresses for non-hashed data. A safe way to ensure\n * this is by receiving a hash of the original message (which may otherwise\n * be too long), and then calling {toEthSignedMessageHash} on it.\n */\n function recover(bytes32 hash, bytes memory signature) internal pure returns (address) {\n (address recovered, RecoverError error) = tryRecover(hash, signature);\n _throwError(error);\n return recovered;\n }\n\n /**\n * @dev Overload of {ECDSA-tryRecover} that receives the `r` and `vs` short-signature fields separately.\n *\n * See https://eips.ethereum.org/EIPS/eip-2098[EIP-2098 short signatures]\n *\n * _Available since v4.3._\n */\n function tryRecover(bytes32 hash, bytes32 r, bytes32 vs) internal pure returns (address, RecoverError) {\n bytes32 s = vs \u0026 bytes32(0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff);\n uint8 v = uint8((uint256(vs) \u003e\u003e 255) + 27);\n return tryRecover(hash, v, r, s);\n }\n\n /**\n * @dev Overload of {ECDSA-recover} that receives the `r and `vs` short-signature fields separately.\n *\n * _Available since v4.2._\n */\n function recover(bytes32 hash, bytes32 r, bytes32 vs) internal pure returns (address) {\n (address recovered, RecoverError error) = tryRecover(hash, r, vs);\n _throwError(error);\n return recovered;\n }\n\n /**\n * @dev Overload of {ECDSA-tryRecover} that receives the `v`,\n * `r` and `s` signature fields separately.\n *\n * _Available since v4.3._\n */\n function tryRecover(bytes32 hash, uint8 v, bytes32 r, bytes32 s) internal pure returns (address, RecoverError) {\n // EIP-2 still allows signature malleability for ecrecover(). Remove this possibility and make the signature\n // unique. Appendix F in the Ethereum Yellow paper (https://ethereum.github.io/yellowpaper/paper.pdf), defines\n // the valid range for s in (301): 0 \u003c s \u003c secp256k1n ÷ 2 + 1, and for v in (302): v ∈ {27, 28}. Most\n // signatures from current libraries generate a unique signature with an s-value in the lower half order.\n //\n // If your library generates malleable signatures, such as s-values in the upper range, calculate a new s-value\n // with 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141 - s1 and flip v from 27 to 28 or\n // vice versa. If your library also generates signatures with 0/1 for v instead 27/28, add 27 to v to accept\n // these malleable signatures as well.\n if (uint256(s) \u003e 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0) {\n return (address(0), RecoverError.InvalidSignatureS);\n }\n\n // If the signature is valid (and not malleable), return the signer address\n address signer = ecrecover(hash, v, r, s);\n if (signer == address(0)) {\n return (address(0), RecoverError.InvalidSignature);\n }\n\n return (signer, RecoverError.NoError);\n }\n\n /**\n * @dev Overload of {ECDSA-recover} that receives the `v`,\n * `r` and `s` signature fields separately.\n */\n function recover(bytes32 hash, uint8 v, bytes32 r, bytes32 s) internal pure returns (address) {\n (address recovered, RecoverError error) = tryRecover(hash, v, r, s);\n _throwError(error);\n return recovered;\n }\n\n /**\n * @dev Returns an Ethereum Signed Message, created from a `hash`. This\n * produces hash corresponding to the one signed with the\n * https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`]\n * JSON-RPC method as part of EIP-191.\n *\n * See {recover}.\n */\n function toEthSignedMessageHash(bytes32 hash) internal pure returns (bytes32 message) {\n // 32 is the length in bytes of hash,\n // enforced by the type signature above\n /// @solidity memory-safe-assembly\n assembly {\n mstore(0x00, \"\\x19Ethereum Signed Message:\\n32\")\n mstore(0x1c, hash)\n message := keccak256(0x00, 0x3c)\n }\n }\n\n /**\n * @dev Returns an Ethereum Signed Message, created from `s`. This\n * produces hash corresponding to the one signed with the\n * https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`]\n * JSON-RPC method as part of EIP-191.\n *\n * See {recover}.\n */\n function toEthSignedMessageHash(bytes memory s) internal pure returns (bytes32) {\n return keccak256(abi.encodePacked(\"\\x19Ethereum Signed Message:\\n\", Strings.toString(s.length), s));\n }\n\n /**\n * @dev Returns an Ethereum Signed Typed Data, created from a\n * `domainSeparator` and a `structHash`. This produces hash corresponding\n * to the one signed with the\n * https://eips.ethereum.org/EIPS/eip-712[`eth_signTypedData`]\n * JSON-RPC method as part of EIP-712.\n *\n * See {recover}.\n */\n function toTypedDataHash(bytes32 domainSeparator, bytes32 structHash) internal pure returns (bytes32 data) {\n /// @solidity memory-safe-assembly\n assembly {\n let ptr := mload(0x40)\n mstore(ptr, \"\\x19\\x01\")\n mstore(add(ptr, 0x02), domainSeparator)\n mstore(add(ptr, 0x22), structHash)\n data := keccak256(ptr, 0x42)\n }\n }\n\n /**\n * @dev Returns an Ethereum Signed Data with intended validator, created from a\n * `validator` and `data` according to the version 0 of EIP-191.\n *\n * See {recover}.\n */\n function toDataWithIntendedValidatorHash(address validator, bytes memory data) internal pure returns (bytes32) {\n return keccak256(abi.encodePacked(\"\\x19\\x00\", validator, data));\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/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/inbox/StatementInbox.sol\n\n// ══════════════════════════════ LIBRARY IMPORTS ══════════════════════════════\n\n// ═════════════════════════════ INTERNAL IMPORTS ══════════════════════════════\n\n// ═════════════════════════════ EXTERNAL IMPORTS ══════════════════════════════\n\n/// @notice `StatementInbox` is the entry point for all agent-signed statements. It verifies the\n/// agent signatures, and passes the unsigned statements to the contract to consume it via `acceptX` functions. Is is\n/// also used to verify the agent-signed statements and initiate the agent slashing, should the statement be invalid.\n/// `StatementInbox` is responsible for the following:\n/// - Accepting State and Receipt Reports to initiate a dispute between Guard and Notary.\n/// - Storing all the Guard Reports with the Guard signature leading to a dispute.\n/// - Verifying State/State Reports referencing the local chain and slashing the signer if statement is invalid.\n/// - Verifying Receipt/Receipt Reports referencing the local chain and slashing the signer if statement is invalid.\nabstract contract StatementInbox is MessagingBase, StatementInboxEvents, IStatementInbox {\n using AttestationLib for bytes;\n using ReceiptLib for bytes;\n using StateLib for bytes;\n using SnapshotLib for bytes;\n\n struct StoredReport {\n uint256 sigIndex;\n bytes statementPayload;\n }\n\n // ══════════════════════════════════════════════════ STORAGE ══════════════════════════════════════════════════════\n\n address public agentManager;\n address public origin;\n address public destination;\n\n // TODO: optimize this\n bytes[] internal _storedSignatures;\n StoredReport[] internal _storedReports;\n\n /// @dev gap for upgrade safety\n uint256[45] private __GAP; // solhint-disable-line var-name-mixedcase\n\n // ════════════════════════════════════════════════ INITIALIZER ════════════════════════════════════════════════════\n\n /// @dev Initializes the contract:\n /// - Sets up `msg.sender` as the owner of the contract.\n /// - Sets up `agentManager`, `origin`, and `destination`.\n // solhint-disable-next-line func-name-mixedcase\n function __StatementInbox_init(address agentManager_, address origin_, address destination_)\n internal\n onlyInitializing\n {\n agentManager = agentManager_;\n origin = origin_;\n destination = destination_;\n __Ownable2Step_init();\n }\n\n // ══════════════════════════════════════════ SUBMIT AGENT STATEMENTS ══════════════════════════════════════════════\n\n /// @inheritdoc IStatementInbox\n // solhint-disable-next-line ordering\n function submitStateReportWithSnapshot(\n uint8 stateIndex,\n bytes memory srSignature,\n bytes memory snapPayload,\n bytes memory snapSignature\n ) external returns (bool wasAccepted) {\n // This will revert if payload is not a snapshot\n Snapshot snapshot = snapPayload.castToSnapshot();\n // This will revert if the snapshot signer is not a known Notary\n (AgentStatus memory notaryStatus,) =\n _verifySnapshot({snapshot: snapshot, snapSignature: snapSignature, verifyNotary: true});\n // Notary needs to be Active/Unstaking\n notaryStatus.verifyActiveUnstaking();\n // Check if Notary is active on this chain\n _verifyNotaryDomain(notaryStatus.domain);\n // This will revert if state index is out of range\n State state = snapshot.state(stateIndex);\n // This will revert if the report signer is not an known Guard\n (AgentStatus memory guardStatus,) = _verifyStateReport(state, srSignature);\n // Check that Guard is active\n guardStatus.verifyActive();\n _saveReport(state.unwrap().clone(), srSignature);\n // This will revert if either actor is already in dispute\n IAgentManager(agentManager).openDispute(guardStatus.index, notaryStatus.index);\n return true;\n }\n\n /// @inheritdoc IStatementInbox\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 // This will revert if payload is not a snapshot\n Snapshot snapshot = snapPayload.castToSnapshot();\n // This will revert if state index is out of range\n State state = snapshot.state(stateIndex);\n // This will revert if the report signer is not an known Guard\n (AgentStatus memory guardStatus,) = _verifyStateReport(state, srSignature);\n // Check that Guard is active\n guardStatus.verifyActive();\n // This will revert if payload is not an attestation\n Attestation att = attPayload.castToAttestation();\n // This will revert if signer is not an known Notary\n (AgentStatus memory notaryStatus,) = _verifyAttestation(att, attSignature);\n // Notary needs to be Active/Unstaking\n notaryStatus.verifyActiveUnstaking();\n // Check if Notary is active on this chain\n _verifyNotaryDomain(notaryStatus.domain);\n if (snapshot.calculateRoot() != att.snapRoot()) revert IncorrectSnapshotRoot();\n _saveReport(state.unwrap().clone(), srSignature);\n // This will revert if either actor is already in dispute\n IAgentManager(agentManager).openDispute(guardStatus.index, notaryStatus.index);\n return true;\n }\n\n /// @inheritdoc IStatementInbox\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 // This will revert if payload is not a state\n State state = statePayload.castToState();\n // This will revert if the report signer is not an known Guard\n (AgentStatus memory guardStatus,) = _verifyStateReport(state, srSignature);\n // Check that Guard is active\n guardStatus.verifyActive();\n // This will revert if payload is not an attestation\n Attestation att = attPayload.castToAttestation();\n // This will revert if signer is not a known Notary\n (AgentStatus memory notaryStatus,) = _verifyAttestation(att, attSignature);\n // Notary needs to be Active/Unstaking\n notaryStatus.verifyActiveUnstaking();\n // Check if Notary is active on this chain\n _verifyNotaryDomain(notaryStatus.domain);\n // This will revert if any of these is true:\n // - Attestation root is not equal to Merkle Root derived from State and Snapshot Proof.\n // - Snapshot Proof's first element does not match the State metadata.\n // - Snapshot Proof length exceeds Snapshot tree Height.\n // - State index is out of range.\n _verifySnapshotMerkle(att, stateIndex, state, snapProof);\n _saveReport(statePayload, srSignature);\n // This will revert if either actor is already in dispute\n IAgentManager(agentManager).openDispute(guardStatus.index, notaryStatus.index);\n return true;\n }\n\n // ══════════════════════════════════════════ VERIFY AGENT STATEMENTS ══════════════════════════════════════════════\n\n /// @inheritdoc IStatementInbox\n function verifyReceipt(bytes memory rcptPayload, bytes memory rcptSignature)\n external\n returns (bool isValidReceipt)\n {\n // This will revert if payload is not a receipt\n Receipt rcpt = rcptPayload.castToReceipt();\n // This will revert if the attestation signer is not a known Notary\n (AgentStatus memory status, address notary) = _verifyReceipt(rcpt, rcptSignature);\n // Notary needs to be Active/Unstaking\n status.verifyActiveUnstaking();\n isValidReceipt = IExecutionHub(destination).isValidReceipt(rcptPayload);\n if (!isValidReceipt) {\n emit InvalidReceipt(rcptPayload, rcptSignature);\n IAgentManager(agentManager).slashAgent(status.domain, notary, msg.sender);\n }\n }\n\n /// @inheritdoc IStatementInbox\n function verifyReceiptReport(bytes memory rcptPayload, bytes memory rrSignature)\n external\n returns (bool isValidReport)\n {\n // This will revert if payload is not a receipt\n Receipt rcpt = rcptPayload.castToReceipt();\n // This will revert if the report signer is not a known Guard\n (AgentStatus memory status, address guard) = _verifyReceiptReport(rcpt, rrSignature);\n // Guard needs to be Active/Unstaking\n status.verifyActiveUnstaking();\n // Report is valid IF AND ONLY IF the reported receipt in invalid\n isValidReport = !IExecutionHub(destination).isValidReceipt(rcptPayload);\n if (!isValidReport) {\n emit InvalidReceiptReport(rcptPayload, rrSignature);\n IAgentManager(agentManager).slashAgent(status.domain, guard, msg.sender);\n }\n }\n\n /// @inheritdoc IStatementInbox\n function verifyStateWithAttestation(\n uint8 stateIndex,\n bytes memory snapPayload,\n bytes memory attPayload,\n bytes memory attSignature\n ) external returns (bool isValidState) {\n // This will revert if payload is not an attestation\n Attestation att = attPayload.castToAttestation();\n // This will revert if the attestation signer is not a known Notary\n (AgentStatus memory status, address notary) = _verifyAttestation(att, attSignature);\n // Notary needs to be Active/Unstaking\n status.verifyActiveUnstaking();\n // This will revert if payload is not a snapshot\n Snapshot snapshot = snapPayload.castToSnapshot();\n if (snapshot.calculateRoot() != att.snapRoot()) revert IncorrectSnapshotRoot();\n // This will revert if state does not refer to this chain\n bytes memory statePayload = snapshot.state(stateIndex).unwrap().clone();\n isValidState = IStateHub(origin).isValidState(statePayload);\n if (!isValidState) {\n emit InvalidStateWithAttestation(stateIndex, statePayload, attPayload, attSignature);\n IAgentManager(agentManager).slashAgent(status.domain, notary, msg.sender);\n }\n }\n\n /// @inheritdoc IStatementInbox\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 // This will revert if payload is not an attestation\n Attestation att = attPayload.castToAttestation();\n // This will revert if the attestation signer is not a known Notary\n (AgentStatus memory status, address notary) = _verifyAttestation(att, attSignature);\n // Notary needs to be Active/Unstaking\n status.verifyActiveUnstaking();\n // This will revert if payload is not a state\n State state = statePayload.castToState();\n // This will revert if any of these is true:\n // - Attestation root is not equal to Merkle Root derived from State and Snapshot Proof.\n // - Snapshot Proof's first element does not match the State metadata.\n // - Snapshot Proof length exceeds Snapshot tree Height.\n // - State index is out of range.\n _verifySnapshotMerkle(att, stateIndex, state, snapProof);\n // This will revert if state does not refer to this chain\n isValidState = IStateHub(origin).isValidState(statePayload);\n if (!isValidState) {\n emit InvalidStateWithAttestation(stateIndex, statePayload, attPayload, attSignature);\n IAgentManager(agentManager).slashAgent(status.domain, notary, msg.sender);\n }\n }\n\n /// @inheritdoc IStatementInbox\n function verifyStateWithSnapshot(uint8 stateIndex, bytes memory snapPayload, bytes memory snapSignature)\n external\n returns (bool isValidState)\n {\n // This will revert if payload is not a snapshot\n Snapshot snapshot = snapPayload.castToSnapshot();\n // This will revert if the snapshot signer is not a known Guard/Notary\n (AgentStatus memory status, address agent) =\n _verifySnapshot({snapshot: snapshot, snapSignature: snapSignature, verifyNotary: false});\n // Agent needs to be Active/Unstaking\n status.verifyActiveUnstaking();\n // This will revert if state does not refer to this chain\n isValidState = IStateHub(origin).isValidState(snapshot.state(stateIndex).unwrap().clone());\n if (!isValidState) {\n emit InvalidStateWithSnapshot(stateIndex, snapPayload, snapSignature);\n IAgentManager(agentManager).slashAgent(status.domain, agent, msg.sender);\n }\n }\n\n /// @inheritdoc IStatementInbox\n function verifyStateReport(bytes memory statePayload, bytes memory srSignature)\n external\n returns (bool isValidReport)\n {\n // This will revert if payload is not a state\n State state = statePayload.castToState();\n // This will revert if the report signer is not a known Guard\n (AgentStatus memory status, address guard) = _verifyStateReport(state, srSignature);\n // Guard needs to be Active/Unstaking\n status.verifyActiveUnstaking();\n // Report is valid IF AND ONLY IF the reported state in invalid\n // This will revert if the reported state does not refer to this chain\n isValidReport = !IStateHub(origin).isValidState(statePayload);\n if (!isValidReport) {\n emit InvalidStateReport(statePayload, srSignature);\n IAgentManager(agentManager).slashAgent(status.domain, guard, msg.sender);\n }\n }\n\n // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════\n\n /// @inheritdoc IStatementInbox\n function getReportsAmount() external view returns (uint256) {\n return _storedReports.length;\n }\n\n /// @inheritdoc IStatementInbox\n function getGuardReport(uint256 index)\n external\n view\n returns (bytes memory statementPayload, bytes memory reportSignature)\n {\n if (index \u003e= _storedReports.length) revert IndexOutOfRange();\n StoredReport memory storedReport = _storedReports[index];\n statementPayload = storedReport.statementPayload;\n reportSignature = _storedSignatures[storedReport.sigIndex];\n }\n\n /// @inheritdoc IStatementInbox\n function getStoredSignature(uint256 index) external view returns (bytes memory) {\n return _storedSignatures[index];\n }\n\n // ══════════════════════════════════════════════ INTERNAL LOGIC ═══════════════════════════════════════════════════\n\n /// @dev Saves the statement reported by Guard as invalid and the Guard Report signature.\n function _saveReport(bytes memory statementPayload, bytes memory reportSignature) internal {\n uint256 sigIndex = _saveSignature(reportSignature);\n _storedReports.push(StoredReport(sigIndex, statementPayload));\n }\n\n /// @dev Saves the signature and returns its index.\n function _saveSignature(bytes memory signature) internal returns (uint256 sigIndex) {\n sigIndex = _storedSignatures.length;\n _storedSignatures.push(signature);\n }\n\n // ═══════════════════════════════════════════════ AGENT CHECKS ════════════════════════════════════════════════════\n\n /**\n * @dev Recovers a signer from a hashed message, and a EIP-191 signature for it.\n * Will revert, if the signer is not a known agent.\n * @dev Agent flag could be any of these: Active/Unstaking/Resting/Fraudulent/Slashed\n * Further checks need to be performed in a caller function.\n * @param hashedStatement Hash of the statement that was signed by an Agent\n * @param signature Agent signature for the hashed statement\n * @return status Struct representing agent status:\n * - flag Unknown/Active/Unstaking/Resting/Fraudulent/Slashed\n * - domain Domain where agent is/was active\n * - index Index of agent in the Agent Merkle Tree\n * @return agent Agent that signed the statement\n */\n function _recoverAgent(bytes32 hashedStatement, bytes memory signature)\n internal\n view\n returns (AgentStatus memory status, address agent)\n {\n bytes32 ethSignedMsg = ECDSA.toEthSignedMessageHash(hashedStatement);\n agent = ECDSA.recover(ethSignedMsg, signature);\n status = IAgentManager(agentManager).agentStatus(agent);\n // Discard signature of unknown agents.\n // Further flag checks are supposed to be performed in a caller function.\n status.verifyKnown();\n }\n\n /// @dev Verifies that Notary signature is active on local domain.\n function _verifyNotaryDomain(uint32 notaryDomain) internal view {\n // Notary needs to be from the local domain (if contract is not deployed on Synapse Chain).\n // Or Notary could be from any domain (if contract is deployed on Synapse Chain).\n if (notaryDomain != localDomain \u0026\u0026 localDomain != synapseDomain) revert IncorrectAgentDomain();\n }\n\n // ════════════════════════════════════════ ATTESTATION RELATED CHECKS ═════════════════════════════════════════════\n\n /**\n * @dev Internal function to verify the signed attestation payload.\n * Reverts if any of these is true:\n * - Attestation signer is not a known Notary.\n * @param att Typed memory view over attestation payload\n * @param attSignature Notary signature for the attestation\n * @return status Struct representing agent status, see {_recoverAgent}\n * @return notary Notary that signed the snapshot\n */\n function _verifyAttestation(Attestation att, bytes memory attSignature)\n internal\n view\n returns (AgentStatus memory status, address notary)\n {\n // This will revert if signer is not a known agent\n (status, notary) = _recoverAgent(att.hashValid(), attSignature);\n // Attestation signer needs to be a Notary, not a Guard\n if (status.domain == 0) revert AgentNotNotary();\n }\n\n /**\n * @dev Internal function to verify the signed attestation report payload.\n * Reverts if any of these is true:\n * - Report signer is not a known Guard.\n * @param att Typed memory view over attestation payload that Guard reports as invalid\n * @param arSignature Guard signature for the \"invalid attestation\" report\n * @return status Struct representing guard status, see {_recoverAgent}\n * @return guard Guard that signed the report\n */\n function _verifyAttestationReport(Attestation att, bytes memory arSignature)\n internal\n view\n returns (AgentStatus memory status, address guard)\n {\n // This will revert if signer is not a known agent\n (status, guard) = _recoverAgent(att.hashInvalid(), arSignature);\n // Report signer needs to be a Guard, not a Notary\n if (status.domain != 0) revert AgentNotGuard();\n }\n\n // ══════════════════════════════════════════ RECEIPT RELATED CHECKS ═══════════════════════════════════════════════\n\n /**\n * @dev Internal function to verify the signed receipt payload.\n * Reverts if any of these is true:\n * - Receipt signer is not a known Notary.\n * @param rcpt Typed memory view over receipt payload\n * @param rcptSignature Notary signature for the receipt\n * @return status Struct representing agent status, see {_recoverAgent}\n * @return notary Notary that signed the snapshot\n */\n function _verifyReceipt(Receipt rcpt, bytes memory rcptSignature)\n internal\n view\n returns (AgentStatus memory status, address notary)\n {\n // This will revert if signer is not a known agent\n (status, notary) = _recoverAgent(rcpt.hashValid(), rcptSignature);\n // Receipt signer needs to be a Notary, not a Guard\n if (status.domain == 0) revert AgentNotNotary();\n }\n\n /**\n * @dev Internal function to verify the signed receipt report payload.\n * Reverts if any of these is true:\n * - Report signer is not a known Guard.\n * @param rcpt Typed memory view over receipt payload that Guard reports as invalid\n * @param rrSignature Guard signature for the \"invalid receipt\" report\n * @return status Struct representing guard status, see {_recoverAgent}\n * @return guard Guard that signed the report\n */\n function _verifyReceiptReport(Receipt rcpt, bytes memory rrSignature)\n internal\n view\n returns (AgentStatus memory status, address guard)\n {\n // This will revert if signer is not a known agent\n (status, guard) = _recoverAgent(rcpt.hashInvalid(), rrSignature);\n // Report signer needs to be a Guard, not a Notary\n if (status.domain != 0) revert AgentNotGuard();\n }\n\n // ═══════════════════════════════════════ STATE/SNAPSHOT RELATED CHECKS ═══════════════════════════════════════════\n\n /**\n * @dev Internal function to verify the signed snapshot report payload.\n * Reverts if any of these is true:\n * - Report signer is not a known Guard.\n * @param state Typed memory view over state payload that Guard reports as invalid\n * @param srSignature Guard signature for the report\n * @return status Struct representing guard status, see {_recoverAgent}\n * @return guard Guard that signed the report\n */\n function _verifyStateReport(State state, bytes memory srSignature)\n internal\n view\n returns (AgentStatus memory status, address guard)\n {\n // This will revert if signer is not a known agent\n (status, guard) = _recoverAgent(state.hashInvalid(), srSignature);\n // Report signer needs to be a Guard, not a Notary\n if (status.domain != 0) revert AgentNotGuard();\n }\n\n /**\n * @dev Internal function to verify the signed snapshot payload.\n * Reverts if any of these is true:\n * - Snapshot signer is not a known Agent.\n * - Snapshot signer is not a Notary (if verifyNotary is true).\n * @param snapshot Typed memory view over snapshot payload\n * @param snapSignature Agent signature for the snapshot\n * @param verifyNotary If true, snapshot signer needs to be a Notary, not a Guard\n * @return status Struct representing agent status, see {_recoverAgent}\n * @return agent Agent that signed the snapshot\n */\n function _verifySnapshot(Snapshot snapshot, bytes memory snapSignature, bool verifyNotary)\n internal\n view\n returns (AgentStatus memory status, address agent)\n {\n // This will revert if signer is not a known agent\n (status, agent) = _recoverAgent(snapshot.hashValid(), snapSignature);\n // If requested, snapshot signer needs to be a Notary, not a Guard\n if (verifyNotary \u0026\u0026 status.domain == 0) revert AgentNotNotary();\n }\n\n // ═══════════════════════════════════════════ MERKLE RELATED CHECKS ═══════════════════════════════════════════════\n\n /**\n * @dev Internal function to verify that snapshot roots match.\n * Reverts if any of these is true:\n * - Attestation root is not equal to Merkle Root derived from State and Snapshot Proof.\n * - Snapshot Proof's first element does not match the State metadata.\n * - Snapshot Proof length exceeds Snapshot tree Height.\n * - State index is out of range.\n * @param att Typed memory view over Attestation\n * @param stateIndex Index of state in the snapshot\n * @param state Typed memory view over the provided state payload\n * @param snapProof Raw payload with snapshot data\n */\n function _verifySnapshotMerkle(Attestation att, uint8 stateIndex, State state, bytes32[] memory snapProof)\n internal\n pure\n {\n // Snapshot proof first element should match State metadata (aka \"right sub-leaf\")\n (, bytes32 rightSubLeaf) = state.subLeafs();\n if (snapProof[0] != rightSubLeaf) revert IncorrectSnapshotProof();\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(state.root(), state.origin(), snapProof, stateIndex);\n // Snapshot root should match the attestation root\n if (att.snapRoot() != snapshotRoot) revert IncorrectSnapshotRoot();\n }\n}\n\n// contracts/inbox/Inbox.sol\n\n// ══════════════════════════════ LIBRARY IMPORTS ══════════════════════════════\n\n// ═════════════════════════════ INTERNAL IMPORTS ══════════════════════════════\n\n/// @notice `Inbox` is the child of `StatementInbox` contract, that is used on Synapse Chain.\n/// In addition to the functionality of `StatementInbox`, it also:\n/// - Accepts Guard and Notary Snapshots and passes them to `Summit` contract.\n/// - Accepts Notary-signed Receipts and passes them to `Summit` contract.\n/// - Accepts Receipt Reports to initiate a dispute between Guard and Notary.\n/// - Verifies Attestations and Attestation Reports, and slashes the signer if they are invalid.\ncontract Inbox is StatementInbox, InboxEvents, InterfaceInbox {\n using AttestationLib for bytes;\n using ReceiptLib for bytes;\n using SnapshotLib for bytes;\n\n // Struct to get around stack too deep error. TODO: revisit this\n struct ReceiptInfo {\n AgentStatus rcptNotaryStatus;\n address notary;\n uint32 attNonce;\n AgentStatus attNotaryStatus;\n }\n\n // ══════════════════════════════════════════════════ STORAGE ══════════════════════════════════════════════════════\n\n // The address of the Summit contract.\n address public summit;\n\n // ═════════════════════════════════════════ CONSTRUCTOR \u0026 INITIALIZER ═════════════════════════════════════════════\n\n constructor(uint32 synapseDomain_) MessagingBase(\"0.0.3\", synapseDomain_) {\n if (localDomain != synapseDomain) revert MustBeSynapseDomain();\n }\n\n /// @notice Initializes `Inbox` contract:\n /// - Sets `msg.sender` as the owner of the contract\n /// - Sets `agentManager`, `origin`, `destination` and `summit` addresses\n function initialize(address agentManager_, address origin_, address destination_, address summit_)\n external\n initializer\n {\n __StatementInbox_init(agentManager_, origin_, destination_);\n summit = summit_;\n }\n\n // ══════════════════════════════════════════ SUBMIT AGENT STATEMENTS ══════════════════════════════════════════════\n\n /// @inheritdoc InterfaceInbox\n function submitSnapshot(bytes memory snapPayload, bytes memory snapSignature)\n external\n returns (bytes memory attPayload, bytes32 agentRoot_, uint256[] memory snapGas)\n {\n // This will revert if payload is not a snapshot\n Snapshot snapshot = snapPayload.castToSnapshot();\n // This will revert if the signer is not a known Guard/Notary\n (AgentStatus memory status, address agent) =\n _verifySnapshot({snapshot: snapshot, snapSignature: snapSignature, verifyNotary: false});\n // Check that Agent is active\n status.verifyActive();\n // Store Agent signature for the Snapshot\n uint256 sigIndex = _saveSignature(snapSignature);\n if (status.domain == 0) {\n // Guard that is in Dispute could still submit new snapshots, so we don't check that\n InterfaceSummit(summit).acceptGuardSnapshot({\n guardIndex: status.index,\n sigIndex: sigIndex,\n snapPayload: snapPayload\n });\n } else {\n // Get current agentRoot from AgentManager\n agentRoot_ = IAgentManager(agentManager).agentRoot();\n // This will revert if Notary is in Dispute\n attPayload = InterfaceSummit(summit).acceptNotarySnapshot({\n notaryIndex: status.index,\n sigIndex: sigIndex,\n agentRoot: agentRoot_,\n snapPayload: snapPayload\n });\n ChainGas[] memory snapGas_ = snapshot.snapGas();\n // Pass created attestation to Destination to enable executing messages coming to Synapse Chain\n InterfaceDestination(destination).acceptAttestation(\n status.index, type(uint256).max, attPayload, agentRoot_, snapGas_\n );\n // Use assembly to cast ChainGas[] to uint256[] without copying. Highest bits are left zeroed.\n // solhint-disable-next-line no-inline-assembly\n assembly {\n snapGas := snapGas_\n }\n }\n emit SnapshotAccepted(status.domain, agent, snapPayload, snapSignature);\n }\n\n /// @inheritdoc InterfaceInbox\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 // Struct to get around stack too deep error.\n ReceiptInfo memory info;\n // This will revert if payload is not a receipt\n Receipt rcpt = rcptPayload.castToReceipt();\n // This will revert if the receipt signer is not a known Notary\n (info.rcptNotaryStatus, info.notary) = _verifyReceipt(rcpt, rcptSignature);\n // Receipt Notary needs to be Active\n info.rcptNotaryStatus.verifyActive();\n info.attNonce = IExecutionHub(destination).getAttestationNonce(rcpt.snapshotRoot());\n if (info.attNonce == 0) revert IncorrectSnapshotRoot();\n // Attestation Notary domain needs to match the destination domain\n info.attNotaryStatus = IAgentManager(agentManager).agentStatus(rcpt.attNotary());\n if (info.attNotaryStatus.domain != rcpt.destination()) revert IncorrectAgentDomain();\n // Check that the correct tip values for the message were provided\n _verifyReceiptTips(rcpt.messageHash(), paddedTips, headerHash, bodyHash);\n // Store Notary signature for the Receipt\n uint256 sigIndex = _saveSignature(rcptSignature);\n // This will revert if Receipt Notary is in Dispute\n wasAccepted = InterfaceSummit(summit).acceptReceipt({\n rcptNotaryIndex: info.rcptNotaryStatus.index,\n attNotaryIndex: info.attNotaryStatus.index,\n sigIndex: sigIndex,\n attNonce: info.attNonce,\n paddedTips: paddedTips,\n rcptPayload: rcptPayload\n });\n if (wasAccepted) {\n emit ReceiptAccepted(info.rcptNotaryStatus.domain, info.notary, rcptPayload, rcptSignature);\n }\n }\n\n /// @inheritdoc InterfaceInbox\n function submitReceiptReport(bytes memory rcptPayload, bytes memory rcptSignature, bytes memory rrSignature)\n external\n returns (bool wasAccepted)\n {\n // This will revert if payload is not a receipt\n Receipt rcpt = rcptPayload.castToReceipt();\n // This will revert if the receipt signer is not a known Guard\n (AgentStatus memory guardStatus,) = _verifyReceiptReport(rcpt, rrSignature);\n // Guard needs to be Active\n guardStatus.verifyActive();\n // This will revert if report signer is not a known Notary\n (AgentStatus memory notaryStatus,) = _verifyReceipt(rcpt, rcptSignature);\n // Notary needs to be Active/Unstaking\n notaryStatus.verifyActiveUnstaking();\n _saveReport(rcptPayload, rrSignature);\n // This will revert if either actor is already in dispute\n IAgentManager(agentManager).openDispute(guardStatus.index, notaryStatus.index);\n return true;\n }\n\n /// @inheritdoc InterfaceInbox\n function passReceipt(uint32 attNotaryIndex, uint32 attNonce, uint256 paddedTips, bytes memory rcptPayload)\n external\n returns (bool wasAccepted)\n {\n // Only Destination can pass receipts\n if (msg.sender != destination) revert CallerNotDestination();\n return InterfaceSummit(summit).acceptReceipt({\n rcptNotaryIndex: attNotaryIndex,\n attNotaryIndex: attNotaryIndex,\n sigIndex: type(uint256).max,\n attNonce: attNonce,\n paddedTips: paddedTips,\n rcptPayload: rcptPayload\n });\n }\n\n // ══════════════════════════════════════════ VERIFY AGENT STATEMENTS ══════════════════════════════════════════════\n\n /// @inheritdoc InterfaceInbox\n function verifyAttestation(bytes memory attPayload, bytes memory attSignature)\n external\n returns (bool isValidAttestation)\n {\n // This will revert if payload is not an attestation\n Attestation att = attPayload.castToAttestation();\n // This will revert if the attestation signer is not a known Notary\n (AgentStatus memory status, address notary) = _verifyAttestation(att, attSignature);\n // Notary needs to be Active/Unstaking\n status.verifyActiveUnstaking();\n isValidAttestation = ISnapshotHub(summit).isValidAttestation(attPayload);\n if (!isValidAttestation) {\n emit InvalidAttestation(attPayload, attSignature);\n IAgentManager(agentManager).slashAgent(status.domain, notary, msg.sender);\n }\n }\n\n /// @inheritdoc InterfaceInbox\n function verifyAttestationReport(bytes memory attPayload, bytes memory arSignature)\n external\n returns (bool isValidReport)\n {\n // This will revert if payload is not an attestation\n Attestation att = attPayload.castToAttestation();\n // This will revert if the report signer is not a known Guard\n (AgentStatus memory status, address guard) = _verifyAttestationReport(att, arSignature);\n // Guard needs to be Active/Unstaking\n status.verifyActiveUnstaking();\n // Report is valid IF AND ONLY IF the reported attestation in invalid\n isValidReport = !ISnapshotHub(summit).isValidAttestation(attPayload);\n if (!isValidReport) {\n emit InvalidAttestationReport(attPayload, arSignature);\n IAgentManager(agentManager).slashAgent(status.domain, guard, msg.sender);\n }\n }\n\n // ══════════════════════════════════════════════ INTERNAL VIEWS ═══════════════════════════════════════════════════\n\n /// @dev Verifies that tips proof matches the message hash.\n function _verifyReceiptTips(bytes32 msgHash, uint256 paddedTips, bytes32 headerHash, bytes32 bodyHash)\n internal\n pure\n {\n Tips tips = TipsLib.wrapPadded(paddedTips);\n // full message leaf is (header, baseMessage), while base message leaf is (tips, remainingBody).\n if (MerkleMath.getParent(headerHash, MerkleMath.getParent(tips.leaf(), bodyHash)) != msgHash) {\n revert IncorrectTipsProof();\n }\n }\n}\n","language":"Solidity","languageVersion":"0.8.17","compilerVersion":"0.8.17","compilerOptions":"--combined-json bin,bin-runtime,srcmap,srcmap-runtime,abi,userdoc,devdoc,metadata,hashes --optimize --optimize-runs 10000 --allow-paths ., ./, ../","srcMap":"196448:6371:0:-:0;;;;;;;;;;;;;;;-1:-1:-1;;;196448:6371:0;;;;;;;;;;;;;;;;;","srcMapRuntime":"196448: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/Inbox.sol\":\"ReceiptLib\"},\"evmVersion\":\"london\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\"},\"optimizer\":{\"enabled\":true,\"runs\":10000},\"remappings\":[]},\"sources\":{\"solidity/Inbox.sol\":{\"keccak256\":\"0x9b516081a036814c0169e20e484d4a5499066b7a6f48fada952b5e844a1ca3e5\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://32bde393b3f24ef4307d9626d4143f337b3c0bd34e17bb969fd5a15221d96987\",\"dweb:/ipfs/QmTkt2XZRtgsbSpmsVQUM3c4ebETQoDVYbmEV9yheBghnr\"]}},\"version\":1}"},"hashes":{}},"solidity/Inbox.sol:SafeCast":{"code":"0x60566037600b82828239805160001a607314602a57634e487b7160e01b600052600060045260246000fd5b30600052607381538281f3fe73000000000000000000000000000000000000000030146080604052600080fdfea264697066735822122001149e8f865fc487cd605960f1473f6160490a135eed622ba53dc48ad449e41364736f6c63430008110033","runtime-code":"0x73000000000000000000000000000000000000000030146080604052600080fdfea264697066735822122001149e8f865fc487cd605960f1473f6160490a135eed622ba53dc48ad449e41364736f6c63430008110033","info":{"source":"// SPDX-License-Identifier: MIT\npragma solidity =0.8.17 ^0.8.0 ^0.8.1 ^0.8.2;\n\n// contracts/events/InboxEvents.sol\n\nabstract contract InboxEvents {\n /**\n * @notice Emitted when a snapshot is accepted by the Summit contract.\n * @param domain Domain where the signed Agent is active (ZERO for Guards)\n * @param agent Agent who signed the snapshot\n * @param snapPayload Raw payload with snapshot data\n * @param snapSignature Agent signature for the snapshot\n */\n event SnapshotAccepted(uint32 indexed domain, address indexed agent, bytes snapPayload, bytes snapSignature);\n\n /**\n * @notice Emitted when a snapshot is accepted by the Summit contract.\n * @param domain Domain where the signed Notary is active\n * @param notary Notary who signed the attestation\n * @param rcptPayload Raw payload with receipt data\n * @param rcptSignature Notary signature for the receipt\n */\n event ReceiptAccepted(uint32 domain, address notary, bytes rcptPayload, bytes rcptSignature);\n\n /**\n * @notice Emitted when a proof of invalid attestation is submitted.\n * @param attPayload Raw payload with Attestation data\n * @param attSignature Notary signature for the attestation\n */\n event InvalidAttestation(bytes attPayload, bytes attSignature);\n\n /**\n * @notice Emitted when a proof of invalid attestation report is submitted.\n * @param arPayload Raw payload with report data\n * @param arSignature Guard signature for the report\n */\n event InvalidAttestationReport(bytes arPayload, bytes arSignature);\n}\n\n// contracts/events/StatementInboxEvents.sol\n\nabstract contract StatementInboxEvents {\n // ════════════════════════════════════════════ STATEMENT ACCEPTED ═════════════════════════════════════════════════\n\n /**\n * @notice Emitted when a snapshot is accepted by the Destination contract.\n * @param domain Domain where the signed Notary is active\n * @param notary Notary who signed the attestation\n * @param attPayload Raw payload with attestation data\n * @param attSignature Notary signature for the attestation\n */\n event AttestationAccepted(uint32 domain, address notary, bytes attPayload, bytes attSignature);\n\n // ═════════════════════════════════════════ INVALID STATEMENT PROVED ══════════════════════════════════════════════\n\n /**\n * @notice Emitted when a proof of invalid receipt statement is submitted.\n * @param rcptPayload Raw payload with the receipt statement\n * @param rcptSignature Notary signature for the receipt statement\n */\n event InvalidReceipt(bytes rcptPayload, bytes rcptSignature);\n\n /**\n * @notice Emitted when a proof of invalid receipt report is submitted.\n * @param rrPayload Raw payload with report data\n * @param rrSignature Guard signature for the report\n */\n event InvalidReceiptReport(bytes rrPayload, bytes rrSignature);\n\n /**\n * @notice Emitted when a proof of invalid state in the signed attestation is submitted.\n * @param stateIndex Index of invalid state in the snapshot\n * @param statePayload Raw payload with state data\n * @param attPayload Raw payload with Attestation data for snapshot\n * @param attSignature Notary signature for the attestation\n */\n event InvalidStateWithAttestation(uint8 stateIndex, bytes statePayload, bytes attPayload, bytes attSignature);\n\n /**\n * @notice Emitted when a proof of invalid state in the signed snapshot is submitted.\n * @param stateIndex Index of invalid state in the snapshot\n * @param snapPayload Raw payload with snapshot data\n * @param snapSignature Agent signature for the snapshot\n */\n event InvalidStateWithSnapshot(uint8 stateIndex, bytes snapPayload, bytes snapSignature);\n\n /**\n * @notice Emitted when a proof of invalid state report is submitted.\n * @param srPayload Raw payload with report data\n * @param srSignature Guard signature for the report\n */\n event InvalidStateReport(bytes srPayload, bytes srSignature);\n}\n\n// contracts/interfaces/ISnapshotHub.sol\n\ninterface ISnapshotHub {\n /**\n * @notice Check that a given attestation is valid: matches the historical attestation\n * derived from an accepted Notary snapshot.\n * @dev Will revert if any of these is true:\n * - Attestation payload is not properly formatted.\n * @param attPayload Raw payload with attestation data\n * @return isValid Whether the provided attestation is valid\n */\n function isValidAttestation(bytes memory attPayload) external view returns (bool isValid);\n\n /**\n * @notice Returns saved attestation with the given nonce.\n * @dev Reverts if attestation with given nonce hasn't been created yet.\n * @param attNonce Nonce for the attestation\n * @return attPayload Raw payload with formatted Attestation data\n * @return agentRoot Agent root hash used for the attestation\n * @return snapGas Snapshot gas data used for the attestation\n */\n function getAttestation(uint32 attNonce)\n external\n view\n returns (bytes memory attPayload, bytes32 agentRoot, uint256[] memory snapGas);\n\n /**\n * @notice Returns the state with the highest known nonce submitted by a given Agent.\n * @param origin Domain of origin chain\n * @param agent Agent address\n * @return statePayload Raw payload with agent's latest state for origin\n */\n function getLatestAgentState(uint32 origin, address agent) external view returns (bytes memory statePayload);\n\n /**\n * @notice Returns latest saved attestation for a Notary.\n * @param notary Notary address\n * @return attPayload Raw payload with formatted Attestation data\n * @return agentRoot Agent root hash used for the attestation\n * @return snapGas Snapshot gas data used for the attestation\n */\n function getLatestNotaryAttestation(address notary)\n external\n view\n returns (bytes memory attPayload, bytes32 agentRoot, uint256[] memory snapGas);\n\n /**\n * @notice Returns Guard snapshot from the list of all accepted Guard snapshots.\n * @dev Reverts if snapshot with given index hasn't been accepted yet.\n * @param index Snapshot index in the list of all Guard snapshots\n * @return snapPayload Raw payload with Guard snapshot\n * @return snapSignature Raw payload with Guard signature for snapshot\n */\n function getGuardSnapshot(uint256 index)\n external\n view\n returns (bytes memory snapPayload, bytes memory snapSignature);\n\n /**\n * @notice Returns Notary snapshot from the list of all accepted Guard snapshots.\n * @dev Reverts if snapshot with given index hasn't been accepted yet.\n * @param index Snapshot index in the list of all Notary snapshots\n * @return snapPayload Raw payload with Notary snapshot\n * @return snapSignature Raw payload with Notary signature for snapshot\n */\n function getNotarySnapshot(uint256 index)\n external\n view\n returns (bytes memory snapPayload, bytes memory snapSignature);\n\n /**\n * @notice Returns Notary snapshot that was used for creating a given attestation.\n * @dev Reverts if any of these is true:\n * - Attestation payload is not properly formatted.\n * - Attestation is invalid (doesn't have a matching Notary snapshot).\n * @param attPayload Raw payload with attestation data\n * @return snapPayload Raw payload with Notary snapshot\n * @return snapSignature Raw payload with Notary signature for snapshot\n */\n function getNotarySnapshot(bytes memory attPayload)\n external\n view\n returns (bytes memory snapPayload, bytes memory snapSignature);\n\n /**\n * @notice Returns proof of inclusion of (root, origin) fields of a given snapshot's state\n * into the Snapshot Merkle Tree for a given attestation.\n * @dev Reverts if any of these is true:\n * - Attestation with given nonce hasn't been created yet.\n * - State index is out of range of snapshot list.\n * @param attNonce Nonce for the attestation\n * @param stateIndex Index of state in the attestation's snapshot\n * @return snapProof The snapshot proof\n */\n function getSnapshotProof(uint32 attNonce, uint8 stateIndex) external view returns (bytes32[] memory snapProof);\n}\n\n// contracts/interfaces/IStateHub.sol\n\ninterface IStateHub {\n /**\n * @notice Check that a given state is valid: matches the historical state of Origin contract.\n * Note: any Agent including an invalid state in their snapshot will be slashed\n * upon providing the snapshot and agent signature for it to Origin contract.\n * @dev Will revert if any of these is true:\n * - State payload is not properly formatted.\n * @param statePayload Raw payload with state data\n * @return isValid Whether the provided state is valid\n */\n function isValidState(bytes memory statePayload) external view returns (bool isValid);\n\n /**\n * @notice Returns the amount of saved states so far.\n * @dev This includes the initial state of \"empty Origin Merkle Tree\".\n */\n function statesAmount() external view returns (uint256);\n\n /**\n * @notice Suggest the data (state after latest sent message) to sign for an Agent.\n * Note: signing the suggested state data will will never lead to slashing of the actor,\n * assuming they have confirmed that the block, which number is included in the data,\n * is not subject to reorganization (which is different for every observed chain).\n * @return statePayload Raw payload with the latest state data\n */\n function suggestLatestState() external view returns (bytes memory statePayload);\n\n /**\n * @notice Given the historical nonce, suggest the state data to sign for an Agent.\n * Note: signing the suggested state data will will never lead to slashing of the actor,\n * assuming they have confirmed that the block, which number is included in the data,\n * is not subject to reorganization (which is different for every observed chain).\n * @param nonce Historical nonce to form a state\n * @return statePayload Raw payload with historical state data\n */\n function suggestState(uint32 nonce) external view returns (bytes memory statePayload);\n}\n\n// contracts/interfaces/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/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// node_modules/@openzeppelin/contracts/utils/math/Math.sol\n\n// OpenZeppelin Contracts (last updated v4.9.0) (utils/math/Math.sol)\n\n/**\n * @dev Standard math utilities missing in the Solidity language.\n */\nlibrary Math {\n enum Rounding {\n Down, // Toward negative infinity\n Up, // Toward infinity\n Zero // Toward zero\n }\n\n /**\n * @dev Returns the largest of two numbers.\n */\n function max(uint256 a, uint256 b) internal pure returns (uint256) {\n return a \u003e b ? a : b;\n }\n\n /**\n * @dev Returns the smallest of two numbers.\n */\n function min(uint256 a, uint256 b) internal pure returns (uint256) {\n return a \u003c b ? a : b;\n }\n\n /**\n * @dev Returns the average of two numbers. The result is rounded towards\n * zero.\n */\n function average(uint256 a, uint256 b) internal pure returns (uint256) {\n // (a + b) / 2 can overflow.\n return (a \u0026 b) + (a ^ b) / 2;\n }\n\n /**\n * @dev Returns the ceiling of the division of two numbers.\n *\n * This differs from standard division with `/` in that it rounds up instead\n * of rounding down.\n */\n function ceilDiv(uint256 a, uint256 b) internal pure returns (uint256) {\n // (a + b - 1) / b can overflow on addition, so we distribute.\n return a == 0 ? 0 : (a - 1) / b + 1;\n }\n\n /**\n * @notice Calculates floor(x * y / denominator) with full precision. Throws if result overflows a uint256 or denominator == 0\n * @dev Original credit to Remco Bloemen under MIT license (https://xn--2-umb.com/21/muldiv)\n * with further edits by Uniswap Labs also under MIT license.\n */\n function mulDiv(uint256 x, uint256 y, uint256 denominator) internal pure returns (uint256 result) {\n unchecked {\n // 512-bit multiply [prod1 prod0] = x * y. Compute the product mod 2^256 and mod 2^256 - 1, then use\n // use the Chinese Remainder Theorem to reconstruct the 512 bit result. The result is stored in two 256\n // variables such that product = prod1 * 2^256 + prod0.\n uint256 prod0; // Least significant 256 bits of the product\n uint256 prod1; // Most significant 256 bits of the product\n assembly {\n let mm := mulmod(x, y, not(0))\n prod0 := mul(x, y)\n prod1 := sub(sub(mm, prod0), lt(mm, prod0))\n }\n\n // Handle non-overflow cases, 256 by 256 division.\n if (prod1 == 0) {\n // Solidity will revert if denominator == 0, unlike the div opcode on its own.\n // The surrounding unchecked block does not change this fact.\n // See https://docs.soliditylang.org/en/latest/control-structures.html#checked-or-unchecked-arithmetic.\n return prod0 / denominator;\n }\n\n // Make sure the result is less than 2^256. Also prevents denominator == 0.\n require(denominator \u003e prod1, \"Math: mulDiv overflow\");\n\n ///////////////////////////////////////////////\n // 512 by 256 division.\n ///////////////////////////////////////////////\n\n // Make division exact by subtracting the remainder from [prod1 prod0].\n uint256 remainder;\n assembly {\n // Compute remainder using mulmod.\n remainder := mulmod(x, y, denominator)\n\n // Subtract 256 bit number from 512 bit number.\n prod1 := sub(prod1, gt(remainder, prod0))\n prod0 := sub(prod0, remainder)\n }\n\n // Factor powers of two out of denominator and compute largest power of two divisor of denominator. Always \u003e= 1.\n // See https://cs.stackexchange.com/q/138556/92363.\n\n // Does not overflow because the denominator cannot be zero at this stage in the function.\n uint256 twos = denominator \u0026 (~denominator + 1);\n assembly {\n // Divide denominator by twos.\n denominator := div(denominator, twos)\n\n // Divide [prod1 prod0] by twos.\n prod0 := div(prod0, twos)\n\n // Flip twos such that it is 2^256 / twos. If twos is zero, then it becomes one.\n twos := add(div(sub(0, twos), twos), 1)\n }\n\n // Shift in bits from prod1 into prod0.\n prod0 |= prod1 * twos;\n\n // Invert denominator mod 2^256. Now that denominator is an odd number, it has an inverse modulo 2^256 such\n // that denominator * inv = 1 mod 2^256. Compute the inverse by starting with a seed that is correct for\n // four bits. That is, denominator * inv = 1 mod 2^4.\n uint256 inverse = (3 * denominator) ^ 2;\n\n // Use the Newton-Raphson iteration to improve the precision. Thanks to Hensel's lifting lemma, this also works\n // in modular arithmetic, doubling the correct bits in each step.\n inverse *= 2 - denominator * inverse; // inverse mod 2^8\n inverse *= 2 - denominator * inverse; // inverse mod 2^16\n inverse *= 2 - denominator * inverse; // inverse mod 2^32\n inverse *= 2 - denominator * inverse; // inverse mod 2^64\n inverse *= 2 - denominator * inverse; // inverse mod 2^128\n inverse *= 2 - denominator * inverse; // inverse mod 2^256\n\n // Because the division is now exact we can divide by multiplying with the modular inverse of denominator.\n // This will give us the correct result modulo 2^256. Since the preconditions guarantee that the outcome is\n // less than 2^256, this is the final result. We don't need to compute the high bits of the result and prod1\n // is no longer required.\n result = prod0 * inverse;\n return result;\n }\n }\n\n /**\n * @notice Calculates x * y / denominator with full precision, following the selected rounding direction.\n */\n function mulDiv(uint256 x, uint256 y, uint256 denominator, Rounding rounding) internal pure returns (uint256) {\n uint256 result = mulDiv(x, y, denominator);\n if (rounding == Rounding.Up \u0026\u0026 mulmod(x, y, denominator) \u003e 0) {\n result += 1;\n }\n return result;\n }\n\n /**\n * @dev Returns the square root of a number. If the number is not a perfect square, the value is rounded down.\n *\n * Inspired by Henry S. Warren, Jr.'s \"Hacker's Delight\" (Chapter 11).\n */\n function sqrt(uint256 a) internal pure returns (uint256) {\n if (a == 0) {\n return 0;\n }\n\n // For our first guess, we get the biggest power of 2 which is smaller than the square root of the target.\n //\n // We know that the \"msb\" (most significant bit) of our target number `a` is a power of 2 such that we have\n // `msb(a) \u003c= a \u003c 2*msb(a)`. This value can be written `msb(a)=2**k` with `k=log2(a)`.\n //\n // This can be rewritten `2**log2(a) \u003c= a \u003c 2**(log2(a) + 1)`\n // → `sqrt(2**k) \u003c= sqrt(a) \u003c sqrt(2**(k+1))`\n // → `2**(k/2) \u003c= sqrt(a) \u003c 2**((k+1)/2) \u003c= 2**(k/2 + 1)`\n //\n // Consequently, `2**(log2(a) / 2)` is a good first approximation of `sqrt(a)` with at least 1 correct bit.\n uint256 result = 1 \u003c\u003c (log2(a) \u003e\u003e 1);\n\n // At this point `result` is an estimation with one bit of precision. We know the true value is a uint128,\n // since it is the square root of a uint256. Newton's method converges quadratically (precision doubles at\n // every iteration). We thus need at most 7 iteration to turn our partial result with one bit of precision\n // into the expected uint128 result.\n unchecked {\n result = (result + a / result) \u003e\u003e 1;\n result = (result + a / result) \u003e\u003e 1;\n result = (result + a / result) \u003e\u003e 1;\n result = (result + a / result) \u003e\u003e 1;\n result = (result + a / result) \u003e\u003e 1;\n result = (result + a / result) \u003e\u003e 1;\n result = (result + a / result) \u003e\u003e 1;\n return min(result, a / result);\n }\n }\n\n /**\n * @notice Calculates sqrt(a), following the selected rounding direction.\n */\n function sqrt(uint256 a, Rounding rounding) internal pure returns (uint256) {\n unchecked {\n uint256 result = sqrt(a);\n return result + (rounding == Rounding.Up \u0026\u0026 result * result \u003c a ? 1 : 0);\n }\n }\n\n /**\n * @dev Return the log in base 2, rounded down, of a positive value.\n * Returns 0 if given 0.\n */\n function log2(uint256 value) internal pure returns (uint256) {\n uint256 result = 0;\n unchecked {\n if (value \u003e\u003e 128 \u003e 0) {\n value \u003e\u003e= 128;\n result += 128;\n }\n if (value \u003e\u003e 64 \u003e 0) {\n value \u003e\u003e= 64;\n result += 64;\n }\n if (value \u003e\u003e 32 \u003e 0) {\n value \u003e\u003e= 32;\n result += 32;\n }\n if (value \u003e\u003e 16 \u003e 0) {\n value \u003e\u003e= 16;\n result += 16;\n }\n if (value \u003e\u003e 8 \u003e 0) {\n value \u003e\u003e= 8;\n result += 8;\n }\n if (value \u003e\u003e 4 \u003e 0) {\n value \u003e\u003e= 4;\n result += 4;\n }\n if (value \u003e\u003e 2 \u003e 0) {\n value \u003e\u003e= 2;\n result += 2;\n }\n if (value \u003e\u003e 1 \u003e 0) {\n result += 1;\n }\n }\n return result;\n }\n\n /**\n * @dev Return the log in base 2, following the selected rounding direction, of a positive value.\n * Returns 0 if given 0.\n */\n function log2(uint256 value, Rounding rounding) internal pure returns (uint256) {\n unchecked {\n uint256 result = log2(value);\n return result + (rounding == Rounding.Up \u0026\u0026 1 \u003c\u003c result \u003c value ? 1 : 0);\n }\n }\n\n /**\n * @dev Return the log in base 10, rounded down, of a positive value.\n * Returns 0 if given 0.\n */\n function log10(uint256 value) internal pure returns (uint256) {\n uint256 result = 0;\n unchecked {\n if (value \u003e= 10 ** 64) {\n value /= 10 ** 64;\n result += 64;\n }\n if (value \u003e= 10 ** 32) {\n value /= 10 ** 32;\n result += 32;\n }\n if (value \u003e= 10 ** 16) {\n value /= 10 ** 16;\n result += 16;\n }\n if (value \u003e= 10 ** 8) {\n value /= 10 ** 8;\n result += 8;\n }\n if (value \u003e= 10 ** 4) {\n value /= 10 ** 4;\n result += 4;\n }\n if (value \u003e= 10 ** 2) {\n value /= 10 ** 2;\n result += 2;\n }\n if (value \u003e= 10 ** 1) {\n result += 1;\n }\n }\n return result;\n }\n\n /**\n * @dev Return the log in base 10, following the selected rounding direction, of a positive value.\n * Returns 0 if given 0.\n */\n function log10(uint256 value, Rounding rounding) internal pure returns (uint256) {\n unchecked {\n uint256 result = log10(value);\n return result + (rounding == Rounding.Up \u0026\u0026 10 ** result \u003c value ? 1 : 0);\n }\n }\n\n /**\n * @dev Return the log in base 256, rounded down, of a positive value.\n * Returns 0 if given 0.\n *\n * Adding one to the result gives the number of pairs of hex symbols needed to represent `value` as a hex string.\n */\n function log256(uint256 value) internal pure returns (uint256) {\n uint256 result = 0;\n unchecked {\n if (value \u003e\u003e 128 \u003e 0) {\n value \u003e\u003e= 128;\n result += 16;\n }\n if (value \u003e\u003e 64 \u003e 0) {\n value \u003e\u003e= 64;\n result += 8;\n }\n if (value \u003e\u003e 32 \u003e 0) {\n value \u003e\u003e= 32;\n result += 4;\n }\n if (value \u003e\u003e 16 \u003e 0) {\n value \u003e\u003e= 16;\n result += 2;\n }\n if (value \u003e\u003e 8 \u003e 0) {\n result += 1;\n }\n }\n return result;\n }\n\n /**\n * @dev Return the log in base 256, following the selected rounding direction, of a positive value.\n * Returns 0 if given 0.\n */\n function log256(uint256 value, Rounding rounding) internal pure returns (uint256) {\n unchecked {\n uint256 result = log256(value);\n return result + (rounding == Rounding.Up \u0026\u0026 1 \u003c\u003c (result \u003c\u003c 3) \u003c value ? 1 : 0);\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/utils/math/SignedMath.sol\n\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/math/SignedMath.sol)\n\n/**\n * @dev Standard signed math utilities missing in the Solidity language.\n */\nlibrary SignedMath {\n /**\n * @dev Returns the largest of two signed numbers.\n */\n function max(int256 a, int256 b) internal pure returns (int256) {\n return a \u003e b ? a : b;\n }\n\n /**\n * @dev Returns the smallest of two signed numbers.\n */\n function min(int256 a, int256 b) internal pure returns (int256) {\n return a \u003c b ? a : b;\n }\n\n /**\n * @dev Returns the average of two signed numbers without overflow.\n * The result is rounded towards zero.\n */\n function average(int256 a, int256 b) internal pure returns (int256) {\n // Formula from the book \"Hacker's Delight\"\n int256 x = (a \u0026 b) + ((a ^ b) \u003e\u003e 1);\n return x + (int256(uint256(x) \u003e\u003e 255) \u0026 (a ^ b));\n }\n\n /**\n * @dev Returns the absolute unsigned value of a signed value.\n */\n function abs(int256 n) internal pure returns (uint256) {\n unchecked {\n // must be unchecked in order to support `n = type(int256).min`\n return uint256(n \u003e= 0 ? n : -n);\n }\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// 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/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/InterfaceSummit.sol\n\ninterface InterfaceSummit {\n // ══════════════════════════════════════════ ACCEPT AGENT STATEMENTS ══════════════════════════════════════════════\n\n /**\n * @notice Accepts a receipt, which local `AgentManager` verified to have been signed by an active Notary.\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 * - Notary who signed the receipt is referenced as the \"Receipt Notary\".\n * - Notary who signed the attestation on destination chain is referenced as the \"Attestation Notary\".\n * \u003e Will revert if any of these is true:\n * \u003e - Called by anyone other than local `AgentManager`.\n * \u003e - Receipt body payload is not properly formatted.\n * \u003e - Receipt signer is in Dispute.\n * \u003e - Receipt's snapshot root is unknown.\n * @param rcptNotaryIndex Index of Receipt Notary in Agent Merkle Tree\n * @param attNotaryIndex Index of Attestation Notary in Agent Merkle Tree\n * @param sigIndex Index of stored Notary signature\n * @param attNonce Nonce of the attestation used for proving the executed message\n * @param paddedTips Padded encoded paid tips information\n * @param rcptPayload Raw payload with message execution receipt\n * @return wasAccepted Whether the receipt was accepted\n */\n function acceptReceipt(\n uint32 rcptNotaryIndex,\n uint32 attNotaryIndex,\n uint256 sigIndex,\n uint32 attNonce,\n uint256 paddedTips,\n bytes memory rcptPayload\n ) external returns (bool wasAccepted);\n\n /**\n * @notice Accepts a snapshot, which local `AgentManager` verified to have been signed by an active Guard.\n * \u003e Snapshot is a list of states for a set of Origin contracts residing on any of the chains.\n * All the states in the Guard-signed snapshot become available for Notary signing.\n * \u003e Will revert if any of these is true:\n * \u003e - Called by anyone other than local `AgentManager`.\n * \u003e - Snapshot payload is not properly formatted.\n * \u003e - Snapshot contains a state older then the Guard has previously submitted.\n * @param guardIndex Index of Guard in Agent Merkle Tree\n * @param sigIndex Index of stored Agent signature\n * @param snapPayload Raw payload with snapshot data\n */\n function acceptGuardSnapshot(uint32 guardIndex, uint256 sigIndex, bytes memory snapPayload) external;\n\n /**\n * @notice Accepts a snapshot, which local `AgentManager` verified to have been signed by an active Notary.\n * \u003e Snapshot is a list of states for a set of Origin contracts residing on any of the chains.\n * Snapshot Merkle Root is calculated and saved for valid snapshots, i.e.\n * snapshots which are only using states previously submitted by any of the Guards.\n * - Notary could use states singed by the same of different Guards 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 - Called by anyone other than local `AgentManager`.\n * \u003e - Snapshot payload is not properly formatted.\n * \u003e - Snapshot contains a state older then the Notary has previously submitted.\n * \u003e - Snapshot contains a state that no Guard has previously submitted.\n * @param notaryIndex Index of Notary in Agent Merkle Tree\n * @param sigIndex Index of stored Agent signature\n * @param agentRoot Current root of the Agent Merkle Tree\n * @param snapPayload Raw payload with snapshot data\n * @return attPayload Raw payload with data for attestation derived from Notary snapshot.\n */\n function acceptNotarySnapshot(uint32 notaryIndex, uint256 sigIndex, bytes32 agentRoot, bytes memory snapPayload)\n external\n returns (bytes memory attPayload);\n\n // ════════════════════════════════════════════════ TIPS LOGIC ═════════════════════════════════════════════════════\n\n /**\n * @notice Distributes tips using the first Receipt from the \"receipt quarantine queue\".\n * Possible scenarios:\n * - Receipt queue is empty =\u003e does nothing\n * - Receipt optimistic period is not over =\u003e does nothing\n * - Either of Notaries present in Receipt was slashed =\u003e receipt is deleted from the queue\n * - Either of Notaries present in Receipt in Dispute =\u003e receipt is moved to the end of queue\n * - None of the above =\u003e receipt tips are distributed\n * @dev Returned value makes it possible to do the following: `while (distributeTips()) {}`\n * @return queuePopped Whether the first element was popped from the queue\n */\n function distributeTips() external returns (bool queuePopped);\n\n /**\n * @notice Withdraws locked base message tips from requested domain Origin to the recipient.\n * This is done by a call to a local Origin contract, or by a manager message to the remote chain.\n * @dev This will revert, if the pending balance of origin tips (earned-claimed) is lower than requested.\n * @param origin Domain of chain to withdraw tips on\n * @param amount Amount of tips to withdraw\n */\n function withdrawTips(uint32 origin, uint256 amount) external;\n\n // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════\n\n /**\n * @notice Returns earned and claimed tips for the actor.\n * Note: Tips for address(0) belong to the Treasury.\n * @param actor Address of the actor\n * @param origin Domain where the tips were initially paid\n * @return earned Total amount of origin tips the actor has earned so far\n * @return claimed Total amount of origin tips the actor has claimed so far\n */\n function actorTips(address actor, uint32 origin) external view returns (uint128 earned, uint128 claimed);\n\n /**\n * @notice Returns the amount of receipts in the \"Receipt Quarantine Queue\".\n */\n function receiptQueueLength() external view returns (uint256);\n\n /**\n * @notice Returns the state with the highest known nonce\n * submitted by any of the currently active Guards.\n * @param origin Domain of origin chain\n * @return statePayload Raw payload with latest active Guard state for origin\n */\n function getLatestState(uint32 origin) external view returns (bytes memory statePayload);\n}\n\n// node_modules/@openzeppelin/contracts/utils/Strings.sol\n\n// OpenZeppelin Contracts (last updated v4.9.0) (utils/Strings.sol)\n\n/**\n * @dev String operations.\n */\nlibrary Strings {\n bytes16 private constant _SYMBOLS = \"0123456789abcdef\";\n uint8 private constant _ADDRESS_LENGTH = 20;\n\n /**\n * @dev Converts a `uint256` to its ASCII `string` decimal representation.\n */\n function toString(uint256 value) internal pure returns (string memory) {\n unchecked {\n uint256 length = Math.log10(value) + 1;\n string memory buffer = new string(length);\n uint256 ptr;\n /// @solidity memory-safe-assembly\n assembly {\n ptr := add(buffer, add(32, length))\n }\n while (true) {\n ptr--;\n /// @solidity memory-safe-assembly\n assembly {\n mstore8(ptr, byte(mod(value, 10), _SYMBOLS))\n }\n value /= 10;\n if (value == 0) break;\n }\n return buffer;\n }\n }\n\n /**\n * @dev Converts a `int256` to its ASCII `string` decimal representation.\n */\n function toString(int256 value) internal pure returns (string memory) {\n return string(abi.encodePacked(value \u003c 0 ? \"-\" : \"\", toString(SignedMath.abs(value))));\n }\n\n /**\n * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation.\n */\n function toHexString(uint256 value) internal pure returns (string memory) {\n unchecked {\n return toHexString(value, Math.log256(value) + 1);\n }\n }\n\n /**\n * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length.\n */\n function toHexString(uint256 value, uint256 length) internal pure returns (string memory) {\n bytes memory buffer = new bytes(2 * length + 2);\n buffer[0] = \"0\";\n buffer[1] = \"x\";\n for (uint256 i = 2 * length + 1; i \u003e 1; --i) {\n buffer[i] = _SYMBOLS[value \u0026 0xf];\n value \u003e\u003e= 4;\n }\n require(value == 0, \"Strings: hex length insufficient\");\n return string(buffer);\n }\n\n /**\n * @dev Converts an `address` with fixed length of 20 bytes to its not checksummed ASCII `string` hexadecimal representation.\n */\n function toHexString(address addr) internal pure returns (string memory) {\n return toHexString(uint256(uint160(addr)), _ADDRESS_LENGTH);\n }\n\n /**\n * @dev Returns true if the two strings are equal.\n */\n function equal(string memory a, string memory b) internal pure returns (bool) {\n return keccak256(bytes(a)) == keccak256(bytes(b));\n }\n}\n\n// node_modules/@openzeppelin/contracts-upgradeable/utils/ContextUpgradeable.sol\n\n// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)\n\n/**\n * @dev Provides information about the current execution context, including the\n * sender of the transaction and its data. While these are generally available\n * via msg.sender and msg.data, they should not be accessed in such a direct\n * manner, since when dealing with meta-transactions the account sending and\n * paying for execution may not be the actual sender (as far as an application\n * is concerned).\n *\n * This contract is only required for intermediate, library-like contracts.\n */\nabstract contract ContextUpgradeable is Initializable {\n function __Context_init() internal onlyInitializing {\n }\n\n function __Context_init_unchained() internal onlyInitializing {\n }\n function _msgSender() internal view virtual returns (address) {\n return msg.sender;\n }\n\n function _msgData() internal view virtual returns (bytes calldata) {\n return msg.data;\n }\n\n /**\n * @dev This empty reserved space is put in place to allow future versions to add new\n * variables without shifting down storage in the inheritance chain.\n * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\n */\n uint256[50] private __gap;\n}\n\n// contracts/libs/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/utils/cryptography/ECDSA.sol\n\n// OpenZeppelin Contracts (last updated v4.9.0) (utils/cryptography/ECDSA.sol)\n\n/**\n * @dev Elliptic Curve Digital Signature Algorithm (ECDSA) operations.\n *\n * These functions can be used to verify that a message was signed by the holder\n * of the private keys of a given address.\n */\nlibrary ECDSA {\n enum RecoverError {\n NoError,\n InvalidSignature,\n InvalidSignatureLength,\n InvalidSignatureS,\n InvalidSignatureV // Deprecated in v4.8\n }\n\n function _throwError(RecoverError error) private pure {\n if (error == RecoverError.NoError) {\n return; // no error: do nothing\n } else if (error == RecoverError.InvalidSignature) {\n revert(\"ECDSA: invalid signature\");\n } else if (error == RecoverError.InvalidSignatureLength) {\n revert(\"ECDSA: invalid signature length\");\n } else if (error == RecoverError.InvalidSignatureS) {\n revert(\"ECDSA: invalid signature 's' value\");\n }\n }\n\n /**\n * @dev Returns the address that signed a hashed message (`hash`) with\n * `signature` or error string. This address can then be used for verification purposes.\n *\n * The `ecrecover` EVM opcode allows for malleable (non-unique) signatures:\n * this function rejects them by requiring the `s` value to be in the lower\n * half order, and the `v` value to be either 27 or 28.\n *\n * IMPORTANT: `hash` _must_ be the result of a hash operation for the\n * verification to be secure: it is possible to craft signatures that\n * recover to arbitrary addresses for non-hashed data. A safe way to ensure\n * this is by receiving a hash of the original message (which may otherwise\n * be too long), and then calling {toEthSignedMessageHash} on it.\n *\n * Documentation for signature generation:\n * - with https://web3js.readthedocs.io/en/v1.3.4/web3-eth-accounts.html#sign[Web3.js]\n * - with https://docs.ethers.io/v5/api/signer/#Signer-signMessage[ethers]\n *\n * _Available since v4.3._\n */\n function tryRecover(bytes32 hash, bytes memory signature) internal pure returns (address, RecoverError) {\n if (signature.length == 65) {\n bytes32 r;\n bytes32 s;\n uint8 v;\n // ecrecover takes the signature parameters, and the only way to get them\n // currently is to use assembly.\n /// @solidity memory-safe-assembly\n assembly {\n r := mload(add(signature, 0x20))\n s := mload(add(signature, 0x40))\n v := byte(0, mload(add(signature, 0x60)))\n }\n return tryRecover(hash, v, r, s);\n } else {\n return (address(0), RecoverError.InvalidSignatureLength);\n }\n }\n\n /**\n * @dev Returns the address that signed a hashed message (`hash`) with\n * `signature`. This address can then be used for verification purposes.\n *\n * The `ecrecover` EVM opcode allows for malleable (non-unique) signatures:\n * this function rejects them by requiring the `s` value to be in the lower\n * half order, and the `v` value to be either 27 or 28.\n *\n * IMPORTANT: `hash` _must_ be the result of a hash operation for the\n * verification to be secure: it is possible to craft signatures that\n * recover to arbitrary addresses for non-hashed data. A safe way to ensure\n * this is by receiving a hash of the original message (which may otherwise\n * be too long), and then calling {toEthSignedMessageHash} on it.\n */\n function recover(bytes32 hash, bytes memory signature) internal pure returns (address) {\n (address recovered, RecoverError error) = tryRecover(hash, signature);\n _throwError(error);\n return recovered;\n }\n\n /**\n * @dev Overload of {ECDSA-tryRecover} that receives the `r` and `vs` short-signature fields separately.\n *\n * See https://eips.ethereum.org/EIPS/eip-2098[EIP-2098 short signatures]\n *\n * _Available since v4.3._\n */\n function tryRecover(bytes32 hash, bytes32 r, bytes32 vs) internal pure returns (address, RecoverError) {\n bytes32 s = vs \u0026 bytes32(0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff);\n uint8 v = uint8((uint256(vs) \u003e\u003e 255) + 27);\n return tryRecover(hash, v, r, s);\n }\n\n /**\n * @dev Overload of {ECDSA-recover} that receives the `r and `vs` short-signature fields separately.\n *\n * _Available since v4.2._\n */\n function recover(bytes32 hash, bytes32 r, bytes32 vs) internal pure returns (address) {\n (address recovered, RecoverError error) = tryRecover(hash, r, vs);\n _throwError(error);\n return recovered;\n }\n\n /**\n * @dev Overload of {ECDSA-tryRecover} that receives the `v`,\n * `r` and `s` signature fields separately.\n *\n * _Available since v4.3._\n */\n function tryRecover(bytes32 hash, uint8 v, bytes32 r, bytes32 s) internal pure returns (address, RecoverError) {\n // EIP-2 still allows signature malleability for ecrecover(). Remove this possibility and make the signature\n // unique. Appendix F in the Ethereum Yellow paper (https://ethereum.github.io/yellowpaper/paper.pdf), defines\n // the valid range for s in (301): 0 \u003c s \u003c secp256k1n ÷ 2 + 1, and for v in (302): v ∈ {27, 28}. Most\n // signatures from current libraries generate a unique signature with an s-value in the lower half order.\n //\n // If your library generates malleable signatures, such as s-values in the upper range, calculate a new s-value\n // with 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141 - s1 and flip v from 27 to 28 or\n // vice versa. If your library also generates signatures with 0/1 for v instead 27/28, add 27 to v to accept\n // these malleable signatures as well.\n if (uint256(s) \u003e 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0) {\n return (address(0), RecoverError.InvalidSignatureS);\n }\n\n // If the signature is valid (and not malleable), return the signer address\n address signer = ecrecover(hash, v, r, s);\n if (signer == address(0)) {\n return (address(0), RecoverError.InvalidSignature);\n }\n\n return (signer, RecoverError.NoError);\n }\n\n /**\n * @dev Overload of {ECDSA-recover} that receives the `v`,\n * `r` and `s` signature fields separately.\n */\n function recover(bytes32 hash, uint8 v, bytes32 r, bytes32 s) internal pure returns (address) {\n (address recovered, RecoverError error) = tryRecover(hash, v, r, s);\n _throwError(error);\n return recovered;\n }\n\n /**\n * @dev Returns an Ethereum Signed Message, created from a `hash`. This\n * produces hash corresponding to the one signed with the\n * https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`]\n * JSON-RPC method as part of EIP-191.\n *\n * See {recover}.\n */\n function toEthSignedMessageHash(bytes32 hash) internal pure returns (bytes32 message) {\n // 32 is the length in bytes of hash,\n // enforced by the type signature above\n /// @solidity memory-safe-assembly\n assembly {\n mstore(0x00, \"\\x19Ethereum Signed Message:\\n32\")\n mstore(0x1c, hash)\n message := keccak256(0x00, 0x3c)\n }\n }\n\n /**\n * @dev Returns an Ethereum Signed Message, created from `s`. This\n * produces hash corresponding to the one signed with the\n * https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`]\n * JSON-RPC method as part of EIP-191.\n *\n * See {recover}.\n */\n function toEthSignedMessageHash(bytes memory s) internal pure returns (bytes32) {\n return keccak256(abi.encodePacked(\"\\x19Ethereum Signed Message:\\n\", Strings.toString(s.length), s));\n }\n\n /**\n * @dev Returns an Ethereum Signed Typed Data, created from a\n * `domainSeparator` and a `structHash`. This produces hash corresponding\n * to the one signed with the\n * https://eips.ethereum.org/EIPS/eip-712[`eth_signTypedData`]\n * JSON-RPC method as part of EIP-712.\n *\n * See {recover}.\n */\n function toTypedDataHash(bytes32 domainSeparator, bytes32 structHash) internal pure returns (bytes32 data) {\n /// @solidity memory-safe-assembly\n assembly {\n let ptr := mload(0x40)\n mstore(ptr, \"\\x19\\x01\")\n mstore(add(ptr, 0x02), domainSeparator)\n mstore(add(ptr, 0x22), structHash)\n data := keccak256(ptr, 0x42)\n }\n }\n\n /**\n * @dev Returns an Ethereum Signed Data with intended validator, created from a\n * `validator` and `data` according to the version 0 of EIP-191.\n *\n * See {recover}.\n */\n function toDataWithIntendedValidatorHash(address validator, bytes memory data) internal pure returns (bytes32) {\n return keccak256(abi.encodePacked(\"\\x19\\x00\", validator, data));\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/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/inbox/StatementInbox.sol\n\n// ══════════════════════════════ LIBRARY IMPORTS ══════════════════════════════\n\n// ═════════════════════════════ INTERNAL IMPORTS ══════════════════════════════\n\n// ═════════════════════════════ EXTERNAL IMPORTS ══════════════════════════════\n\n/// @notice `StatementInbox` is the entry point for all agent-signed statements. It verifies the\n/// agent signatures, and passes the unsigned statements to the contract to consume it via `acceptX` functions. Is is\n/// also used to verify the agent-signed statements and initiate the agent slashing, should the statement be invalid.\n/// `StatementInbox` is responsible for the following:\n/// - Accepting State and Receipt Reports to initiate a dispute between Guard and Notary.\n/// - Storing all the Guard Reports with the Guard signature leading to a dispute.\n/// - Verifying State/State Reports referencing the local chain and slashing the signer if statement is invalid.\n/// - Verifying Receipt/Receipt Reports referencing the local chain and slashing the signer if statement is invalid.\nabstract contract StatementInbox is MessagingBase, StatementInboxEvents, IStatementInbox {\n using AttestationLib for bytes;\n using ReceiptLib for bytes;\n using StateLib for bytes;\n using SnapshotLib for bytes;\n\n struct StoredReport {\n uint256 sigIndex;\n bytes statementPayload;\n }\n\n // ══════════════════════════════════════════════════ STORAGE ══════════════════════════════════════════════════════\n\n address public agentManager;\n address public origin;\n address public destination;\n\n // TODO: optimize this\n bytes[] internal _storedSignatures;\n StoredReport[] internal _storedReports;\n\n /// @dev gap for upgrade safety\n uint256[45] private __GAP; // solhint-disable-line var-name-mixedcase\n\n // ════════════════════════════════════════════════ INITIALIZER ════════════════════════════════════════════════════\n\n /// @dev Initializes the contract:\n /// - Sets up `msg.sender` as the owner of the contract.\n /// - Sets up `agentManager`, `origin`, and `destination`.\n // solhint-disable-next-line func-name-mixedcase\n function __StatementInbox_init(address agentManager_, address origin_, address destination_)\n internal\n onlyInitializing\n {\n agentManager = agentManager_;\n origin = origin_;\n destination = destination_;\n __Ownable2Step_init();\n }\n\n // ══════════════════════════════════════════ SUBMIT AGENT STATEMENTS ══════════════════════════════════════════════\n\n /// @inheritdoc IStatementInbox\n // solhint-disable-next-line ordering\n function submitStateReportWithSnapshot(\n uint8 stateIndex,\n bytes memory srSignature,\n bytes memory snapPayload,\n bytes memory snapSignature\n ) external returns (bool wasAccepted) {\n // This will revert if payload is not a snapshot\n Snapshot snapshot = snapPayload.castToSnapshot();\n // This will revert if the snapshot signer is not a known Notary\n (AgentStatus memory notaryStatus,) =\n _verifySnapshot({snapshot: snapshot, snapSignature: snapSignature, verifyNotary: true});\n // Notary needs to be Active/Unstaking\n notaryStatus.verifyActiveUnstaking();\n // Check if Notary is active on this chain\n _verifyNotaryDomain(notaryStatus.domain);\n // This will revert if state index is out of range\n State state = snapshot.state(stateIndex);\n // This will revert if the report signer is not an known Guard\n (AgentStatus memory guardStatus,) = _verifyStateReport(state, srSignature);\n // Check that Guard is active\n guardStatus.verifyActive();\n _saveReport(state.unwrap().clone(), srSignature);\n // This will revert if either actor is already in dispute\n IAgentManager(agentManager).openDispute(guardStatus.index, notaryStatus.index);\n return true;\n }\n\n /// @inheritdoc IStatementInbox\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 // This will revert if payload is not a snapshot\n Snapshot snapshot = snapPayload.castToSnapshot();\n // This will revert if state index is out of range\n State state = snapshot.state(stateIndex);\n // This will revert if the report signer is not an known Guard\n (AgentStatus memory guardStatus,) = _verifyStateReport(state, srSignature);\n // Check that Guard is active\n guardStatus.verifyActive();\n // This will revert if payload is not an attestation\n Attestation att = attPayload.castToAttestation();\n // This will revert if signer is not an known Notary\n (AgentStatus memory notaryStatus,) = _verifyAttestation(att, attSignature);\n // Notary needs to be Active/Unstaking\n notaryStatus.verifyActiveUnstaking();\n // Check if Notary is active on this chain\n _verifyNotaryDomain(notaryStatus.domain);\n if (snapshot.calculateRoot() != att.snapRoot()) revert IncorrectSnapshotRoot();\n _saveReport(state.unwrap().clone(), srSignature);\n // This will revert if either actor is already in dispute\n IAgentManager(agentManager).openDispute(guardStatus.index, notaryStatus.index);\n return true;\n }\n\n /// @inheritdoc IStatementInbox\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 // This will revert if payload is not a state\n State state = statePayload.castToState();\n // This will revert if the report signer is not an known Guard\n (AgentStatus memory guardStatus,) = _verifyStateReport(state, srSignature);\n // Check that Guard is active\n guardStatus.verifyActive();\n // This will revert if payload is not an attestation\n Attestation att = attPayload.castToAttestation();\n // This will revert if signer is not a known Notary\n (AgentStatus memory notaryStatus,) = _verifyAttestation(att, attSignature);\n // Notary needs to be Active/Unstaking\n notaryStatus.verifyActiveUnstaking();\n // Check if Notary is active on this chain\n _verifyNotaryDomain(notaryStatus.domain);\n // This will revert if any of these is true:\n // - Attestation root is not equal to Merkle Root derived from State and Snapshot Proof.\n // - Snapshot Proof's first element does not match the State metadata.\n // - Snapshot Proof length exceeds Snapshot tree Height.\n // - State index is out of range.\n _verifySnapshotMerkle(att, stateIndex, state, snapProof);\n _saveReport(statePayload, srSignature);\n // This will revert if either actor is already in dispute\n IAgentManager(agentManager).openDispute(guardStatus.index, notaryStatus.index);\n return true;\n }\n\n // ══════════════════════════════════════════ VERIFY AGENT STATEMENTS ══════════════════════════════════════════════\n\n /// @inheritdoc IStatementInbox\n function verifyReceipt(bytes memory rcptPayload, bytes memory rcptSignature)\n external\n returns (bool isValidReceipt)\n {\n // This will revert if payload is not a receipt\n Receipt rcpt = rcptPayload.castToReceipt();\n // This will revert if the attestation signer is not a known Notary\n (AgentStatus memory status, address notary) = _verifyReceipt(rcpt, rcptSignature);\n // Notary needs to be Active/Unstaking\n status.verifyActiveUnstaking();\n isValidReceipt = IExecutionHub(destination).isValidReceipt(rcptPayload);\n if (!isValidReceipt) {\n emit InvalidReceipt(rcptPayload, rcptSignature);\n IAgentManager(agentManager).slashAgent(status.domain, notary, msg.sender);\n }\n }\n\n /// @inheritdoc IStatementInbox\n function verifyReceiptReport(bytes memory rcptPayload, bytes memory rrSignature)\n external\n returns (bool isValidReport)\n {\n // This will revert if payload is not a receipt\n Receipt rcpt = rcptPayload.castToReceipt();\n // This will revert if the report signer is not a known Guard\n (AgentStatus memory status, address guard) = _verifyReceiptReport(rcpt, rrSignature);\n // Guard needs to be Active/Unstaking\n status.verifyActiveUnstaking();\n // Report is valid IF AND ONLY IF the reported receipt in invalid\n isValidReport = !IExecutionHub(destination).isValidReceipt(rcptPayload);\n if (!isValidReport) {\n emit InvalidReceiptReport(rcptPayload, rrSignature);\n IAgentManager(agentManager).slashAgent(status.domain, guard, msg.sender);\n }\n }\n\n /// @inheritdoc IStatementInbox\n function verifyStateWithAttestation(\n uint8 stateIndex,\n bytes memory snapPayload,\n bytes memory attPayload,\n bytes memory attSignature\n ) external returns (bool isValidState) {\n // This will revert if payload is not an attestation\n Attestation att = attPayload.castToAttestation();\n // This will revert if the attestation signer is not a known Notary\n (AgentStatus memory status, address notary) = _verifyAttestation(att, attSignature);\n // Notary needs to be Active/Unstaking\n status.verifyActiveUnstaking();\n // This will revert if payload is not a snapshot\n Snapshot snapshot = snapPayload.castToSnapshot();\n if (snapshot.calculateRoot() != att.snapRoot()) revert IncorrectSnapshotRoot();\n // This will revert if state does not refer to this chain\n bytes memory statePayload = snapshot.state(stateIndex).unwrap().clone();\n isValidState = IStateHub(origin).isValidState(statePayload);\n if (!isValidState) {\n emit InvalidStateWithAttestation(stateIndex, statePayload, attPayload, attSignature);\n IAgentManager(agentManager).slashAgent(status.domain, notary, msg.sender);\n }\n }\n\n /// @inheritdoc IStatementInbox\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 // This will revert if payload is not an attestation\n Attestation att = attPayload.castToAttestation();\n // This will revert if the attestation signer is not a known Notary\n (AgentStatus memory status, address notary) = _verifyAttestation(att, attSignature);\n // Notary needs to be Active/Unstaking\n status.verifyActiveUnstaking();\n // This will revert if payload is not a state\n State state = statePayload.castToState();\n // This will revert if any of these is true:\n // - Attestation root is not equal to Merkle Root derived from State and Snapshot Proof.\n // - Snapshot Proof's first element does not match the State metadata.\n // - Snapshot Proof length exceeds Snapshot tree Height.\n // - State index is out of range.\n _verifySnapshotMerkle(att, stateIndex, state, snapProof);\n // This will revert if state does not refer to this chain\n isValidState = IStateHub(origin).isValidState(statePayload);\n if (!isValidState) {\n emit InvalidStateWithAttestation(stateIndex, statePayload, attPayload, attSignature);\n IAgentManager(agentManager).slashAgent(status.domain, notary, msg.sender);\n }\n }\n\n /// @inheritdoc IStatementInbox\n function verifyStateWithSnapshot(uint8 stateIndex, bytes memory snapPayload, bytes memory snapSignature)\n external\n returns (bool isValidState)\n {\n // This will revert if payload is not a snapshot\n Snapshot snapshot = snapPayload.castToSnapshot();\n // This will revert if the snapshot signer is not a known Guard/Notary\n (AgentStatus memory status, address agent) =\n _verifySnapshot({snapshot: snapshot, snapSignature: snapSignature, verifyNotary: false});\n // Agent needs to be Active/Unstaking\n status.verifyActiveUnstaking();\n // This will revert if state does not refer to this chain\n isValidState = IStateHub(origin).isValidState(snapshot.state(stateIndex).unwrap().clone());\n if (!isValidState) {\n emit InvalidStateWithSnapshot(stateIndex, snapPayload, snapSignature);\n IAgentManager(agentManager).slashAgent(status.domain, agent, msg.sender);\n }\n }\n\n /// @inheritdoc IStatementInbox\n function verifyStateReport(bytes memory statePayload, bytes memory srSignature)\n external\n returns (bool isValidReport)\n {\n // This will revert if payload is not a state\n State state = statePayload.castToState();\n // This will revert if the report signer is not a known Guard\n (AgentStatus memory status, address guard) = _verifyStateReport(state, srSignature);\n // Guard needs to be Active/Unstaking\n status.verifyActiveUnstaking();\n // Report is valid IF AND ONLY IF the reported state in invalid\n // This will revert if the reported state does not refer to this chain\n isValidReport = !IStateHub(origin).isValidState(statePayload);\n if (!isValidReport) {\n emit InvalidStateReport(statePayload, srSignature);\n IAgentManager(agentManager).slashAgent(status.domain, guard, msg.sender);\n }\n }\n\n // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════\n\n /// @inheritdoc IStatementInbox\n function getReportsAmount() external view returns (uint256) {\n return _storedReports.length;\n }\n\n /// @inheritdoc IStatementInbox\n function getGuardReport(uint256 index)\n external\n view\n returns (bytes memory statementPayload, bytes memory reportSignature)\n {\n if (index \u003e= _storedReports.length) revert IndexOutOfRange();\n StoredReport memory storedReport = _storedReports[index];\n statementPayload = storedReport.statementPayload;\n reportSignature = _storedSignatures[storedReport.sigIndex];\n }\n\n /// @inheritdoc IStatementInbox\n function getStoredSignature(uint256 index) external view returns (bytes memory) {\n return _storedSignatures[index];\n }\n\n // ══════════════════════════════════════════════ INTERNAL LOGIC ═══════════════════════════════════════════════════\n\n /// @dev Saves the statement reported by Guard as invalid and the Guard Report signature.\n function _saveReport(bytes memory statementPayload, bytes memory reportSignature) internal {\n uint256 sigIndex = _saveSignature(reportSignature);\n _storedReports.push(StoredReport(sigIndex, statementPayload));\n }\n\n /// @dev Saves the signature and returns its index.\n function _saveSignature(bytes memory signature) internal returns (uint256 sigIndex) {\n sigIndex = _storedSignatures.length;\n _storedSignatures.push(signature);\n }\n\n // ═══════════════════════════════════════════════ AGENT CHECKS ════════════════════════════════════════════════════\n\n /**\n * @dev Recovers a signer from a hashed message, and a EIP-191 signature for it.\n * Will revert, if the signer is not a known agent.\n * @dev Agent flag could be any of these: Active/Unstaking/Resting/Fraudulent/Slashed\n * Further checks need to be performed in a caller function.\n * @param hashedStatement Hash of the statement that was signed by an Agent\n * @param signature Agent signature for the hashed statement\n * @return status Struct representing agent status:\n * - flag Unknown/Active/Unstaking/Resting/Fraudulent/Slashed\n * - domain Domain where agent is/was active\n * - index Index of agent in the Agent Merkle Tree\n * @return agent Agent that signed the statement\n */\n function _recoverAgent(bytes32 hashedStatement, bytes memory signature)\n internal\n view\n returns (AgentStatus memory status, address agent)\n {\n bytes32 ethSignedMsg = ECDSA.toEthSignedMessageHash(hashedStatement);\n agent = ECDSA.recover(ethSignedMsg, signature);\n status = IAgentManager(agentManager).agentStatus(agent);\n // Discard signature of unknown agents.\n // Further flag checks are supposed to be performed in a caller function.\n status.verifyKnown();\n }\n\n /// @dev Verifies that Notary signature is active on local domain.\n function _verifyNotaryDomain(uint32 notaryDomain) internal view {\n // Notary needs to be from the local domain (if contract is not deployed on Synapse Chain).\n // Or Notary could be from any domain (if contract is deployed on Synapse Chain).\n if (notaryDomain != localDomain \u0026\u0026 localDomain != synapseDomain) revert IncorrectAgentDomain();\n }\n\n // ════════════════════════════════════════ ATTESTATION RELATED CHECKS ═════════════════════════════════════════════\n\n /**\n * @dev Internal function to verify the signed attestation payload.\n * Reverts if any of these is true:\n * - Attestation signer is not a known Notary.\n * @param att Typed memory view over attestation payload\n * @param attSignature Notary signature for the attestation\n * @return status Struct representing agent status, see {_recoverAgent}\n * @return notary Notary that signed the snapshot\n */\n function _verifyAttestation(Attestation att, bytes memory attSignature)\n internal\n view\n returns (AgentStatus memory status, address notary)\n {\n // This will revert if signer is not a known agent\n (status, notary) = _recoverAgent(att.hashValid(), attSignature);\n // Attestation signer needs to be a Notary, not a Guard\n if (status.domain == 0) revert AgentNotNotary();\n }\n\n /**\n * @dev Internal function to verify the signed attestation report payload.\n * Reverts if any of these is true:\n * - Report signer is not a known Guard.\n * @param att Typed memory view over attestation payload that Guard reports as invalid\n * @param arSignature Guard signature for the \"invalid attestation\" report\n * @return status Struct representing guard status, see {_recoverAgent}\n * @return guard Guard that signed the report\n */\n function _verifyAttestationReport(Attestation att, bytes memory arSignature)\n internal\n view\n returns (AgentStatus memory status, address guard)\n {\n // This will revert if signer is not a known agent\n (status, guard) = _recoverAgent(att.hashInvalid(), arSignature);\n // Report signer needs to be a Guard, not a Notary\n if (status.domain != 0) revert AgentNotGuard();\n }\n\n // ══════════════════════════════════════════ RECEIPT RELATED CHECKS ═══════════════════════════════════════════════\n\n /**\n * @dev Internal function to verify the signed receipt payload.\n * Reverts if any of these is true:\n * - Receipt signer is not a known Notary.\n * @param rcpt Typed memory view over receipt payload\n * @param rcptSignature Notary signature for the receipt\n * @return status Struct representing agent status, see {_recoverAgent}\n * @return notary Notary that signed the snapshot\n */\n function _verifyReceipt(Receipt rcpt, bytes memory rcptSignature)\n internal\n view\n returns (AgentStatus memory status, address notary)\n {\n // This will revert if signer is not a known agent\n (status, notary) = _recoverAgent(rcpt.hashValid(), rcptSignature);\n // Receipt signer needs to be a Notary, not a Guard\n if (status.domain == 0) revert AgentNotNotary();\n }\n\n /**\n * @dev Internal function to verify the signed receipt report payload.\n * Reverts if any of these is true:\n * - Report signer is not a known Guard.\n * @param rcpt Typed memory view over receipt payload that Guard reports as invalid\n * @param rrSignature Guard signature for the \"invalid receipt\" report\n * @return status Struct representing guard status, see {_recoverAgent}\n * @return guard Guard that signed the report\n */\n function _verifyReceiptReport(Receipt rcpt, bytes memory rrSignature)\n internal\n view\n returns (AgentStatus memory status, address guard)\n {\n // This will revert if signer is not a known agent\n (status, guard) = _recoverAgent(rcpt.hashInvalid(), rrSignature);\n // Report signer needs to be a Guard, not a Notary\n if (status.domain != 0) revert AgentNotGuard();\n }\n\n // ═══════════════════════════════════════ STATE/SNAPSHOT RELATED CHECKS ═══════════════════════════════════════════\n\n /**\n * @dev Internal function to verify the signed snapshot report payload.\n * Reverts if any of these is true:\n * - Report signer is not a known Guard.\n * @param state Typed memory view over state payload that Guard reports as invalid\n * @param srSignature Guard signature for the report\n * @return status Struct representing guard status, see {_recoverAgent}\n * @return guard Guard that signed the report\n */\n function _verifyStateReport(State state, bytes memory srSignature)\n internal\n view\n returns (AgentStatus memory status, address guard)\n {\n // This will revert if signer is not a known agent\n (status, guard) = _recoverAgent(state.hashInvalid(), srSignature);\n // Report signer needs to be a Guard, not a Notary\n if (status.domain != 0) revert AgentNotGuard();\n }\n\n /**\n * @dev Internal function to verify the signed snapshot payload.\n * Reverts if any of these is true:\n * - Snapshot signer is not a known Agent.\n * - Snapshot signer is not a Notary (if verifyNotary is true).\n * @param snapshot Typed memory view over snapshot payload\n * @param snapSignature Agent signature for the snapshot\n * @param verifyNotary If true, snapshot signer needs to be a Notary, not a Guard\n * @return status Struct representing agent status, see {_recoverAgent}\n * @return agent Agent that signed the snapshot\n */\n function _verifySnapshot(Snapshot snapshot, bytes memory snapSignature, bool verifyNotary)\n internal\n view\n returns (AgentStatus memory status, address agent)\n {\n // This will revert if signer is not a known agent\n (status, agent) = _recoverAgent(snapshot.hashValid(), snapSignature);\n // If requested, snapshot signer needs to be a Notary, not a Guard\n if (verifyNotary \u0026\u0026 status.domain == 0) revert AgentNotNotary();\n }\n\n // ═══════════════════════════════════════════ MERKLE RELATED CHECKS ═══════════════════════════════════════════════\n\n /**\n * @dev Internal function to verify that snapshot roots match.\n * Reverts if any of these is true:\n * - Attestation root is not equal to Merkle Root derived from State and Snapshot Proof.\n * - Snapshot Proof's first element does not match the State metadata.\n * - Snapshot Proof length exceeds Snapshot tree Height.\n * - State index is out of range.\n * @param att Typed memory view over Attestation\n * @param stateIndex Index of state in the snapshot\n * @param state Typed memory view over the provided state payload\n * @param snapProof Raw payload with snapshot data\n */\n function _verifySnapshotMerkle(Attestation att, uint8 stateIndex, State state, bytes32[] memory snapProof)\n internal\n pure\n {\n // Snapshot proof first element should match State metadata (aka \"right sub-leaf\")\n (, bytes32 rightSubLeaf) = state.subLeafs();\n if (snapProof[0] != rightSubLeaf) revert IncorrectSnapshotProof();\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(state.root(), state.origin(), snapProof, stateIndex);\n // Snapshot root should match the attestation root\n if (att.snapRoot() != snapshotRoot) revert IncorrectSnapshotRoot();\n }\n}\n\n// contracts/inbox/Inbox.sol\n\n// ══════════════════════════════ LIBRARY IMPORTS ══════════════════════════════\n\n// ═════════════════════════════ INTERNAL IMPORTS ══════════════════════════════\n\n/// @notice `Inbox` is the child of `StatementInbox` contract, that is used on Synapse Chain.\n/// In addition to the functionality of `StatementInbox`, it also:\n/// - Accepts Guard and Notary Snapshots and passes them to `Summit` contract.\n/// - Accepts Notary-signed Receipts and passes them to `Summit` contract.\n/// - Accepts Receipt Reports to initiate a dispute between Guard and Notary.\n/// - Verifies Attestations and Attestation Reports, and slashes the signer if they are invalid.\ncontract Inbox is StatementInbox, InboxEvents, InterfaceInbox {\n using AttestationLib for bytes;\n using ReceiptLib for bytes;\n using SnapshotLib for bytes;\n\n // Struct to get around stack too deep error. TODO: revisit this\n struct ReceiptInfo {\n AgentStatus rcptNotaryStatus;\n address notary;\n uint32 attNonce;\n AgentStatus attNotaryStatus;\n }\n\n // ══════════════════════════════════════════════════ STORAGE ══════════════════════════════════════════════════════\n\n // The address of the Summit contract.\n address public summit;\n\n // ═════════════════════════════════════════ CONSTRUCTOR \u0026 INITIALIZER ═════════════════════════════════════════════\n\n constructor(uint32 synapseDomain_) MessagingBase(\"0.0.3\", synapseDomain_) {\n if (localDomain != synapseDomain) revert MustBeSynapseDomain();\n }\n\n /// @notice Initializes `Inbox` contract:\n /// - Sets `msg.sender` as the owner of the contract\n /// - Sets `agentManager`, `origin`, `destination` and `summit` addresses\n function initialize(address agentManager_, address origin_, address destination_, address summit_)\n external\n initializer\n {\n __StatementInbox_init(agentManager_, origin_, destination_);\n summit = summit_;\n }\n\n // ══════════════════════════════════════════ SUBMIT AGENT STATEMENTS ══════════════════════════════════════════════\n\n /// @inheritdoc InterfaceInbox\n function submitSnapshot(bytes memory snapPayload, bytes memory snapSignature)\n external\n returns (bytes memory attPayload, bytes32 agentRoot_, uint256[] memory snapGas)\n {\n // This will revert if payload is not a snapshot\n Snapshot snapshot = snapPayload.castToSnapshot();\n // This will revert if the signer is not a known Guard/Notary\n (AgentStatus memory status, address agent) =\n _verifySnapshot({snapshot: snapshot, snapSignature: snapSignature, verifyNotary: false});\n // Check that Agent is active\n status.verifyActive();\n // Store Agent signature for the Snapshot\n uint256 sigIndex = _saveSignature(snapSignature);\n if (status.domain == 0) {\n // Guard that is in Dispute could still submit new snapshots, so we don't check that\n InterfaceSummit(summit).acceptGuardSnapshot({\n guardIndex: status.index,\n sigIndex: sigIndex,\n snapPayload: snapPayload\n });\n } else {\n // Get current agentRoot from AgentManager\n agentRoot_ = IAgentManager(agentManager).agentRoot();\n // This will revert if Notary is in Dispute\n attPayload = InterfaceSummit(summit).acceptNotarySnapshot({\n notaryIndex: status.index,\n sigIndex: sigIndex,\n agentRoot: agentRoot_,\n snapPayload: snapPayload\n });\n ChainGas[] memory snapGas_ = snapshot.snapGas();\n // Pass created attestation to Destination to enable executing messages coming to Synapse Chain\n InterfaceDestination(destination).acceptAttestation(\n status.index, type(uint256).max, attPayload, agentRoot_, snapGas_\n );\n // Use assembly to cast ChainGas[] to uint256[] without copying. Highest bits are left zeroed.\n // solhint-disable-next-line no-inline-assembly\n assembly {\n snapGas := snapGas_\n }\n }\n emit SnapshotAccepted(status.domain, agent, snapPayload, snapSignature);\n }\n\n /// @inheritdoc InterfaceInbox\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 // Struct to get around stack too deep error.\n ReceiptInfo memory info;\n // This will revert if payload is not a receipt\n Receipt rcpt = rcptPayload.castToReceipt();\n // This will revert if the receipt signer is not a known Notary\n (info.rcptNotaryStatus, info.notary) = _verifyReceipt(rcpt, rcptSignature);\n // Receipt Notary needs to be Active\n info.rcptNotaryStatus.verifyActive();\n info.attNonce = IExecutionHub(destination).getAttestationNonce(rcpt.snapshotRoot());\n if (info.attNonce == 0) revert IncorrectSnapshotRoot();\n // Attestation Notary domain needs to match the destination domain\n info.attNotaryStatus = IAgentManager(agentManager).agentStatus(rcpt.attNotary());\n if (info.attNotaryStatus.domain != rcpt.destination()) revert IncorrectAgentDomain();\n // Check that the correct tip values for the message were provided\n _verifyReceiptTips(rcpt.messageHash(), paddedTips, headerHash, bodyHash);\n // Store Notary signature for the Receipt\n uint256 sigIndex = _saveSignature(rcptSignature);\n // This will revert if Receipt Notary is in Dispute\n wasAccepted = InterfaceSummit(summit).acceptReceipt({\n rcptNotaryIndex: info.rcptNotaryStatus.index,\n attNotaryIndex: info.attNotaryStatus.index,\n sigIndex: sigIndex,\n attNonce: info.attNonce,\n paddedTips: paddedTips,\n rcptPayload: rcptPayload\n });\n if (wasAccepted) {\n emit ReceiptAccepted(info.rcptNotaryStatus.domain, info.notary, rcptPayload, rcptSignature);\n }\n }\n\n /// @inheritdoc InterfaceInbox\n function submitReceiptReport(bytes memory rcptPayload, bytes memory rcptSignature, bytes memory rrSignature)\n external\n returns (bool wasAccepted)\n {\n // This will revert if payload is not a receipt\n Receipt rcpt = rcptPayload.castToReceipt();\n // This will revert if the receipt signer is not a known Guard\n (AgentStatus memory guardStatus,) = _verifyReceiptReport(rcpt, rrSignature);\n // Guard needs to be Active\n guardStatus.verifyActive();\n // This will revert if report signer is not a known Notary\n (AgentStatus memory notaryStatus,) = _verifyReceipt(rcpt, rcptSignature);\n // Notary needs to be Active/Unstaking\n notaryStatus.verifyActiveUnstaking();\n _saveReport(rcptPayload, rrSignature);\n // This will revert if either actor is already in dispute\n IAgentManager(agentManager).openDispute(guardStatus.index, notaryStatus.index);\n return true;\n }\n\n /// @inheritdoc InterfaceInbox\n function passReceipt(uint32 attNotaryIndex, uint32 attNonce, uint256 paddedTips, bytes memory rcptPayload)\n external\n returns (bool wasAccepted)\n {\n // Only Destination can pass receipts\n if (msg.sender != destination) revert CallerNotDestination();\n return InterfaceSummit(summit).acceptReceipt({\n rcptNotaryIndex: attNotaryIndex,\n attNotaryIndex: attNotaryIndex,\n sigIndex: type(uint256).max,\n attNonce: attNonce,\n paddedTips: paddedTips,\n rcptPayload: rcptPayload\n });\n }\n\n // ══════════════════════════════════════════ VERIFY AGENT STATEMENTS ══════════════════════════════════════════════\n\n /// @inheritdoc InterfaceInbox\n function verifyAttestation(bytes memory attPayload, bytes memory attSignature)\n external\n returns (bool isValidAttestation)\n {\n // This will revert if payload is not an attestation\n Attestation att = attPayload.castToAttestation();\n // This will revert if the attestation signer is not a known Notary\n (AgentStatus memory status, address notary) = _verifyAttestation(att, attSignature);\n // Notary needs to be Active/Unstaking\n status.verifyActiveUnstaking();\n isValidAttestation = ISnapshotHub(summit).isValidAttestation(attPayload);\n if (!isValidAttestation) {\n emit InvalidAttestation(attPayload, attSignature);\n IAgentManager(agentManager).slashAgent(status.domain, notary, msg.sender);\n }\n }\n\n /// @inheritdoc InterfaceInbox\n function verifyAttestationReport(bytes memory attPayload, bytes memory arSignature)\n external\n returns (bool isValidReport)\n {\n // This will revert if payload is not an attestation\n Attestation att = attPayload.castToAttestation();\n // This will revert if the report signer is not a known Guard\n (AgentStatus memory status, address guard) = _verifyAttestationReport(att, arSignature);\n // Guard needs to be Active/Unstaking\n status.verifyActiveUnstaking();\n // Report is valid IF AND ONLY IF the reported attestation in invalid\n isValidReport = !ISnapshotHub(summit).isValidAttestation(attPayload);\n if (!isValidReport) {\n emit InvalidAttestationReport(attPayload, arSignature);\n IAgentManager(agentManager).slashAgent(status.domain, guard, msg.sender);\n }\n }\n\n // ══════════════════════════════════════════════ INTERNAL VIEWS ═══════════════════════════════════════════════════\n\n /// @dev Verifies that tips proof matches the message hash.\n function _verifyReceiptTips(bytes32 msgHash, uint256 paddedTips, bytes32 headerHash, bytes32 bodyHash)\n internal\n pure\n {\n Tips tips = TipsLib.wrapPadded(paddedTips);\n // full message leaf is (header, baseMessage), while base message leaf is (tips, remainingBody).\n if (MerkleMath.getParent(headerHash, MerkleMath.getParent(tips.leaf(), bodyHash)) != msgHash) {\n revert IncorrectTipsProof();\n }\n }\n}\n","language":"Solidity","languageVersion":"0.8.17","compilerVersion":"0.8.17","compilerOptions":"--combined-json bin,bin-runtime,srcmap,srcmap-runtime,abi,userdoc,devdoc,metadata,hashes --optimize --optimize-runs 10000 --allow-paths ., ./, ../","srcMap":"60997:34153:0:-:0;;;;;;;;;;;;;;;-1:-1:-1;;;60997:34153:0;;;;;;;;;;;;;;;;;","srcMapRuntime":"60997: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/Inbox.sol\":\"SafeCast\"},\"evmVersion\":\"london\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\"},\"optimizer\":{\"enabled\":true,\"runs\":10000},\"remappings\":[]},\"sources\":{\"solidity/Inbox.sol\":{\"keccak256\":\"0x9b516081a036814c0169e20e484d4a5499066b7a6f48fada952b5e844a1ca3e5\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://32bde393b3f24ef4307d9626d4143f337b3c0bd34e17bb969fd5a15221d96987\",\"dweb:/ipfs/QmTkt2XZRtgsbSpmsVQUM3c4ebETQoDVYbmEV9yheBghnr\"]}},\"version\":1}"},"hashes":{}},"solidity/Inbox.sol:SignedMath":{"code":"0x60566037600b82828239805160001a607314602a57634e487b7160e01b600052600060045260246000fd5b30600052607381538281f3fe73000000000000000000000000000000000000000030146080604052600080fdfea26469706673582212209aa6a44ba95a1b054860d0738ccdca68e2f432b06ad18c93c2f05d45a041840d64736f6c63430008110033","runtime-code":"0x73000000000000000000000000000000000000000030146080604052600080fdfea26469706673582212209aa6a44ba95a1b054860d0738ccdca68e2f432b06ad18c93c2f05d45a041840d64736f6c63430008110033","info":{"source":"// SPDX-License-Identifier: MIT\npragma solidity =0.8.17 ^0.8.0 ^0.8.1 ^0.8.2;\n\n// contracts/events/InboxEvents.sol\n\nabstract contract InboxEvents {\n /**\n * @notice Emitted when a snapshot is accepted by the Summit contract.\n * @param domain Domain where the signed Agent is active (ZERO for Guards)\n * @param agent Agent who signed the snapshot\n * @param snapPayload Raw payload with snapshot data\n * @param snapSignature Agent signature for the snapshot\n */\n event SnapshotAccepted(uint32 indexed domain, address indexed agent, bytes snapPayload, bytes snapSignature);\n\n /**\n * @notice Emitted when a snapshot is accepted by the Summit contract.\n * @param domain Domain where the signed Notary is active\n * @param notary Notary who signed the attestation\n * @param rcptPayload Raw payload with receipt data\n * @param rcptSignature Notary signature for the receipt\n */\n event ReceiptAccepted(uint32 domain, address notary, bytes rcptPayload, bytes rcptSignature);\n\n /**\n * @notice Emitted when a proof of invalid attestation is submitted.\n * @param attPayload Raw payload with Attestation data\n * @param attSignature Notary signature for the attestation\n */\n event InvalidAttestation(bytes attPayload, bytes attSignature);\n\n /**\n * @notice Emitted when a proof of invalid attestation report is submitted.\n * @param arPayload Raw payload with report data\n * @param arSignature Guard signature for the report\n */\n event InvalidAttestationReport(bytes arPayload, bytes arSignature);\n}\n\n// contracts/events/StatementInboxEvents.sol\n\nabstract contract StatementInboxEvents {\n // ════════════════════════════════════════════ STATEMENT ACCEPTED ═════════════════════════════════════════════════\n\n /**\n * @notice Emitted when a snapshot is accepted by the Destination contract.\n * @param domain Domain where the signed Notary is active\n * @param notary Notary who signed the attestation\n * @param attPayload Raw payload with attestation data\n * @param attSignature Notary signature for the attestation\n */\n event AttestationAccepted(uint32 domain, address notary, bytes attPayload, bytes attSignature);\n\n // ═════════════════════════════════════════ INVALID STATEMENT PROVED ══════════════════════════════════════════════\n\n /**\n * @notice Emitted when a proof of invalid receipt statement is submitted.\n * @param rcptPayload Raw payload with the receipt statement\n * @param rcptSignature Notary signature for the receipt statement\n */\n event InvalidReceipt(bytes rcptPayload, bytes rcptSignature);\n\n /**\n * @notice Emitted when a proof of invalid receipt report is submitted.\n * @param rrPayload Raw payload with report data\n * @param rrSignature Guard signature for the report\n */\n event InvalidReceiptReport(bytes rrPayload, bytes rrSignature);\n\n /**\n * @notice Emitted when a proof of invalid state in the signed attestation is submitted.\n * @param stateIndex Index of invalid state in the snapshot\n * @param statePayload Raw payload with state data\n * @param attPayload Raw payload with Attestation data for snapshot\n * @param attSignature Notary signature for the attestation\n */\n event InvalidStateWithAttestation(uint8 stateIndex, bytes statePayload, bytes attPayload, bytes attSignature);\n\n /**\n * @notice Emitted when a proof of invalid state in the signed snapshot is submitted.\n * @param stateIndex Index of invalid state in the snapshot\n * @param snapPayload Raw payload with snapshot data\n * @param snapSignature Agent signature for the snapshot\n */\n event InvalidStateWithSnapshot(uint8 stateIndex, bytes snapPayload, bytes snapSignature);\n\n /**\n * @notice Emitted when a proof of invalid state report is submitted.\n * @param srPayload Raw payload with report data\n * @param srSignature Guard signature for the report\n */\n event InvalidStateReport(bytes srPayload, bytes srSignature);\n}\n\n// contracts/interfaces/ISnapshotHub.sol\n\ninterface ISnapshotHub {\n /**\n * @notice Check that a given attestation is valid: matches the historical attestation\n * derived from an accepted Notary snapshot.\n * @dev Will revert if any of these is true:\n * - Attestation payload is not properly formatted.\n * @param attPayload Raw payload with attestation data\n * @return isValid Whether the provided attestation is valid\n */\n function isValidAttestation(bytes memory attPayload) external view returns (bool isValid);\n\n /**\n * @notice Returns saved attestation with the given nonce.\n * @dev Reverts if attestation with given nonce hasn't been created yet.\n * @param attNonce Nonce for the attestation\n * @return attPayload Raw payload with formatted Attestation data\n * @return agentRoot Agent root hash used for the attestation\n * @return snapGas Snapshot gas data used for the attestation\n */\n function getAttestation(uint32 attNonce)\n external\n view\n returns (bytes memory attPayload, bytes32 agentRoot, uint256[] memory snapGas);\n\n /**\n * @notice Returns the state with the highest known nonce submitted by a given Agent.\n * @param origin Domain of origin chain\n * @param agent Agent address\n * @return statePayload Raw payload with agent's latest state for origin\n */\n function getLatestAgentState(uint32 origin, address agent) external view returns (bytes memory statePayload);\n\n /**\n * @notice Returns latest saved attestation for a Notary.\n * @param notary Notary address\n * @return attPayload Raw payload with formatted Attestation data\n * @return agentRoot Agent root hash used for the attestation\n * @return snapGas Snapshot gas data used for the attestation\n */\n function getLatestNotaryAttestation(address notary)\n external\n view\n returns (bytes memory attPayload, bytes32 agentRoot, uint256[] memory snapGas);\n\n /**\n * @notice Returns Guard snapshot from the list of all accepted Guard snapshots.\n * @dev Reverts if snapshot with given index hasn't been accepted yet.\n * @param index Snapshot index in the list of all Guard snapshots\n * @return snapPayload Raw payload with Guard snapshot\n * @return snapSignature Raw payload with Guard signature for snapshot\n */\n function getGuardSnapshot(uint256 index)\n external\n view\n returns (bytes memory snapPayload, bytes memory snapSignature);\n\n /**\n * @notice Returns Notary snapshot from the list of all accepted Guard snapshots.\n * @dev Reverts if snapshot with given index hasn't been accepted yet.\n * @param index Snapshot index in the list of all Notary snapshots\n * @return snapPayload Raw payload with Notary snapshot\n * @return snapSignature Raw payload with Notary signature for snapshot\n */\n function getNotarySnapshot(uint256 index)\n external\n view\n returns (bytes memory snapPayload, bytes memory snapSignature);\n\n /**\n * @notice Returns Notary snapshot that was used for creating a given attestation.\n * @dev Reverts if any of these is true:\n * - Attestation payload is not properly formatted.\n * - Attestation is invalid (doesn't have a matching Notary snapshot).\n * @param attPayload Raw payload with attestation data\n * @return snapPayload Raw payload with Notary snapshot\n * @return snapSignature Raw payload with Notary signature for snapshot\n */\n function getNotarySnapshot(bytes memory attPayload)\n external\n view\n returns (bytes memory snapPayload, bytes memory snapSignature);\n\n /**\n * @notice Returns proof of inclusion of (root, origin) fields of a given snapshot's state\n * into the Snapshot Merkle Tree for a given attestation.\n * @dev Reverts if any of these is true:\n * - Attestation with given nonce hasn't been created yet.\n * - State index is out of range of snapshot list.\n * @param attNonce Nonce for the attestation\n * @param stateIndex Index of state in the attestation's snapshot\n * @return snapProof The snapshot proof\n */\n function getSnapshotProof(uint32 attNonce, uint8 stateIndex) external view returns (bytes32[] memory snapProof);\n}\n\n// contracts/interfaces/IStateHub.sol\n\ninterface IStateHub {\n /**\n * @notice Check that a given state is valid: matches the historical state of Origin contract.\n * Note: any Agent including an invalid state in their snapshot will be slashed\n * upon providing the snapshot and agent signature for it to Origin contract.\n * @dev Will revert if any of these is true:\n * - State payload is not properly formatted.\n * @param statePayload Raw payload with state data\n * @return isValid Whether the provided state is valid\n */\n function isValidState(bytes memory statePayload) external view returns (bool isValid);\n\n /**\n * @notice Returns the amount of saved states so far.\n * @dev This includes the initial state of \"empty Origin Merkle Tree\".\n */\n function statesAmount() external view returns (uint256);\n\n /**\n * @notice Suggest the data (state after latest sent message) to sign for an Agent.\n * Note: signing the suggested state data will will never lead to slashing of the actor,\n * assuming they have confirmed that the block, which number is included in the data,\n * is not subject to reorganization (which is different for every observed chain).\n * @return statePayload Raw payload with the latest state data\n */\n function suggestLatestState() external view returns (bytes memory statePayload);\n\n /**\n * @notice Given the historical nonce, suggest the state data to sign for an Agent.\n * Note: signing the suggested state data will will never lead to slashing of the actor,\n * assuming they have confirmed that the block, which number is included in the data,\n * is not subject to reorganization (which is different for every observed chain).\n * @param nonce Historical nonce to form a state\n * @return statePayload Raw payload with historical state data\n */\n function suggestState(uint32 nonce) external view returns (bytes memory statePayload);\n}\n\n// contracts/interfaces/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/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// node_modules/@openzeppelin/contracts/utils/math/Math.sol\n\n// OpenZeppelin Contracts (last updated v4.9.0) (utils/math/Math.sol)\n\n/**\n * @dev Standard math utilities missing in the Solidity language.\n */\nlibrary Math {\n enum Rounding {\n Down, // Toward negative infinity\n Up, // Toward infinity\n Zero // Toward zero\n }\n\n /**\n * @dev Returns the largest of two numbers.\n */\n function max(uint256 a, uint256 b) internal pure returns (uint256) {\n return a \u003e b ? a : b;\n }\n\n /**\n * @dev Returns the smallest of two numbers.\n */\n function min(uint256 a, uint256 b) internal pure returns (uint256) {\n return a \u003c b ? a : b;\n }\n\n /**\n * @dev Returns the average of two numbers. The result is rounded towards\n * zero.\n */\n function average(uint256 a, uint256 b) internal pure returns (uint256) {\n // (a + b) / 2 can overflow.\n return (a \u0026 b) + (a ^ b) / 2;\n }\n\n /**\n * @dev Returns the ceiling of the division of two numbers.\n *\n * This differs from standard division with `/` in that it rounds up instead\n * of rounding down.\n */\n function ceilDiv(uint256 a, uint256 b) internal pure returns (uint256) {\n // (a + b - 1) / b can overflow on addition, so we distribute.\n return a == 0 ? 0 : (a - 1) / b + 1;\n }\n\n /**\n * @notice Calculates floor(x * y / denominator) with full precision. Throws if result overflows a uint256 or denominator == 0\n * @dev Original credit to Remco Bloemen under MIT license (https://xn--2-umb.com/21/muldiv)\n * with further edits by Uniswap Labs also under MIT license.\n */\n function mulDiv(uint256 x, uint256 y, uint256 denominator) internal pure returns (uint256 result) {\n unchecked {\n // 512-bit multiply [prod1 prod0] = x * y. Compute the product mod 2^256 and mod 2^256 - 1, then use\n // use the Chinese Remainder Theorem to reconstruct the 512 bit result. The result is stored in two 256\n // variables such that product = prod1 * 2^256 + prod0.\n uint256 prod0; // Least significant 256 bits of the product\n uint256 prod1; // Most significant 256 bits of the product\n assembly {\n let mm := mulmod(x, y, not(0))\n prod0 := mul(x, y)\n prod1 := sub(sub(mm, prod0), lt(mm, prod0))\n }\n\n // Handle non-overflow cases, 256 by 256 division.\n if (prod1 == 0) {\n // Solidity will revert if denominator == 0, unlike the div opcode on its own.\n // The surrounding unchecked block does not change this fact.\n // See https://docs.soliditylang.org/en/latest/control-structures.html#checked-or-unchecked-arithmetic.\n return prod0 / denominator;\n }\n\n // Make sure the result is less than 2^256. Also prevents denominator == 0.\n require(denominator \u003e prod1, \"Math: mulDiv overflow\");\n\n ///////////////////////////////////////////////\n // 512 by 256 division.\n ///////////////////////////////////////////////\n\n // Make division exact by subtracting the remainder from [prod1 prod0].\n uint256 remainder;\n assembly {\n // Compute remainder using mulmod.\n remainder := mulmod(x, y, denominator)\n\n // Subtract 256 bit number from 512 bit number.\n prod1 := sub(prod1, gt(remainder, prod0))\n prod0 := sub(prod0, remainder)\n }\n\n // Factor powers of two out of denominator and compute largest power of two divisor of denominator. Always \u003e= 1.\n // See https://cs.stackexchange.com/q/138556/92363.\n\n // Does not overflow because the denominator cannot be zero at this stage in the function.\n uint256 twos = denominator \u0026 (~denominator + 1);\n assembly {\n // Divide denominator by twos.\n denominator := div(denominator, twos)\n\n // Divide [prod1 prod0] by twos.\n prod0 := div(prod0, twos)\n\n // Flip twos such that it is 2^256 / twos. If twos is zero, then it becomes one.\n twos := add(div(sub(0, twos), twos), 1)\n }\n\n // Shift in bits from prod1 into prod0.\n prod0 |= prod1 * twos;\n\n // Invert denominator mod 2^256. Now that denominator is an odd number, it has an inverse modulo 2^256 such\n // that denominator * inv = 1 mod 2^256. Compute the inverse by starting with a seed that is correct for\n // four bits. That is, denominator * inv = 1 mod 2^4.\n uint256 inverse = (3 * denominator) ^ 2;\n\n // Use the Newton-Raphson iteration to improve the precision. Thanks to Hensel's lifting lemma, this also works\n // in modular arithmetic, doubling the correct bits in each step.\n inverse *= 2 - denominator * inverse; // inverse mod 2^8\n inverse *= 2 - denominator * inverse; // inverse mod 2^16\n inverse *= 2 - denominator * inverse; // inverse mod 2^32\n inverse *= 2 - denominator * inverse; // inverse mod 2^64\n inverse *= 2 - denominator * inverse; // inverse mod 2^128\n inverse *= 2 - denominator * inverse; // inverse mod 2^256\n\n // Because the division is now exact we can divide by multiplying with the modular inverse of denominator.\n // This will give us the correct result modulo 2^256. Since the preconditions guarantee that the outcome is\n // less than 2^256, this is the final result. We don't need to compute the high bits of the result and prod1\n // is no longer required.\n result = prod0 * inverse;\n return result;\n }\n }\n\n /**\n * @notice Calculates x * y / denominator with full precision, following the selected rounding direction.\n */\n function mulDiv(uint256 x, uint256 y, uint256 denominator, Rounding rounding) internal pure returns (uint256) {\n uint256 result = mulDiv(x, y, denominator);\n if (rounding == Rounding.Up \u0026\u0026 mulmod(x, y, denominator) \u003e 0) {\n result += 1;\n }\n return result;\n }\n\n /**\n * @dev Returns the square root of a number. If the number is not a perfect square, the value is rounded down.\n *\n * Inspired by Henry S. Warren, Jr.'s \"Hacker's Delight\" (Chapter 11).\n */\n function sqrt(uint256 a) internal pure returns (uint256) {\n if (a == 0) {\n return 0;\n }\n\n // For our first guess, we get the biggest power of 2 which is smaller than the square root of the target.\n //\n // We know that the \"msb\" (most significant bit) of our target number `a` is a power of 2 such that we have\n // `msb(a) \u003c= a \u003c 2*msb(a)`. This value can be written `msb(a)=2**k` with `k=log2(a)`.\n //\n // This can be rewritten `2**log2(a) \u003c= a \u003c 2**(log2(a) + 1)`\n // → `sqrt(2**k) \u003c= sqrt(a) \u003c sqrt(2**(k+1))`\n // → `2**(k/2) \u003c= sqrt(a) \u003c 2**((k+1)/2) \u003c= 2**(k/2 + 1)`\n //\n // Consequently, `2**(log2(a) / 2)` is a good first approximation of `sqrt(a)` with at least 1 correct bit.\n uint256 result = 1 \u003c\u003c (log2(a) \u003e\u003e 1);\n\n // At this point `result` is an estimation with one bit of precision. We know the true value is a uint128,\n // since it is the square root of a uint256. Newton's method converges quadratically (precision doubles at\n // every iteration). We thus need at most 7 iteration to turn our partial result with one bit of precision\n // into the expected uint128 result.\n unchecked {\n result = (result + a / result) \u003e\u003e 1;\n result = (result + a / result) \u003e\u003e 1;\n result = (result + a / result) \u003e\u003e 1;\n result = (result + a / result) \u003e\u003e 1;\n result = (result + a / result) \u003e\u003e 1;\n result = (result + a / result) \u003e\u003e 1;\n result = (result + a / result) \u003e\u003e 1;\n return min(result, a / result);\n }\n }\n\n /**\n * @notice Calculates sqrt(a), following the selected rounding direction.\n */\n function sqrt(uint256 a, Rounding rounding) internal pure returns (uint256) {\n unchecked {\n uint256 result = sqrt(a);\n return result + (rounding == Rounding.Up \u0026\u0026 result * result \u003c a ? 1 : 0);\n }\n }\n\n /**\n * @dev Return the log in base 2, rounded down, of a positive value.\n * Returns 0 if given 0.\n */\n function log2(uint256 value) internal pure returns (uint256) {\n uint256 result = 0;\n unchecked {\n if (value \u003e\u003e 128 \u003e 0) {\n value \u003e\u003e= 128;\n result += 128;\n }\n if (value \u003e\u003e 64 \u003e 0) {\n value \u003e\u003e= 64;\n result += 64;\n }\n if (value \u003e\u003e 32 \u003e 0) {\n value \u003e\u003e= 32;\n result += 32;\n }\n if (value \u003e\u003e 16 \u003e 0) {\n value \u003e\u003e= 16;\n result += 16;\n }\n if (value \u003e\u003e 8 \u003e 0) {\n value \u003e\u003e= 8;\n result += 8;\n }\n if (value \u003e\u003e 4 \u003e 0) {\n value \u003e\u003e= 4;\n result += 4;\n }\n if (value \u003e\u003e 2 \u003e 0) {\n value \u003e\u003e= 2;\n result += 2;\n }\n if (value \u003e\u003e 1 \u003e 0) {\n result += 1;\n }\n }\n return result;\n }\n\n /**\n * @dev Return the log in base 2, following the selected rounding direction, of a positive value.\n * Returns 0 if given 0.\n */\n function log2(uint256 value, Rounding rounding) internal pure returns (uint256) {\n unchecked {\n uint256 result = log2(value);\n return result + (rounding == Rounding.Up \u0026\u0026 1 \u003c\u003c result \u003c value ? 1 : 0);\n }\n }\n\n /**\n * @dev Return the log in base 10, rounded down, of a positive value.\n * Returns 0 if given 0.\n */\n function log10(uint256 value) internal pure returns (uint256) {\n uint256 result = 0;\n unchecked {\n if (value \u003e= 10 ** 64) {\n value /= 10 ** 64;\n result += 64;\n }\n if (value \u003e= 10 ** 32) {\n value /= 10 ** 32;\n result += 32;\n }\n if (value \u003e= 10 ** 16) {\n value /= 10 ** 16;\n result += 16;\n }\n if (value \u003e= 10 ** 8) {\n value /= 10 ** 8;\n result += 8;\n }\n if (value \u003e= 10 ** 4) {\n value /= 10 ** 4;\n result += 4;\n }\n if (value \u003e= 10 ** 2) {\n value /= 10 ** 2;\n result += 2;\n }\n if (value \u003e= 10 ** 1) {\n result += 1;\n }\n }\n return result;\n }\n\n /**\n * @dev Return the log in base 10, following the selected rounding direction, of a positive value.\n * Returns 0 if given 0.\n */\n function log10(uint256 value, Rounding rounding) internal pure returns (uint256) {\n unchecked {\n uint256 result = log10(value);\n return result + (rounding == Rounding.Up \u0026\u0026 10 ** result \u003c value ? 1 : 0);\n }\n }\n\n /**\n * @dev Return the log in base 256, rounded down, of a positive value.\n * Returns 0 if given 0.\n *\n * Adding one to the result gives the number of pairs of hex symbols needed to represent `value` as a hex string.\n */\n function log256(uint256 value) internal pure returns (uint256) {\n uint256 result = 0;\n unchecked {\n if (value \u003e\u003e 128 \u003e 0) {\n value \u003e\u003e= 128;\n result += 16;\n }\n if (value \u003e\u003e 64 \u003e 0) {\n value \u003e\u003e= 64;\n result += 8;\n }\n if (value \u003e\u003e 32 \u003e 0) {\n value \u003e\u003e= 32;\n result += 4;\n }\n if (value \u003e\u003e 16 \u003e 0) {\n value \u003e\u003e= 16;\n result += 2;\n }\n if (value \u003e\u003e 8 \u003e 0) {\n result += 1;\n }\n }\n return result;\n }\n\n /**\n * @dev Return the log in base 256, following the selected rounding direction, of a positive value.\n * Returns 0 if given 0.\n */\n function log256(uint256 value, Rounding rounding) internal pure returns (uint256) {\n unchecked {\n uint256 result = log256(value);\n return result + (rounding == Rounding.Up \u0026\u0026 1 \u003c\u003c (result \u003c\u003c 3) \u003c value ? 1 : 0);\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/utils/math/SignedMath.sol\n\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/math/SignedMath.sol)\n\n/**\n * @dev Standard signed math utilities missing in the Solidity language.\n */\nlibrary SignedMath {\n /**\n * @dev Returns the largest of two signed numbers.\n */\n function max(int256 a, int256 b) internal pure returns (int256) {\n return a \u003e b ? a : b;\n }\n\n /**\n * @dev Returns the smallest of two signed numbers.\n */\n function min(int256 a, int256 b) internal pure returns (int256) {\n return a \u003c b ? a : b;\n }\n\n /**\n * @dev Returns the average of two signed numbers without overflow.\n * The result is rounded towards zero.\n */\n function average(int256 a, int256 b) internal pure returns (int256) {\n // Formula from the book \"Hacker's Delight\"\n int256 x = (a \u0026 b) + ((a ^ b) \u003e\u003e 1);\n return x + (int256(uint256(x) \u003e\u003e 255) \u0026 (a ^ b));\n }\n\n /**\n * @dev Returns the absolute unsigned value of a signed value.\n */\n function abs(int256 n) internal pure returns (uint256) {\n unchecked {\n // must be unchecked in order to support `n = type(int256).min`\n return uint256(n \u003e= 0 ? n : -n);\n }\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// 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/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/InterfaceSummit.sol\n\ninterface InterfaceSummit {\n // ══════════════════════════════════════════ ACCEPT AGENT STATEMENTS ══════════════════════════════════════════════\n\n /**\n * @notice Accepts a receipt, which local `AgentManager` verified to have been signed by an active Notary.\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 * - Notary who signed the receipt is referenced as the \"Receipt Notary\".\n * - Notary who signed the attestation on destination chain is referenced as the \"Attestation Notary\".\n * \u003e Will revert if any of these is true:\n * \u003e - Called by anyone other than local `AgentManager`.\n * \u003e - Receipt body payload is not properly formatted.\n * \u003e - Receipt signer is in Dispute.\n * \u003e - Receipt's snapshot root is unknown.\n * @param rcptNotaryIndex Index of Receipt Notary in Agent Merkle Tree\n * @param attNotaryIndex Index of Attestation Notary in Agent Merkle Tree\n * @param sigIndex Index of stored Notary signature\n * @param attNonce Nonce of the attestation used for proving the executed message\n * @param paddedTips Padded encoded paid tips information\n * @param rcptPayload Raw payload with message execution receipt\n * @return wasAccepted Whether the receipt was accepted\n */\n function acceptReceipt(\n uint32 rcptNotaryIndex,\n uint32 attNotaryIndex,\n uint256 sigIndex,\n uint32 attNonce,\n uint256 paddedTips,\n bytes memory rcptPayload\n ) external returns (bool wasAccepted);\n\n /**\n * @notice Accepts a snapshot, which local `AgentManager` verified to have been signed by an active Guard.\n * \u003e Snapshot is a list of states for a set of Origin contracts residing on any of the chains.\n * All the states in the Guard-signed snapshot become available for Notary signing.\n * \u003e Will revert if any of these is true:\n * \u003e - Called by anyone other than local `AgentManager`.\n * \u003e - Snapshot payload is not properly formatted.\n * \u003e - Snapshot contains a state older then the Guard has previously submitted.\n * @param guardIndex Index of Guard in Agent Merkle Tree\n * @param sigIndex Index of stored Agent signature\n * @param snapPayload Raw payload with snapshot data\n */\n function acceptGuardSnapshot(uint32 guardIndex, uint256 sigIndex, bytes memory snapPayload) external;\n\n /**\n * @notice Accepts a snapshot, which local `AgentManager` verified to have been signed by an active Notary.\n * \u003e Snapshot is a list of states for a set of Origin contracts residing on any of the chains.\n * Snapshot Merkle Root is calculated and saved for valid snapshots, i.e.\n * snapshots which are only using states previously submitted by any of the Guards.\n * - Notary could use states singed by the same of different Guards 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 - Called by anyone other than local `AgentManager`.\n * \u003e - Snapshot payload is not properly formatted.\n * \u003e - Snapshot contains a state older then the Notary has previously submitted.\n * \u003e - Snapshot contains a state that no Guard has previously submitted.\n * @param notaryIndex Index of Notary in Agent Merkle Tree\n * @param sigIndex Index of stored Agent signature\n * @param agentRoot Current root of the Agent Merkle Tree\n * @param snapPayload Raw payload with snapshot data\n * @return attPayload Raw payload with data for attestation derived from Notary snapshot.\n */\n function acceptNotarySnapshot(uint32 notaryIndex, uint256 sigIndex, bytes32 agentRoot, bytes memory snapPayload)\n external\n returns (bytes memory attPayload);\n\n // ════════════════════════════════════════════════ TIPS LOGIC ═════════════════════════════════════════════════════\n\n /**\n * @notice Distributes tips using the first Receipt from the \"receipt quarantine queue\".\n * Possible scenarios:\n * - Receipt queue is empty =\u003e does nothing\n * - Receipt optimistic period is not over =\u003e does nothing\n * - Either of Notaries present in Receipt was slashed =\u003e receipt is deleted from the queue\n * - Either of Notaries present in Receipt in Dispute =\u003e receipt is moved to the end of queue\n * - None of the above =\u003e receipt tips are distributed\n * @dev Returned value makes it possible to do the following: `while (distributeTips()) {}`\n * @return queuePopped Whether the first element was popped from the queue\n */\n function distributeTips() external returns (bool queuePopped);\n\n /**\n * @notice Withdraws locked base message tips from requested domain Origin to the recipient.\n * This is done by a call to a local Origin contract, or by a manager message to the remote chain.\n * @dev This will revert, if the pending balance of origin tips (earned-claimed) is lower than requested.\n * @param origin Domain of chain to withdraw tips on\n * @param amount Amount of tips to withdraw\n */\n function withdrawTips(uint32 origin, uint256 amount) external;\n\n // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════\n\n /**\n * @notice Returns earned and claimed tips for the actor.\n * Note: Tips for address(0) belong to the Treasury.\n * @param actor Address of the actor\n * @param origin Domain where the tips were initially paid\n * @return earned Total amount of origin tips the actor has earned so far\n * @return claimed Total amount of origin tips the actor has claimed so far\n */\n function actorTips(address actor, uint32 origin) external view returns (uint128 earned, uint128 claimed);\n\n /**\n * @notice Returns the amount of receipts in the \"Receipt Quarantine Queue\".\n */\n function receiptQueueLength() external view returns (uint256);\n\n /**\n * @notice Returns the state with the highest known nonce\n * submitted by any of the currently active Guards.\n * @param origin Domain of origin chain\n * @return statePayload Raw payload with latest active Guard state for origin\n */\n function getLatestState(uint32 origin) external view returns (bytes memory statePayload);\n}\n\n// node_modules/@openzeppelin/contracts/utils/Strings.sol\n\n// OpenZeppelin Contracts (last updated v4.9.0) (utils/Strings.sol)\n\n/**\n * @dev String operations.\n */\nlibrary Strings {\n bytes16 private constant _SYMBOLS = \"0123456789abcdef\";\n uint8 private constant _ADDRESS_LENGTH = 20;\n\n /**\n * @dev Converts a `uint256` to its ASCII `string` decimal representation.\n */\n function toString(uint256 value) internal pure returns (string memory) {\n unchecked {\n uint256 length = Math.log10(value) + 1;\n string memory buffer = new string(length);\n uint256 ptr;\n /// @solidity memory-safe-assembly\n assembly {\n ptr := add(buffer, add(32, length))\n }\n while (true) {\n ptr--;\n /// @solidity memory-safe-assembly\n assembly {\n mstore8(ptr, byte(mod(value, 10), _SYMBOLS))\n }\n value /= 10;\n if (value == 0) break;\n }\n return buffer;\n }\n }\n\n /**\n * @dev Converts a `int256` to its ASCII `string` decimal representation.\n */\n function toString(int256 value) internal pure returns (string memory) {\n return string(abi.encodePacked(value \u003c 0 ? \"-\" : \"\", toString(SignedMath.abs(value))));\n }\n\n /**\n * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation.\n */\n function toHexString(uint256 value) internal pure returns (string memory) {\n unchecked {\n return toHexString(value, Math.log256(value) + 1);\n }\n }\n\n /**\n * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length.\n */\n function toHexString(uint256 value, uint256 length) internal pure returns (string memory) {\n bytes memory buffer = new bytes(2 * length + 2);\n buffer[0] = \"0\";\n buffer[1] = \"x\";\n for (uint256 i = 2 * length + 1; i \u003e 1; --i) {\n buffer[i] = _SYMBOLS[value \u0026 0xf];\n value \u003e\u003e= 4;\n }\n require(value == 0, \"Strings: hex length insufficient\");\n return string(buffer);\n }\n\n /**\n * @dev Converts an `address` with fixed length of 20 bytes to its not checksummed ASCII `string` hexadecimal representation.\n */\n function toHexString(address addr) internal pure returns (string memory) {\n return toHexString(uint256(uint160(addr)), _ADDRESS_LENGTH);\n }\n\n /**\n * @dev Returns true if the two strings are equal.\n */\n function equal(string memory a, string memory b) internal pure returns (bool) {\n return keccak256(bytes(a)) == keccak256(bytes(b));\n }\n}\n\n// node_modules/@openzeppelin/contracts-upgradeable/utils/ContextUpgradeable.sol\n\n// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)\n\n/**\n * @dev Provides information about the current execution context, including the\n * sender of the transaction and its data. While these are generally available\n * via msg.sender and msg.data, they should not be accessed in such a direct\n * manner, since when dealing with meta-transactions the account sending and\n * paying for execution may not be the actual sender (as far as an application\n * is concerned).\n *\n * This contract is only required for intermediate, library-like contracts.\n */\nabstract contract ContextUpgradeable is Initializable {\n function __Context_init() internal onlyInitializing {\n }\n\n function __Context_init_unchained() internal onlyInitializing {\n }\n function _msgSender() internal view virtual returns (address) {\n return msg.sender;\n }\n\n function _msgData() internal view virtual returns (bytes calldata) {\n return msg.data;\n }\n\n /**\n * @dev This empty reserved space is put in place to allow future versions to add new\n * variables without shifting down storage in the inheritance chain.\n * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\n */\n uint256[50] private __gap;\n}\n\n// contracts/libs/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/utils/cryptography/ECDSA.sol\n\n// OpenZeppelin Contracts (last updated v4.9.0) (utils/cryptography/ECDSA.sol)\n\n/**\n * @dev Elliptic Curve Digital Signature Algorithm (ECDSA) operations.\n *\n * These functions can be used to verify that a message was signed by the holder\n * of the private keys of a given address.\n */\nlibrary ECDSA {\n enum RecoverError {\n NoError,\n InvalidSignature,\n InvalidSignatureLength,\n InvalidSignatureS,\n InvalidSignatureV // Deprecated in v4.8\n }\n\n function _throwError(RecoverError error) private pure {\n if (error == RecoverError.NoError) {\n return; // no error: do nothing\n } else if (error == RecoverError.InvalidSignature) {\n revert(\"ECDSA: invalid signature\");\n } else if (error == RecoverError.InvalidSignatureLength) {\n revert(\"ECDSA: invalid signature length\");\n } else if (error == RecoverError.InvalidSignatureS) {\n revert(\"ECDSA: invalid signature 's' value\");\n }\n }\n\n /**\n * @dev Returns the address that signed a hashed message (`hash`) with\n * `signature` or error string. This address can then be used for verification purposes.\n *\n * The `ecrecover` EVM opcode allows for malleable (non-unique) signatures:\n * this function rejects them by requiring the `s` value to be in the lower\n * half order, and the `v` value to be either 27 or 28.\n *\n * IMPORTANT: `hash` _must_ be the result of a hash operation for the\n * verification to be secure: it is possible to craft signatures that\n * recover to arbitrary addresses for non-hashed data. A safe way to ensure\n * this is by receiving a hash of the original message (which may otherwise\n * be too long), and then calling {toEthSignedMessageHash} on it.\n *\n * Documentation for signature generation:\n * - with https://web3js.readthedocs.io/en/v1.3.4/web3-eth-accounts.html#sign[Web3.js]\n * - with https://docs.ethers.io/v5/api/signer/#Signer-signMessage[ethers]\n *\n * _Available since v4.3._\n */\n function tryRecover(bytes32 hash, bytes memory signature) internal pure returns (address, RecoverError) {\n if (signature.length == 65) {\n bytes32 r;\n bytes32 s;\n uint8 v;\n // ecrecover takes the signature parameters, and the only way to get them\n // currently is to use assembly.\n /// @solidity memory-safe-assembly\n assembly {\n r := mload(add(signature, 0x20))\n s := mload(add(signature, 0x40))\n v := byte(0, mload(add(signature, 0x60)))\n }\n return tryRecover(hash, v, r, s);\n } else {\n return (address(0), RecoverError.InvalidSignatureLength);\n }\n }\n\n /**\n * @dev Returns the address that signed a hashed message (`hash`) with\n * `signature`. This address can then be used for verification purposes.\n *\n * The `ecrecover` EVM opcode allows for malleable (non-unique) signatures:\n * this function rejects them by requiring the `s` value to be in the lower\n * half order, and the `v` value to be either 27 or 28.\n *\n * IMPORTANT: `hash` _must_ be the result of a hash operation for the\n * verification to be secure: it is possible to craft signatures that\n * recover to arbitrary addresses for non-hashed data. A safe way to ensure\n * this is by receiving a hash of the original message (which may otherwise\n * be too long), and then calling {toEthSignedMessageHash} on it.\n */\n function recover(bytes32 hash, bytes memory signature) internal pure returns (address) {\n (address recovered, RecoverError error) = tryRecover(hash, signature);\n _throwError(error);\n return recovered;\n }\n\n /**\n * @dev Overload of {ECDSA-tryRecover} that receives the `r` and `vs` short-signature fields separately.\n *\n * See https://eips.ethereum.org/EIPS/eip-2098[EIP-2098 short signatures]\n *\n * _Available since v4.3._\n */\n function tryRecover(bytes32 hash, bytes32 r, bytes32 vs) internal pure returns (address, RecoverError) {\n bytes32 s = vs \u0026 bytes32(0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff);\n uint8 v = uint8((uint256(vs) \u003e\u003e 255) + 27);\n return tryRecover(hash, v, r, s);\n }\n\n /**\n * @dev Overload of {ECDSA-recover} that receives the `r and `vs` short-signature fields separately.\n *\n * _Available since v4.2._\n */\n function recover(bytes32 hash, bytes32 r, bytes32 vs) internal pure returns (address) {\n (address recovered, RecoverError error) = tryRecover(hash, r, vs);\n _throwError(error);\n return recovered;\n }\n\n /**\n * @dev Overload of {ECDSA-tryRecover} that receives the `v`,\n * `r` and `s` signature fields separately.\n *\n * _Available since v4.3._\n */\n function tryRecover(bytes32 hash, uint8 v, bytes32 r, bytes32 s) internal pure returns (address, RecoverError) {\n // EIP-2 still allows signature malleability for ecrecover(). Remove this possibility and make the signature\n // unique. Appendix F in the Ethereum Yellow paper (https://ethereum.github.io/yellowpaper/paper.pdf), defines\n // the valid range for s in (301): 0 \u003c s \u003c secp256k1n ÷ 2 + 1, and for v in (302): v ∈ {27, 28}. Most\n // signatures from current libraries generate a unique signature with an s-value in the lower half order.\n //\n // If your library generates malleable signatures, such as s-values in the upper range, calculate a new s-value\n // with 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141 - s1 and flip v from 27 to 28 or\n // vice versa. If your library also generates signatures with 0/1 for v instead 27/28, add 27 to v to accept\n // these malleable signatures as well.\n if (uint256(s) \u003e 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0) {\n return (address(0), RecoverError.InvalidSignatureS);\n }\n\n // If the signature is valid (and not malleable), return the signer address\n address signer = ecrecover(hash, v, r, s);\n if (signer == address(0)) {\n return (address(0), RecoverError.InvalidSignature);\n }\n\n return (signer, RecoverError.NoError);\n }\n\n /**\n * @dev Overload of {ECDSA-recover} that receives the `v`,\n * `r` and `s` signature fields separately.\n */\n function recover(bytes32 hash, uint8 v, bytes32 r, bytes32 s) internal pure returns (address) {\n (address recovered, RecoverError error) = tryRecover(hash, v, r, s);\n _throwError(error);\n return recovered;\n }\n\n /**\n * @dev Returns an Ethereum Signed Message, created from a `hash`. This\n * produces hash corresponding to the one signed with the\n * https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`]\n * JSON-RPC method as part of EIP-191.\n *\n * See {recover}.\n */\n function toEthSignedMessageHash(bytes32 hash) internal pure returns (bytes32 message) {\n // 32 is the length in bytes of hash,\n // enforced by the type signature above\n /// @solidity memory-safe-assembly\n assembly {\n mstore(0x00, \"\\x19Ethereum Signed Message:\\n32\")\n mstore(0x1c, hash)\n message := keccak256(0x00, 0x3c)\n }\n }\n\n /**\n * @dev Returns an Ethereum Signed Message, created from `s`. This\n * produces hash corresponding to the one signed with the\n * https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`]\n * JSON-RPC method as part of EIP-191.\n *\n * See {recover}.\n */\n function toEthSignedMessageHash(bytes memory s) internal pure returns (bytes32) {\n return keccak256(abi.encodePacked(\"\\x19Ethereum Signed Message:\\n\", Strings.toString(s.length), s));\n }\n\n /**\n * @dev Returns an Ethereum Signed Typed Data, created from a\n * `domainSeparator` and a `structHash`. This produces hash corresponding\n * to the one signed with the\n * https://eips.ethereum.org/EIPS/eip-712[`eth_signTypedData`]\n * JSON-RPC method as part of EIP-712.\n *\n * See {recover}.\n */\n function toTypedDataHash(bytes32 domainSeparator, bytes32 structHash) internal pure returns (bytes32 data) {\n /// @solidity memory-safe-assembly\n assembly {\n let ptr := mload(0x40)\n mstore(ptr, \"\\x19\\x01\")\n mstore(add(ptr, 0x02), domainSeparator)\n mstore(add(ptr, 0x22), structHash)\n data := keccak256(ptr, 0x42)\n }\n }\n\n /**\n * @dev Returns an Ethereum Signed Data with intended validator, created from a\n * `validator` and `data` according to the version 0 of EIP-191.\n *\n * See {recover}.\n */\n function toDataWithIntendedValidatorHash(address validator, bytes memory data) internal pure returns (bytes32) {\n return keccak256(abi.encodePacked(\"\\x19\\x00\", validator, data));\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/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/inbox/StatementInbox.sol\n\n// ══════════════════════════════ LIBRARY IMPORTS ══════════════════════════════\n\n// ═════════════════════════════ INTERNAL IMPORTS ══════════════════════════════\n\n// ═════════════════════════════ EXTERNAL IMPORTS ══════════════════════════════\n\n/// @notice `StatementInbox` is the entry point for all agent-signed statements. It verifies the\n/// agent signatures, and passes the unsigned statements to the contract to consume it via `acceptX` functions. Is is\n/// also used to verify the agent-signed statements and initiate the agent slashing, should the statement be invalid.\n/// `StatementInbox` is responsible for the following:\n/// - Accepting State and Receipt Reports to initiate a dispute between Guard and Notary.\n/// - Storing all the Guard Reports with the Guard signature leading to a dispute.\n/// - Verifying State/State Reports referencing the local chain and slashing the signer if statement is invalid.\n/// - Verifying Receipt/Receipt Reports referencing the local chain and slashing the signer if statement is invalid.\nabstract contract StatementInbox is MessagingBase, StatementInboxEvents, IStatementInbox {\n using AttestationLib for bytes;\n using ReceiptLib for bytes;\n using StateLib for bytes;\n using SnapshotLib for bytes;\n\n struct StoredReport {\n uint256 sigIndex;\n bytes statementPayload;\n }\n\n // ══════════════════════════════════════════════════ STORAGE ══════════════════════════════════════════════════════\n\n address public agentManager;\n address public origin;\n address public destination;\n\n // TODO: optimize this\n bytes[] internal _storedSignatures;\n StoredReport[] internal _storedReports;\n\n /// @dev gap for upgrade safety\n uint256[45] private __GAP; // solhint-disable-line var-name-mixedcase\n\n // ════════════════════════════════════════════════ INITIALIZER ════════════════════════════════════════════════════\n\n /// @dev Initializes the contract:\n /// - Sets up `msg.sender` as the owner of the contract.\n /// - Sets up `agentManager`, `origin`, and `destination`.\n // solhint-disable-next-line func-name-mixedcase\n function __StatementInbox_init(address agentManager_, address origin_, address destination_)\n internal\n onlyInitializing\n {\n agentManager = agentManager_;\n origin = origin_;\n destination = destination_;\n __Ownable2Step_init();\n }\n\n // ══════════════════════════════════════════ SUBMIT AGENT STATEMENTS ══════════════════════════════════════════════\n\n /// @inheritdoc IStatementInbox\n // solhint-disable-next-line ordering\n function submitStateReportWithSnapshot(\n uint8 stateIndex,\n bytes memory srSignature,\n bytes memory snapPayload,\n bytes memory snapSignature\n ) external returns (bool wasAccepted) {\n // This will revert if payload is not a snapshot\n Snapshot snapshot = snapPayload.castToSnapshot();\n // This will revert if the snapshot signer is not a known Notary\n (AgentStatus memory notaryStatus,) =\n _verifySnapshot({snapshot: snapshot, snapSignature: snapSignature, verifyNotary: true});\n // Notary needs to be Active/Unstaking\n notaryStatus.verifyActiveUnstaking();\n // Check if Notary is active on this chain\n _verifyNotaryDomain(notaryStatus.domain);\n // This will revert if state index is out of range\n State state = snapshot.state(stateIndex);\n // This will revert if the report signer is not an known Guard\n (AgentStatus memory guardStatus,) = _verifyStateReport(state, srSignature);\n // Check that Guard is active\n guardStatus.verifyActive();\n _saveReport(state.unwrap().clone(), srSignature);\n // This will revert if either actor is already in dispute\n IAgentManager(agentManager).openDispute(guardStatus.index, notaryStatus.index);\n return true;\n }\n\n /// @inheritdoc IStatementInbox\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 // This will revert if payload is not a snapshot\n Snapshot snapshot = snapPayload.castToSnapshot();\n // This will revert if state index is out of range\n State state = snapshot.state(stateIndex);\n // This will revert if the report signer is not an known Guard\n (AgentStatus memory guardStatus,) = _verifyStateReport(state, srSignature);\n // Check that Guard is active\n guardStatus.verifyActive();\n // This will revert if payload is not an attestation\n Attestation att = attPayload.castToAttestation();\n // This will revert if signer is not an known Notary\n (AgentStatus memory notaryStatus,) = _verifyAttestation(att, attSignature);\n // Notary needs to be Active/Unstaking\n notaryStatus.verifyActiveUnstaking();\n // Check if Notary is active on this chain\n _verifyNotaryDomain(notaryStatus.domain);\n if (snapshot.calculateRoot() != att.snapRoot()) revert IncorrectSnapshotRoot();\n _saveReport(state.unwrap().clone(), srSignature);\n // This will revert if either actor is already in dispute\n IAgentManager(agentManager).openDispute(guardStatus.index, notaryStatus.index);\n return true;\n }\n\n /// @inheritdoc IStatementInbox\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 // This will revert if payload is not a state\n State state = statePayload.castToState();\n // This will revert if the report signer is not an known Guard\n (AgentStatus memory guardStatus,) = _verifyStateReport(state, srSignature);\n // Check that Guard is active\n guardStatus.verifyActive();\n // This will revert if payload is not an attestation\n Attestation att = attPayload.castToAttestation();\n // This will revert if signer is not a known Notary\n (AgentStatus memory notaryStatus,) = _verifyAttestation(att, attSignature);\n // Notary needs to be Active/Unstaking\n notaryStatus.verifyActiveUnstaking();\n // Check if Notary is active on this chain\n _verifyNotaryDomain(notaryStatus.domain);\n // This will revert if any of these is true:\n // - Attestation root is not equal to Merkle Root derived from State and Snapshot Proof.\n // - Snapshot Proof's first element does not match the State metadata.\n // - Snapshot Proof length exceeds Snapshot tree Height.\n // - State index is out of range.\n _verifySnapshotMerkle(att, stateIndex, state, snapProof);\n _saveReport(statePayload, srSignature);\n // This will revert if either actor is already in dispute\n IAgentManager(agentManager).openDispute(guardStatus.index, notaryStatus.index);\n return true;\n }\n\n // ══════════════════════════════════════════ VERIFY AGENT STATEMENTS ══════════════════════════════════════════════\n\n /// @inheritdoc IStatementInbox\n function verifyReceipt(bytes memory rcptPayload, bytes memory rcptSignature)\n external\n returns (bool isValidReceipt)\n {\n // This will revert if payload is not a receipt\n Receipt rcpt = rcptPayload.castToReceipt();\n // This will revert if the attestation signer is not a known Notary\n (AgentStatus memory status, address notary) = _verifyReceipt(rcpt, rcptSignature);\n // Notary needs to be Active/Unstaking\n status.verifyActiveUnstaking();\n isValidReceipt = IExecutionHub(destination).isValidReceipt(rcptPayload);\n if (!isValidReceipt) {\n emit InvalidReceipt(rcptPayload, rcptSignature);\n IAgentManager(agentManager).slashAgent(status.domain, notary, msg.sender);\n }\n }\n\n /// @inheritdoc IStatementInbox\n function verifyReceiptReport(bytes memory rcptPayload, bytes memory rrSignature)\n external\n returns (bool isValidReport)\n {\n // This will revert if payload is not a receipt\n Receipt rcpt = rcptPayload.castToReceipt();\n // This will revert if the report signer is not a known Guard\n (AgentStatus memory status, address guard) = _verifyReceiptReport(rcpt, rrSignature);\n // Guard needs to be Active/Unstaking\n status.verifyActiveUnstaking();\n // Report is valid IF AND ONLY IF the reported receipt in invalid\n isValidReport = !IExecutionHub(destination).isValidReceipt(rcptPayload);\n if (!isValidReport) {\n emit InvalidReceiptReport(rcptPayload, rrSignature);\n IAgentManager(agentManager).slashAgent(status.domain, guard, msg.sender);\n }\n }\n\n /// @inheritdoc IStatementInbox\n function verifyStateWithAttestation(\n uint8 stateIndex,\n bytes memory snapPayload,\n bytes memory attPayload,\n bytes memory attSignature\n ) external returns (bool isValidState) {\n // This will revert if payload is not an attestation\n Attestation att = attPayload.castToAttestation();\n // This will revert if the attestation signer is not a known Notary\n (AgentStatus memory status, address notary) = _verifyAttestation(att, attSignature);\n // Notary needs to be Active/Unstaking\n status.verifyActiveUnstaking();\n // This will revert if payload is not a snapshot\n Snapshot snapshot = snapPayload.castToSnapshot();\n if (snapshot.calculateRoot() != att.snapRoot()) revert IncorrectSnapshotRoot();\n // This will revert if state does not refer to this chain\n bytes memory statePayload = snapshot.state(stateIndex).unwrap().clone();\n isValidState = IStateHub(origin).isValidState(statePayload);\n if (!isValidState) {\n emit InvalidStateWithAttestation(stateIndex, statePayload, attPayload, attSignature);\n IAgentManager(agentManager).slashAgent(status.domain, notary, msg.sender);\n }\n }\n\n /// @inheritdoc IStatementInbox\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 // This will revert if payload is not an attestation\n Attestation att = attPayload.castToAttestation();\n // This will revert if the attestation signer is not a known Notary\n (AgentStatus memory status, address notary) = _verifyAttestation(att, attSignature);\n // Notary needs to be Active/Unstaking\n status.verifyActiveUnstaking();\n // This will revert if payload is not a state\n State state = statePayload.castToState();\n // This will revert if any of these is true:\n // - Attestation root is not equal to Merkle Root derived from State and Snapshot Proof.\n // - Snapshot Proof's first element does not match the State metadata.\n // - Snapshot Proof length exceeds Snapshot tree Height.\n // - State index is out of range.\n _verifySnapshotMerkle(att, stateIndex, state, snapProof);\n // This will revert if state does not refer to this chain\n isValidState = IStateHub(origin).isValidState(statePayload);\n if (!isValidState) {\n emit InvalidStateWithAttestation(stateIndex, statePayload, attPayload, attSignature);\n IAgentManager(agentManager).slashAgent(status.domain, notary, msg.sender);\n }\n }\n\n /// @inheritdoc IStatementInbox\n function verifyStateWithSnapshot(uint8 stateIndex, bytes memory snapPayload, bytes memory snapSignature)\n external\n returns (bool isValidState)\n {\n // This will revert if payload is not a snapshot\n Snapshot snapshot = snapPayload.castToSnapshot();\n // This will revert if the snapshot signer is not a known Guard/Notary\n (AgentStatus memory status, address agent) =\n _verifySnapshot({snapshot: snapshot, snapSignature: snapSignature, verifyNotary: false});\n // Agent needs to be Active/Unstaking\n status.verifyActiveUnstaking();\n // This will revert if state does not refer to this chain\n isValidState = IStateHub(origin).isValidState(snapshot.state(stateIndex).unwrap().clone());\n if (!isValidState) {\n emit InvalidStateWithSnapshot(stateIndex, snapPayload, snapSignature);\n IAgentManager(agentManager).slashAgent(status.domain, agent, msg.sender);\n }\n }\n\n /// @inheritdoc IStatementInbox\n function verifyStateReport(bytes memory statePayload, bytes memory srSignature)\n external\n returns (bool isValidReport)\n {\n // This will revert if payload is not a state\n State state = statePayload.castToState();\n // This will revert if the report signer is not a known Guard\n (AgentStatus memory status, address guard) = _verifyStateReport(state, srSignature);\n // Guard needs to be Active/Unstaking\n status.verifyActiveUnstaking();\n // Report is valid IF AND ONLY IF the reported state in invalid\n // This will revert if the reported state does not refer to this chain\n isValidReport = !IStateHub(origin).isValidState(statePayload);\n if (!isValidReport) {\n emit InvalidStateReport(statePayload, srSignature);\n IAgentManager(agentManager).slashAgent(status.domain, guard, msg.sender);\n }\n }\n\n // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════\n\n /// @inheritdoc IStatementInbox\n function getReportsAmount() external view returns (uint256) {\n return _storedReports.length;\n }\n\n /// @inheritdoc IStatementInbox\n function getGuardReport(uint256 index)\n external\n view\n returns (bytes memory statementPayload, bytes memory reportSignature)\n {\n if (index \u003e= _storedReports.length) revert IndexOutOfRange();\n StoredReport memory storedReport = _storedReports[index];\n statementPayload = storedReport.statementPayload;\n reportSignature = _storedSignatures[storedReport.sigIndex];\n }\n\n /// @inheritdoc IStatementInbox\n function getStoredSignature(uint256 index) external view returns (bytes memory) {\n return _storedSignatures[index];\n }\n\n // ══════════════════════════════════════════════ INTERNAL LOGIC ═══════════════════════════════════════════════════\n\n /// @dev Saves the statement reported by Guard as invalid and the Guard Report signature.\n function _saveReport(bytes memory statementPayload, bytes memory reportSignature) internal {\n uint256 sigIndex = _saveSignature(reportSignature);\n _storedReports.push(StoredReport(sigIndex, statementPayload));\n }\n\n /// @dev Saves the signature and returns its index.\n function _saveSignature(bytes memory signature) internal returns (uint256 sigIndex) {\n sigIndex = _storedSignatures.length;\n _storedSignatures.push(signature);\n }\n\n // ═══════════════════════════════════════════════ AGENT CHECKS ════════════════════════════════════════════════════\n\n /**\n * @dev Recovers a signer from a hashed message, and a EIP-191 signature for it.\n * Will revert, if the signer is not a known agent.\n * @dev Agent flag could be any of these: Active/Unstaking/Resting/Fraudulent/Slashed\n * Further checks need to be performed in a caller function.\n * @param hashedStatement Hash of the statement that was signed by an Agent\n * @param signature Agent signature for the hashed statement\n * @return status Struct representing agent status:\n * - flag Unknown/Active/Unstaking/Resting/Fraudulent/Slashed\n * - domain Domain where agent is/was active\n * - index Index of agent in the Agent Merkle Tree\n * @return agent Agent that signed the statement\n */\n function _recoverAgent(bytes32 hashedStatement, bytes memory signature)\n internal\n view\n returns (AgentStatus memory status, address agent)\n {\n bytes32 ethSignedMsg = ECDSA.toEthSignedMessageHash(hashedStatement);\n agent = ECDSA.recover(ethSignedMsg, signature);\n status = IAgentManager(agentManager).agentStatus(agent);\n // Discard signature of unknown agents.\n // Further flag checks are supposed to be performed in a caller function.\n status.verifyKnown();\n }\n\n /// @dev Verifies that Notary signature is active on local domain.\n function _verifyNotaryDomain(uint32 notaryDomain) internal view {\n // Notary needs to be from the local domain (if contract is not deployed on Synapse Chain).\n // Or Notary could be from any domain (if contract is deployed on Synapse Chain).\n if (notaryDomain != localDomain \u0026\u0026 localDomain != synapseDomain) revert IncorrectAgentDomain();\n }\n\n // ════════════════════════════════════════ ATTESTATION RELATED CHECKS ═════════════════════════════════════════════\n\n /**\n * @dev Internal function to verify the signed attestation payload.\n * Reverts if any of these is true:\n * - Attestation signer is not a known Notary.\n * @param att Typed memory view over attestation payload\n * @param attSignature Notary signature for the attestation\n * @return status Struct representing agent status, see {_recoverAgent}\n * @return notary Notary that signed the snapshot\n */\n function _verifyAttestation(Attestation att, bytes memory attSignature)\n internal\n view\n returns (AgentStatus memory status, address notary)\n {\n // This will revert if signer is not a known agent\n (status, notary) = _recoverAgent(att.hashValid(), attSignature);\n // Attestation signer needs to be a Notary, not a Guard\n if (status.domain == 0) revert AgentNotNotary();\n }\n\n /**\n * @dev Internal function to verify the signed attestation report payload.\n * Reverts if any of these is true:\n * - Report signer is not a known Guard.\n * @param att Typed memory view over attestation payload that Guard reports as invalid\n * @param arSignature Guard signature for the \"invalid attestation\" report\n * @return status Struct representing guard status, see {_recoverAgent}\n * @return guard Guard that signed the report\n */\n function _verifyAttestationReport(Attestation att, bytes memory arSignature)\n internal\n view\n returns (AgentStatus memory status, address guard)\n {\n // This will revert if signer is not a known agent\n (status, guard) = _recoverAgent(att.hashInvalid(), arSignature);\n // Report signer needs to be a Guard, not a Notary\n if (status.domain != 0) revert AgentNotGuard();\n }\n\n // ══════════════════════════════════════════ RECEIPT RELATED CHECKS ═══════════════════════════════════════════════\n\n /**\n * @dev Internal function to verify the signed receipt payload.\n * Reverts if any of these is true:\n * - Receipt signer is not a known Notary.\n * @param rcpt Typed memory view over receipt payload\n * @param rcptSignature Notary signature for the receipt\n * @return status Struct representing agent status, see {_recoverAgent}\n * @return notary Notary that signed the snapshot\n */\n function _verifyReceipt(Receipt rcpt, bytes memory rcptSignature)\n internal\n view\n returns (AgentStatus memory status, address notary)\n {\n // This will revert if signer is not a known agent\n (status, notary) = _recoverAgent(rcpt.hashValid(), rcptSignature);\n // Receipt signer needs to be a Notary, not a Guard\n if (status.domain == 0) revert AgentNotNotary();\n }\n\n /**\n * @dev Internal function to verify the signed receipt report payload.\n * Reverts if any of these is true:\n * - Report signer is not a known Guard.\n * @param rcpt Typed memory view over receipt payload that Guard reports as invalid\n * @param rrSignature Guard signature for the \"invalid receipt\" report\n * @return status Struct representing guard status, see {_recoverAgent}\n * @return guard Guard that signed the report\n */\n function _verifyReceiptReport(Receipt rcpt, bytes memory rrSignature)\n internal\n view\n returns (AgentStatus memory status, address guard)\n {\n // This will revert if signer is not a known agent\n (status, guard) = _recoverAgent(rcpt.hashInvalid(), rrSignature);\n // Report signer needs to be a Guard, not a Notary\n if (status.domain != 0) revert AgentNotGuard();\n }\n\n // ═══════════════════════════════════════ STATE/SNAPSHOT RELATED CHECKS ═══════════════════════════════════════════\n\n /**\n * @dev Internal function to verify the signed snapshot report payload.\n * Reverts if any of these is true:\n * - Report signer is not a known Guard.\n * @param state Typed memory view over state payload that Guard reports as invalid\n * @param srSignature Guard signature for the report\n * @return status Struct representing guard status, see {_recoverAgent}\n * @return guard Guard that signed the report\n */\n function _verifyStateReport(State state, bytes memory srSignature)\n internal\n view\n returns (AgentStatus memory status, address guard)\n {\n // This will revert if signer is not a known agent\n (status, guard) = _recoverAgent(state.hashInvalid(), srSignature);\n // Report signer needs to be a Guard, not a Notary\n if (status.domain != 0) revert AgentNotGuard();\n }\n\n /**\n * @dev Internal function to verify the signed snapshot payload.\n * Reverts if any of these is true:\n * - Snapshot signer is not a known Agent.\n * - Snapshot signer is not a Notary (if verifyNotary is true).\n * @param snapshot Typed memory view over snapshot payload\n * @param snapSignature Agent signature for the snapshot\n * @param verifyNotary If true, snapshot signer needs to be a Notary, not a Guard\n * @return status Struct representing agent status, see {_recoverAgent}\n * @return agent Agent that signed the snapshot\n */\n function _verifySnapshot(Snapshot snapshot, bytes memory snapSignature, bool verifyNotary)\n internal\n view\n returns (AgentStatus memory status, address agent)\n {\n // This will revert if signer is not a known agent\n (status, agent) = _recoverAgent(snapshot.hashValid(), snapSignature);\n // If requested, snapshot signer needs to be a Notary, not a Guard\n if (verifyNotary \u0026\u0026 status.domain == 0) revert AgentNotNotary();\n }\n\n // ═══════════════════════════════════════════ MERKLE RELATED CHECKS ═══════════════════════════════════════════════\n\n /**\n * @dev Internal function to verify that snapshot roots match.\n * Reverts if any of these is true:\n * - Attestation root is not equal to Merkle Root derived from State and Snapshot Proof.\n * - Snapshot Proof's first element does not match the State metadata.\n * - Snapshot Proof length exceeds Snapshot tree Height.\n * - State index is out of range.\n * @param att Typed memory view over Attestation\n * @param stateIndex Index of state in the snapshot\n * @param state Typed memory view over the provided state payload\n * @param snapProof Raw payload with snapshot data\n */\n function _verifySnapshotMerkle(Attestation att, uint8 stateIndex, State state, bytes32[] memory snapProof)\n internal\n pure\n {\n // Snapshot proof first element should match State metadata (aka \"right sub-leaf\")\n (, bytes32 rightSubLeaf) = state.subLeafs();\n if (snapProof[0] != rightSubLeaf) revert IncorrectSnapshotProof();\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(state.root(), state.origin(), snapProof, stateIndex);\n // Snapshot root should match the attestation root\n if (att.snapRoot() != snapshotRoot) revert IncorrectSnapshotRoot();\n }\n}\n\n// contracts/inbox/Inbox.sol\n\n// ══════════════════════════════ LIBRARY IMPORTS ══════════════════════════════\n\n// ═════════════════════════════ INTERNAL IMPORTS ══════════════════════════════\n\n/// @notice `Inbox` is the child of `StatementInbox` contract, that is used on Synapse Chain.\n/// In addition to the functionality of `StatementInbox`, it also:\n/// - Accepts Guard and Notary Snapshots and passes them to `Summit` contract.\n/// - Accepts Notary-signed Receipts and passes them to `Summit` contract.\n/// - Accepts Receipt Reports to initiate a dispute between Guard and Notary.\n/// - Verifies Attestations and Attestation Reports, and slashes the signer if they are invalid.\ncontract Inbox is StatementInbox, InboxEvents, InterfaceInbox {\n using AttestationLib for bytes;\n using ReceiptLib for bytes;\n using SnapshotLib for bytes;\n\n // Struct to get around stack too deep error. TODO: revisit this\n struct ReceiptInfo {\n AgentStatus rcptNotaryStatus;\n address notary;\n uint32 attNonce;\n AgentStatus attNotaryStatus;\n }\n\n // ══════════════════════════════════════════════════ STORAGE ══════════════════════════════════════════════════════\n\n // The address of the Summit contract.\n address public summit;\n\n // ═════════════════════════════════════════ CONSTRUCTOR \u0026 INITIALIZER ═════════════════════════════════════════════\n\n constructor(uint32 synapseDomain_) MessagingBase(\"0.0.3\", synapseDomain_) {\n if (localDomain != synapseDomain) revert MustBeSynapseDomain();\n }\n\n /// @notice Initializes `Inbox` contract:\n /// - Sets `msg.sender` as the owner of the contract\n /// - Sets `agentManager`, `origin`, `destination` and `summit` addresses\n function initialize(address agentManager_, address origin_, address destination_, address summit_)\n external\n initializer\n {\n __StatementInbox_init(agentManager_, origin_, destination_);\n summit = summit_;\n }\n\n // ══════════════════════════════════════════ SUBMIT AGENT STATEMENTS ══════════════════════════════════════════════\n\n /// @inheritdoc InterfaceInbox\n function submitSnapshot(bytes memory snapPayload, bytes memory snapSignature)\n external\n returns (bytes memory attPayload, bytes32 agentRoot_, uint256[] memory snapGas)\n {\n // This will revert if payload is not a snapshot\n Snapshot snapshot = snapPayload.castToSnapshot();\n // This will revert if the signer is not a known Guard/Notary\n (AgentStatus memory status, address agent) =\n _verifySnapshot({snapshot: snapshot, snapSignature: snapSignature, verifyNotary: false});\n // Check that Agent is active\n status.verifyActive();\n // Store Agent signature for the Snapshot\n uint256 sigIndex = _saveSignature(snapSignature);\n if (status.domain == 0) {\n // Guard that is in Dispute could still submit new snapshots, so we don't check that\n InterfaceSummit(summit).acceptGuardSnapshot({\n guardIndex: status.index,\n sigIndex: sigIndex,\n snapPayload: snapPayload\n });\n } else {\n // Get current agentRoot from AgentManager\n agentRoot_ = IAgentManager(agentManager).agentRoot();\n // This will revert if Notary is in Dispute\n attPayload = InterfaceSummit(summit).acceptNotarySnapshot({\n notaryIndex: status.index,\n sigIndex: sigIndex,\n agentRoot: agentRoot_,\n snapPayload: snapPayload\n });\n ChainGas[] memory snapGas_ = snapshot.snapGas();\n // Pass created attestation to Destination to enable executing messages coming to Synapse Chain\n InterfaceDestination(destination).acceptAttestation(\n status.index, type(uint256).max, attPayload, agentRoot_, snapGas_\n );\n // Use assembly to cast ChainGas[] to uint256[] without copying. Highest bits are left zeroed.\n // solhint-disable-next-line no-inline-assembly\n assembly {\n snapGas := snapGas_\n }\n }\n emit SnapshotAccepted(status.domain, agent, snapPayload, snapSignature);\n }\n\n /// @inheritdoc InterfaceInbox\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 // Struct to get around stack too deep error.\n ReceiptInfo memory info;\n // This will revert if payload is not a receipt\n Receipt rcpt = rcptPayload.castToReceipt();\n // This will revert if the receipt signer is not a known Notary\n (info.rcptNotaryStatus, info.notary) = _verifyReceipt(rcpt, rcptSignature);\n // Receipt Notary needs to be Active\n info.rcptNotaryStatus.verifyActive();\n info.attNonce = IExecutionHub(destination).getAttestationNonce(rcpt.snapshotRoot());\n if (info.attNonce == 0) revert IncorrectSnapshotRoot();\n // Attestation Notary domain needs to match the destination domain\n info.attNotaryStatus = IAgentManager(agentManager).agentStatus(rcpt.attNotary());\n if (info.attNotaryStatus.domain != rcpt.destination()) revert IncorrectAgentDomain();\n // Check that the correct tip values for the message were provided\n _verifyReceiptTips(rcpt.messageHash(), paddedTips, headerHash, bodyHash);\n // Store Notary signature for the Receipt\n uint256 sigIndex = _saveSignature(rcptSignature);\n // This will revert if Receipt Notary is in Dispute\n wasAccepted = InterfaceSummit(summit).acceptReceipt({\n rcptNotaryIndex: info.rcptNotaryStatus.index,\n attNotaryIndex: info.attNotaryStatus.index,\n sigIndex: sigIndex,\n attNonce: info.attNonce,\n paddedTips: paddedTips,\n rcptPayload: rcptPayload\n });\n if (wasAccepted) {\n emit ReceiptAccepted(info.rcptNotaryStatus.domain, info.notary, rcptPayload, rcptSignature);\n }\n }\n\n /// @inheritdoc InterfaceInbox\n function submitReceiptReport(bytes memory rcptPayload, bytes memory rcptSignature, bytes memory rrSignature)\n external\n returns (bool wasAccepted)\n {\n // This will revert if payload is not a receipt\n Receipt rcpt = rcptPayload.castToReceipt();\n // This will revert if the receipt signer is not a known Guard\n (AgentStatus memory guardStatus,) = _verifyReceiptReport(rcpt, rrSignature);\n // Guard needs to be Active\n guardStatus.verifyActive();\n // This will revert if report signer is not a known Notary\n (AgentStatus memory notaryStatus,) = _verifyReceipt(rcpt, rcptSignature);\n // Notary needs to be Active/Unstaking\n notaryStatus.verifyActiveUnstaking();\n _saveReport(rcptPayload, rrSignature);\n // This will revert if either actor is already in dispute\n IAgentManager(agentManager).openDispute(guardStatus.index, notaryStatus.index);\n return true;\n }\n\n /// @inheritdoc InterfaceInbox\n function passReceipt(uint32 attNotaryIndex, uint32 attNonce, uint256 paddedTips, bytes memory rcptPayload)\n external\n returns (bool wasAccepted)\n {\n // Only Destination can pass receipts\n if (msg.sender != destination) revert CallerNotDestination();\n return InterfaceSummit(summit).acceptReceipt({\n rcptNotaryIndex: attNotaryIndex,\n attNotaryIndex: attNotaryIndex,\n sigIndex: type(uint256).max,\n attNonce: attNonce,\n paddedTips: paddedTips,\n rcptPayload: rcptPayload\n });\n }\n\n // ══════════════════════════════════════════ VERIFY AGENT STATEMENTS ══════════════════════════════════════════════\n\n /// @inheritdoc InterfaceInbox\n function verifyAttestation(bytes memory attPayload, bytes memory attSignature)\n external\n returns (bool isValidAttestation)\n {\n // This will revert if payload is not an attestation\n Attestation att = attPayload.castToAttestation();\n // This will revert if the attestation signer is not a known Notary\n (AgentStatus memory status, address notary) = _verifyAttestation(att, attSignature);\n // Notary needs to be Active/Unstaking\n status.verifyActiveUnstaking();\n isValidAttestation = ISnapshotHub(summit).isValidAttestation(attPayload);\n if (!isValidAttestation) {\n emit InvalidAttestation(attPayload, attSignature);\n IAgentManager(agentManager).slashAgent(status.domain, notary, msg.sender);\n }\n }\n\n /// @inheritdoc InterfaceInbox\n function verifyAttestationReport(bytes memory attPayload, bytes memory arSignature)\n external\n returns (bool isValidReport)\n {\n // This will revert if payload is not an attestation\n Attestation att = attPayload.castToAttestation();\n // This will revert if the report signer is not a known Guard\n (AgentStatus memory status, address guard) = _verifyAttestationReport(att, arSignature);\n // Guard needs to be Active/Unstaking\n status.verifyActiveUnstaking();\n // Report is valid IF AND ONLY IF the reported attestation in invalid\n isValidReport = !ISnapshotHub(summit).isValidAttestation(attPayload);\n if (!isValidReport) {\n emit InvalidAttestationReport(attPayload, arSignature);\n IAgentManager(agentManager).slashAgent(status.domain, guard, msg.sender);\n }\n }\n\n // ══════════════════════════════════════════════ INTERNAL VIEWS ═══════════════════════════════════════════════════\n\n /// @dev Verifies that tips proof matches the message hash.\n function _verifyReceiptTips(bytes32 msgHash, uint256 paddedTips, bytes32 headerHash, bytes32 bodyHash)\n internal\n pure\n {\n Tips tips = TipsLib.wrapPadded(paddedTips);\n // full message leaf is (header, baseMessage), while base message leaf is (tips, remainingBody).\n if (MerkleMath.getParent(headerHash, MerkleMath.getParent(tips.leaf(), bodyHash)) != msgHash) {\n revert IncorrectTipsProof();\n }\n }\n}\n","language":"Solidity","languageVersion":"0.8.17","compilerVersion":"0.8.17","compilerOptions":"--combined-json bin,bin-runtime,srcmap,srcmap-runtime,abi,userdoc,devdoc,metadata,hashes --optimize --optimize-runs 10000 --allow-paths ., ./, ../","srcMap":"95377:1047:0:-:0;;;;;;;;;;;;;;;-1:-1:-1;;;95377:1047:0;;;;;;;;;;;;;;;;;","srcMapRuntime":"95377:1047:0:-:0;;;;;;;;","abiDefinition":[],"userDoc":{"kind":"user","methods":{},"version":1},"developerDoc":{"details":"Standard signed math utilities missing in the Solidity language.","kind":"dev","methods":{},"version":1},"metadata":"{\"compiler\":{\"version\":\"0.8.17+commit.8df45f5f\"},\"language\":\"Solidity\",\"output\":{\"abi\":[],\"devdoc\":{\"details\":\"Standard signed math utilities missing in the Solidity language.\",\"kind\":\"dev\",\"methods\":{},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"solidity/Inbox.sol\":\"SignedMath\"},\"evmVersion\":\"london\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\"},\"optimizer\":{\"enabled\":true,\"runs\":10000},\"remappings\":[]},\"sources\":{\"solidity/Inbox.sol\":{\"keccak256\":\"0x9b516081a036814c0169e20e484d4a5499066b7a6f48fada952b5e844a1ca3e5\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://32bde393b3f24ef4307d9626d4143f337b3c0bd34e17bb969fd5a15221d96987\",\"dweb:/ipfs/QmTkt2XZRtgsbSpmsVQUM3c4ebETQoDVYbmEV9yheBghnr\"]}},\"version\":1}"},"hashes":{}},"solidity/Inbox.sol:SnapshotLib":{"code":"0x60566037600b82828239805160001a607314602a57634e487b7160e01b600052600060045260246000fd5b30600052607381538281f3fe73000000000000000000000000000000000000000030146080604052600080fdfea26469706673582212209dafbb5f84ebec6dc61dd3571a8eed3f1c5ed4960845a1f5cc9da97a49c52f5864736f6c63430008110033","runtime-code":"0x73000000000000000000000000000000000000000030146080604052600080fdfea26469706673582212209dafbb5f84ebec6dc61dd3571a8eed3f1c5ed4960845a1f5cc9da97a49c52f5864736f6c63430008110033","info":{"source":"// SPDX-License-Identifier: MIT\npragma solidity =0.8.17 ^0.8.0 ^0.8.1 ^0.8.2;\n\n// contracts/events/InboxEvents.sol\n\nabstract contract InboxEvents {\n /**\n * @notice Emitted when a snapshot is accepted by the Summit contract.\n * @param domain Domain where the signed Agent is active (ZERO for Guards)\n * @param agent Agent who signed the snapshot\n * @param snapPayload Raw payload with snapshot data\n * @param snapSignature Agent signature for the snapshot\n */\n event SnapshotAccepted(uint32 indexed domain, address indexed agent, bytes snapPayload, bytes snapSignature);\n\n /**\n * @notice Emitted when a snapshot is accepted by the Summit contract.\n * @param domain Domain where the signed Notary is active\n * @param notary Notary who signed the attestation\n * @param rcptPayload Raw payload with receipt data\n * @param rcptSignature Notary signature for the receipt\n */\n event ReceiptAccepted(uint32 domain, address notary, bytes rcptPayload, bytes rcptSignature);\n\n /**\n * @notice Emitted when a proof of invalid attestation is submitted.\n * @param attPayload Raw payload with Attestation data\n * @param attSignature Notary signature for the attestation\n */\n event InvalidAttestation(bytes attPayload, bytes attSignature);\n\n /**\n * @notice Emitted when a proof of invalid attestation report is submitted.\n * @param arPayload Raw payload with report data\n * @param arSignature Guard signature for the report\n */\n event InvalidAttestationReport(bytes arPayload, bytes arSignature);\n}\n\n// contracts/events/StatementInboxEvents.sol\n\nabstract contract StatementInboxEvents {\n // ════════════════════════════════════════════ STATEMENT ACCEPTED ═════════════════════════════════════════════════\n\n /**\n * @notice Emitted when a snapshot is accepted by the Destination contract.\n * @param domain Domain where the signed Notary is active\n * @param notary Notary who signed the attestation\n * @param attPayload Raw payload with attestation data\n * @param attSignature Notary signature for the attestation\n */\n event AttestationAccepted(uint32 domain, address notary, bytes attPayload, bytes attSignature);\n\n // ═════════════════════════════════════════ INVALID STATEMENT PROVED ══════════════════════════════════════════════\n\n /**\n * @notice Emitted when a proof of invalid receipt statement is submitted.\n * @param rcptPayload Raw payload with the receipt statement\n * @param rcptSignature Notary signature for the receipt statement\n */\n event InvalidReceipt(bytes rcptPayload, bytes rcptSignature);\n\n /**\n * @notice Emitted when a proof of invalid receipt report is submitted.\n * @param rrPayload Raw payload with report data\n * @param rrSignature Guard signature for the report\n */\n event InvalidReceiptReport(bytes rrPayload, bytes rrSignature);\n\n /**\n * @notice Emitted when a proof of invalid state in the signed attestation is submitted.\n * @param stateIndex Index of invalid state in the snapshot\n * @param statePayload Raw payload with state data\n * @param attPayload Raw payload with Attestation data for snapshot\n * @param attSignature Notary signature for the attestation\n */\n event InvalidStateWithAttestation(uint8 stateIndex, bytes statePayload, bytes attPayload, bytes attSignature);\n\n /**\n * @notice Emitted when a proof of invalid state in the signed snapshot is submitted.\n * @param stateIndex Index of invalid state in the snapshot\n * @param snapPayload Raw payload with snapshot data\n * @param snapSignature Agent signature for the snapshot\n */\n event InvalidStateWithSnapshot(uint8 stateIndex, bytes snapPayload, bytes snapSignature);\n\n /**\n * @notice Emitted when a proof of invalid state report is submitted.\n * @param srPayload Raw payload with report data\n * @param srSignature Guard signature for the report\n */\n event InvalidStateReport(bytes srPayload, bytes srSignature);\n}\n\n// contracts/interfaces/ISnapshotHub.sol\n\ninterface ISnapshotHub {\n /**\n * @notice Check that a given attestation is valid: matches the historical attestation\n * derived from an accepted Notary snapshot.\n * @dev Will revert if any of these is true:\n * - Attestation payload is not properly formatted.\n * @param attPayload Raw payload with attestation data\n * @return isValid Whether the provided attestation is valid\n */\n function isValidAttestation(bytes memory attPayload) external view returns (bool isValid);\n\n /**\n * @notice Returns saved attestation with the given nonce.\n * @dev Reverts if attestation with given nonce hasn't been created yet.\n * @param attNonce Nonce for the attestation\n * @return attPayload Raw payload with formatted Attestation data\n * @return agentRoot Agent root hash used for the attestation\n * @return snapGas Snapshot gas data used for the attestation\n */\n function getAttestation(uint32 attNonce)\n external\n view\n returns (bytes memory attPayload, bytes32 agentRoot, uint256[] memory snapGas);\n\n /**\n * @notice Returns the state with the highest known nonce submitted by a given Agent.\n * @param origin Domain of origin chain\n * @param agent Agent address\n * @return statePayload Raw payload with agent's latest state for origin\n */\n function getLatestAgentState(uint32 origin, address agent) external view returns (bytes memory statePayload);\n\n /**\n * @notice Returns latest saved attestation for a Notary.\n * @param notary Notary address\n * @return attPayload Raw payload with formatted Attestation data\n * @return agentRoot Agent root hash used for the attestation\n * @return snapGas Snapshot gas data used for the attestation\n */\n function getLatestNotaryAttestation(address notary)\n external\n view\n returns (bytes memory attPayload, bytes32 agentRoot, uint256[] memory snapGas);\n\n /**\n * @notice Returns Guard snapshot from the list of all accepted Guard snapshots.\n * @dev Reverts if snapshot with given index hasn't been accepted yet.\n * @param index Snapshot index in the list of all Guard snapshots\n * @return snapPayload Raw payload with Guard snapshot\n * @return snapSignature Raw payload with Guard signature for snapshot\n */\n function getGuardSnapshot(uint256 index)\n external\n view\n returns (bytes memory snapPayload, bytes memory snapSignature);\n\n /**\n * @notice Returns Notary snapshot from the list of all accepted Guard snapshots.\n * @dev Reverts if snapshot with given index hasn't been accepted yet.\n * @param index Snapshot index in the list of all Notary snapshots\n * @return snapPayload Raw payload with Notary snapshot\n * @return snapSignature Raw payload with Notary signature for snapshot\n */\n function getNotarySnapshot(uint256 index)\n external\n view\n returns (bytes memory snapPayload, bytes memory snapSignature);\n\n /**\n * @notice Returns Notary snapshot that was used for creating a given attestation.\n * @dev Reverts if any of these is true:\n * - Attestation payload is not properly formatted.\n * - Attestation is invalid (doesn't have a matching Notary snapshot).\n * @param attPayload Raw payload with attestation data\n * @return snapPayload Raw payload with Notary snapshot\n * @return snapSignature Raw payload with Notary signature for snapshot\n */\n function getNotarySnapshot(bytes memory attPayload)\n external\n view\n returns (bytes memory snapPayload, bytes memory snapSignature);\n\n /**\n * @notice Returns proof of inclusion of (root, origin) fields of a given snapshot's state\n * into the Snapshot Merkle Tree for a given attestation.\n * @dev Reverts if any of these is true:\n * - Attestation with given nonce hasn't been created yet.\n * - State index is out of range of snapshot list.\n * @param attNonce Nonce for the attestation\n * @param stateIndex Index of state in the attestation's snapshot\n * @return snapProof The snapshot proof\n */\n function getSnapshotProof(uint32 attNonce, uint8 stateIndex) external view returns (bytes32[] memory snapProof);\n}\n\n// contracts/interfaces/IStateHub.sol\n\ninterface IStateHub {\n /**\n * @notice Check that a given state is valid: matches the historical state of Origin contract.\n * Note: any Agent including an invalid state in their snapshot will be slashed\n * upon providing the snapshot and agent signature for it to Origin contract.\n * @dev Will revert if any of these is true:\n * - State payload is not properly formatted.\n * @param statePayload Raw payload with state data\n * @return isValid Whether the provided state is valid\n */\n function isValidState(bytes memory statePayload) external view returns (bool isValid);\n\n /**\n * @notice Returns the amount of saved states so far.\n * @dev This includes the initial state of \"empty Origin Merkle Tree\".\n */\n function statesAmount() external view returns (uint256);\n\n /**\n * @notice Suggest the data (state after latest sent message) to sign for an Agent.\n * Note: signing the suggested state data will will never lead to slashing of the actor,\n * assuming they have confirmed that the block, which number is included in the data,\n * is not subject to reorganization (which is different for every observed chain).\n * @return statePayload Raw payload with the latest state data\n */\n function suggestLatestState() external view returns (bytes memory statePayload);\n\n /**\n * @notice Given the historical nonce, suggest the state data to sign for an Agent.\n * Note: signing the suggested state data will will never lead to slashing of the actor,\n * assuming they have confirmed that the block, which number is included in the data,\n * is not subject to reorganization (which is different for every observed chain).\n * @param nonce Historical nonce to form a state\n * @return statePayload Raw payload with historical state data\n */\n function suggestState(uint32 nonce) external view returns (bytes memory statePayload);\n}\n\n// contracts/interfaces/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/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// node_modules/@openzeppelin/contracts/utils/math/Math.sol\n\n// OpenZeppelin Contracts (last updated v4.9.0) (utils/math/Math.sol)\n\n/**\n * @dev Standard math utilities missing in the Solidity language.\n */\nlibrary Math {\n enum Rounding {\n Down, // Toward negative infinity\n Up, // Toward infinity\n Zero // Toward zero\n }\n\n /**\n * @dev Returns the largest of two numbers.\n */\n function max(uint256 a, uint256 b) internal pure returns (uint256) {\n return a \u003e b ? a : b;\n }\n\n /**\n * @dev Returns the smallest of two numbers.\n */\n function min(uint256 a, uint256 b) internal pure returns (uint256) {\n return a \u003c b ? a : b;\n }\n\n /**\n * @dev Returns the average of two numbers. The result is rounded towards\n * zero.\n */\n function average(uint256 a, uint256 b) internal pure returns (uint256) {\n // (a + b) / 2 can overflow.\n return (a \u0026 b) + (a ^ b) / 2;\n }\n\n /**\n * @dev Returns the ceiling of the division of two numbers.\n *\n * This differs from standard division with `/` in that it rounds up instead\n * of rounding down.\n */\n function ceilDiv(uint256 a, uint256 b) internal pure returns (uint256) {\n // (a + b - 1) / b can overflow on addition, so we distribute.\n return a == 0 ? 0 : (a - 1) / b + 1;\n }\n\n /**\n * @notice Calculates floor(x * y / denominator) with full precision. Throws if result overflows a uint256 or denominator == 0\n * @dev Original credit to Remco Bloemen under MIT license (https://xn--2-umb.com/21/muldiv)\n * with further edits by Uniswap Labs also under MIT license.\n */\n function mulDiv(uint256 x, uint256 y, uint256 denominator) internal pure returns (uint256 result) {\n unchecked {\n // 512-bit multiply [prod1 prod0] = x * y. Compute the product mod 2^256 and mod 2^256 - 1, then use\n // use the Chinese Remainder Theorem to reconstruct the 512 bit result. The result is stored in two 256\n // variables such that product = prod1 * 2^256 + prod0.\n uint256 prod0; // Least significant 256 bits of the product\n uint256 prod1; // Most significant 256 bits of the product\n assembly {\n let mm := mulmod(x, y, not(0))\n prod0 := mul(x, y)\n prod1 := sub(sub(mm, prod0), lt(mm, prod0))\n }\n\n // Handle non-overflow cases, 256 by 256 division.\n if (prod1 == 0) {\n // Solidity will revert if denominator == 0, unlike the div opcode on its own.\n // The surrounding unchecked block does not change this fact.\n // See https://docs.soliditylang.org/en/latest/control-structures.html#checked-or-unchecked-arithmetic.\n return prod0 / denominator;\n }\n\n // Make sure the result is less than 2^256. Also prevents denominator == 0.\n require(denominator \u003e prod1, \"Math: mulDiv overflow\");\n\n ///////////////////////////////////////////////\n // 512 by 256 division.\n ///////////////////////////////////////////////\n\n // Make division exact by subtracting the remainder from [prod1 prod0].\n uint256 remainder;\n assembly {\n // Compute remainder using mulmod.\n remainder := mulmod(x, y, denominator)\n\n // Subtract 256 bit number from 512 bit number.\n prod1 := sub(prod1, gt(remainder, prod0))\n prod0 := sub(prod0, remainder)\n }\n\n // Factor powers of two out of denominator and compute largest power of two divisor of denominator. Always \u003e= 1.\n // See https://cs.stackexchange.com/q/138556/92363.\n\n // Does not overflow because the denominator cannot be zero at this stage in the function.\n uint256 twos = denominator \u0026 (~denominator + 1);\n assembly {\n // Divide denominator by twos.\n denominator := div(denominator, twos)\n\n // Divide [prod1 prod0] by twos.\n prod0 := div(prod0, twos)\n\n // Flip twos such that it is 2^256 / twos. If twos is zero, then it becomes one.\n twos := add(div(sub(0, twos), twos), 1)\n }\n\n // Shift in bits from prod1 into prod0.\n prod0 |= prod1 * twos;\n\n // Invert denominator mod 2^256. Now that denominator is an odd number, it has an inverse modulo 2^256 such\n // that denominator * inv = 1 mod 2^256. Compute the inverse by starting with a seed that is correct for\n // four bits. That is, denominator * inv = 1 mod 2^4.\n uint256 inverse = (3 * denominator) ^ 2;\n\n // Use the Newton-Raphson iteration to improve the precision. Thanks to Hensel's lifting lemma, this also works\n // in modular arithmetic, doubling the correct bits in each step.\n inverse *= 2 - denominator * inverse; // inverse mod 2^8\n inverse *= 2 - denominator * inverse; // inverse mod 2^16\n inverse *= 2 - denominator * inverse; // inverse mod 2^32\n inverse *= 2 - denominator * inverse; // inverse mod 2^64\n inverse *= 2 - denominator * inverse; // inverse mod 2^128\n inverse *= 2 - denominator * inverse; // inverse mod 2^256\n\n // Because the division is now exact we can divide by multiplying with the modular inverse of denominator.\n // This will give us the correct result modulo 2^256. Since the preconditions guarantee that the outcome is\n // less than 2^256, this is the final result. We don't need to compute the high bits of the result and prod1\n // is no longer required.\n result = prod0 * inverse;\n return result;\n }\n }\n\n /**\n * @notice Calculates x * y / denominator with full precision, following the selected rounding direction.\n */\n function mulDiv(uint256 x, uint256 y, uint256 denominator, Rounding rounding) internal pure returns (uint256) {\n uint256 result = mulDiv(x, y, denominator);\n if (rounding == Rounding.Up \u0026\u0026 mulmod(x, y, denominator) \u003e 0) {\n result += 1;\n }\n return result;\n }\n\n /**\n * @dev Returns the square root of a number. If the number is not a perfect square, the value is rounded down.\n *\n * Inspired by Henry S. Warren, Jr.'s \"Hacker's Delight\" (Chapter 11).\n */\n function sqrt(uint256 a) internal pure returns (uint256) {\n if (a == 0) {\n return 0;\n }\n\n // For our first guess, we get the biggest power of 2 which is smaller than the square root of the target.\n //\n // We know that the \"msb\" (most significant bit) of our target number `a` is a power of 2 such that we have\n // `msb(a) \u003c= a \u003c 2*msb(a)`. This value can be written `msb(a)=2**k` with `k=log2(a)`.\n //\n // This can be rewritten `2**log2(a) \u003c= a \u003c 2**(log2(a) + 1)`\n // → `sqrt(2**k) \u003c= sqrt(a) \u003c sqrt(2**(k+1))`\n // → `2**(k/2) \u003c= sqrt(a) \u003c 2**((k+1)/2) \u003c= 2**(k/2 + 1)`\n //\n // Consequently, `2**(log2(a) / 2)` is a good first approximation of `sqrt(a)` with at least 1 correct bit.\n uint256 result = 1 \u003c\u003c (log2(a) \u003e\u003e 1);\n\n // At this point `result` is an estimation with one bit of precision. We know the true value is a uint128,\n // since it is the square root of a uint256. Newton's method converges quadratically (precision doubles at\n // every iteration). We thus need at most 7 iteration to turn our partial result with one bit of precision\n // into the expected uint128 result.\n unchecked {\n result = (result + a / result) \u003e\u003e 1;\n result = (result + a / result) \u003e\u003e 1;\n result = (result + a / result) \u003e\u003e 1;\n result = (result + a / result) \u003e\u003e 1;\n result = (result + a / result) \u003e\u003e 1;\n result = (result + a / result) \u003e\u003e 1;\n result = (result + a / result) \u003e\u003e 1;\n return min(result, a / result);\n }\n }\n\n /**\n * @notice Calculates sqrt(a), following the selected rounding direction.\n */\n function sqrt(uint256 a, Rounding rounding) internal pure returns (uint256) {\n unchecked {\n uint256 result = sqrt(a);\n return result + (rounding == Rounding.Up \u0026\u0026 result * result \u003c a ? 1 : 0);\n }\n }\n\n /**\n * @dev Return the log in base 2, rounded down, of a positive value.\n * Returns 0 if given 0.\n */\n function log2(uint256 value) internal pure returns (uint256) {\n uint256 result = 0;\n unchecked {\n if (value \u003e\u003e 128 \u003e 0) {\n value \u003e\u003e= 128;\n result += 128;\n }\n if (value \u003e\u003e 64 \u003e 0) {\n value \u003e\u003e= 64;\n result += 64;\n }\n if (value \u003e\u003e 32 \u003e 0) {\n value \u003e\u003e= 32;\n result += 32;\n }\n if (value \u003e\u003e 16 \u003e 0) {\n value \u003e\u003e= 16;\n result += 16;\n }\n if (value \u003e\u003e 8 \u003e 0) {\n value \u003e\u003e= 8;\n result += 8;\n }\n if (value \u003e\u003e 4 \u003e 0) {\n value \u003e\u003e= 4;\n result += 4;\n }\n if (value \u003e\u003e 2 \u003e 0) {\n value \u003e\u003e= 2;\n result += 2;\n }\n if (value \u003e\u003e 1 \u003e 0) {\n result += 1;\n }\n }\n return result;\n }\n\n /**\n * @dev Return the log in base 2, following the selected rounding direction, of a positive value.\n * Returns 0 if given 0.\n */\n function log2(uint256 value, Rounding rounding) internal pure returns (uint256) {\n unchecked {\n uint256 result = log2(value);\n return result + (rounding == Rounding.Up \u0026\u0026 1 \u003c\u003c result \u003c value ? 1 : 0);\n }\n }\n\n /**\n * @dev Return the log in base 10, rounded down, of a positive value.\n * Returns 0 if given 0.\n */\n function log10(uint256 value) internal pure returns (uint256) {\n uint256 result = 0;\n unchecked {\n if (value \u003e= 10 ** 64) {\n value /= 10 ** 64;\n result += 64;\n }\n if (value \u003e= 10 ** 32) {\n value /= 10 ** 32;\n result += 32;\n }\n if (value \u003e= 10 ** 16) {\n value /= 10 ** 16;\n result += 16;\n }\n if (value \u003e= 10 ** 8) {\n value /= 10 ** 8;\n result += 8;\n }\n if (value \u003e= 10 ** 4) {\n value /= 10 ** 4;\n result += 4;\n }\n if (value \u003e= 10 ** 2) {\n value /= 10 ** 2;\n result += 2;\n }\n if (value \u003e= 10 ** 1) {\n result += 1;\n }\n }\n return result;\n }\n\n /**\n * @dev Return the log in base 10, following the selected rounding direction, of a positive value.\n * Returns 0 if given 0.\n */\n function log10(uint256 value, Rounding rounding) internal pure returns (uint256) {\n unchecked {\n uint256 result = log10(value);\n return result + (rounding == Rounding.Up \u0026\u0026 10 ** result \u003c value ? 1 : 0);\n }\n }\n\n /**\n * @dev Return the log in base 256, rounded down, of a positive value.\n * Returns 0 if given 0.\n *\n * Adding one to the result gives the number of pairs of hex symbols needed to represent `value` as a hex string.\n */\n function log256(uint256 value) internal pure returns (uint256) {\n uint256 result = 0;\n unchecked {\n if (value \u003e\u003e 128 \u003e 0) {\n value \u003e\u003e= 128;\n result += 16;\n }\n if (value \u003e\u003e 64 \u003e 0) {\n value \u003e\u003e= 64;\n result += 8;\n }\n if (value \u003e\u003e 32 \u003e 0) {\n value \u003e\u003e= 32;\n result += 4;\n }\n if (value \u003e\u003e 16 \u003e 0) {\n value \u003e\u003e= 16;\n result += 2;\n }\n if (value \u003e\u003e 8 \u003e 0) {\n result += 1;\n }\n }\n return result;\n }\n\n /**\n * @dev Return the log in base 256, following the selected rounding direction, of a positive value.\n * Returns 0 if given 0.\n */\n function log256(uint256 value, Rounding rounding) internal pure returns (uint256) {\n unchecked {\n uint256 result = log256(value);\n return result + (rounding == Rounding.Up \u0026\u0026 1 \u003c\u003c (result \u003c\u003c 3) \u003c value ? 1 : 0);\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/utils/math/SignedMath.sol\n\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/math/SignedMath.sol)\n\n/**\n * @dev Standard signed math utilities missing in the Solidity language.\n */\nlibrary SignedMath {\n /**\n * @dev Returns the largest of two signed numbers.\n */\n function max(int256 a, int256 b) internal pure returns (int256) {\n return a \u003e b ? a : b;\n }\n\n /**\n * @dev Returns the smallest of two signed numbers.\n */\n function min(int256 a, int256 b) internal pure returns (int256) {\n return a \u003c b ? a : b;\n }\n\n /**\n * @dev Returns the average of two signed numbers without overflow.\n * The result is rounded towards zero.\n */\n function average(int256 a, int256 b) internal pure returns (int256) {\n // Formula from the book \"Hacker's Delight\"\n int256 x = (a \u0026 b) + ((a ^ b) \u003e\u003e 1);\n return x + (int256(uint256(x) \u003e\u003e 255) \u0026 (a ^ b));\n }\n\n /**\n * @dev Returns the absolute unsigned value of a signed value.\n */\n function abs(int256 n) internal pure returns (uint256) {\n unchecked {\n // must be unchecked in order to support `n = type(int256).min`\n return uint256(n \u003e= 0 ? n : -n);\n }\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// 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/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/InterfaceSummit.sol\n\ninterface InterfaceSummit {\n // ══════════════════════════════════════════ ACCEPT AGENT STATEMENTS ══════════════════════════════════════════════\n\n /**\n * @notice Accepts a receipt, which local `AgentManager` verified to have been signed by an active Notary.\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 * - Notary who signed the receipt is referenced as the \"Receipt Notary\".\n * - Notary who signed the attestation on destination chain is referenced as the \"Attestation Notary\".\n * \u003e Will revert if any of these is true:\n * \u003e - Called by anyone other than local `AgentManager`.\n * \u003e - Receipt body payload is not properly formatted.\n * \u003e - Receipt signer is in Dispute.\n * \u003e - Receipt's snapshot root is unknown.\n * @param rcptNotaryIndex Index of Receipt Notary in Agent Merkle Tree\n * @param attNotaryIndex Index of Attestation Notary in Agent Merkle Tree\n * @param sigIndex Index of stored Notary signature\n * @param attNonce Nonce of the attestation used for proving the executed message\n * @param paddedTips Padded encoded paid tips information\n * @param rcptPayload Raw payload with message execution receipt\n * @return wasAccepted Whether the receipt was accepted\n */\n function acceptReceipt(\n uint32 rcptNotaryIndex,\n uint32 attNotaryIndex,\n uint256 sigIndex,\n uint32 attNonce,\n uint256 paddedTips,\n bytes memory rcptPayload\n ) external returns (bool wasAccepted);\n\n /**\n * @notice Accepts a snapshot, which local `AgentManager` verified to have been signed by an active Guard.\n * \u003e Snapshot is a list of states for a set of Origin contracts residing on any of the chains.\n * All the states in the Guard-signed snapshot become available for Notary signing.\n * \u003e Will revert if any of these is true:\n * \u003e - Called by anyone other than local `AgentManager`.\n * \u003e - Snapshot payload is not properly formatted.\n * \u003e - Snapshot contains a state older then the Guard has previously submitted.\n * @param guardIndex Index of Guard in Agent Merkle Tree\n * @param sigIndex Index of stored Agent signature\n * @param snapPayload Raw payload with snapshot data\n */\n function acceptGuardSnapshot(uint32 guardIndex, uint256 sigIndex, bytes memory snapPayload) external;\n\n /**\n * @notice Accepts a snapshot, which local `AgentManager` verified to have been signed by an active Notary.\n * \u003e Snapshot is a list of states for a set of Origin contracts residing on any of the chains.\n * Snapshot Merkle Root is calculated and saved for valid snapshots, i.e.\n * snapshots which are only using states previously submitted by any of the Guards.\n * - Notary could use states singed by the same of different Guards 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 - Called by anyone other than local `AgentManager`.\n * \u003e - Snapshot payload is not properly formatted.\n * \u003e - Snapshot contains a state older then the Notary has previously submitted.\n * \u003e - Snapshot contains a state that no Guard has previously submitted.\n * @param notaryIndex Index of Notary in Agent Merkle Tree\n * @param sigIndex Index of stored Agent signature\n * @param agentRoot Current root of the Agent Merkle Tree\n * @param snapPayload Raw payload with snapshot data\n * @return attPayload Raw payload with data for attestation derived from Notary snapshot.\n */\n function acceptNotarySnapshot(uint32 notaryIndex, uint256 sigIndex, bytes32 agentRoot, bytes memory snapPayload)\n external\n returns (bytes memory attPayload);\n\n // ════════════════════════════════════════════════ TIPS LOGIC ═════════════════════════════════════════════════════\n\n /**\n * @notice Distributes tips using the first Receipt from the \"receipt quarantine queue\".\n * Possible scenarios:\n * - Receipt queue is empty =\u003e does nothing\n * - Receipt optimistic period is not over =\u003e does nothing\n * - Either of Notaries present in Receipt was slashed =\u003e receipt is deleted from the queue\n * - Either of Notaries present in Receipt in Dispute =\u003e receipt is moved to the end of queue\n * - None of the above =\u003e receipt tips are distributed\n * @dev Returned value makes it possible to do the following: `while (distributeTips()) {}`\n * @return queuePopped Whether the first element was popped from the queue\n */\n function distributeTips() external returns (bool queuePopped);\n\n /**\n * @notice Withdraws locked base message tips from requested domain Origin to the recipient.\n * This is done by a call to a local Origin contract, or by a manager message to the remote chain.\n * @dev This will revert, if the pending balance of origin tips (earned-claimed) is lower than requested.\n * @param origin Domain of chain to withdraw tips on\n * @param amount Amount of tips to withdraw\n */\n function withdrawTips(uint32 origin, uint256 amount) external;\n\n // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════\n\n /**\n * @notice Returns earned and claimed tips for the actor.\n * Note: Tips for address(0) belong to the Treasury.\n * @param actor Address of the actor\n * @param origin Domain where the tips were initially paid\n * @return earned Total amount of origin tips the actor has earned so far\n * @return claimed Total amount of origin tips the actor has claimed so far\n */\n function actorTips(address actor, uint32 origin) external view returns (uint128 earned, uint128 claimed);\n\n /**\n * @notice Returns the amount of receipts in the \"Receipt Quarantine Queue\".\n */\n function receiptQueueLength() external view returns (uint256);\n\n /**\n * @notice Returns the state with the highest known nonce\n * submitted by any of the currently active Guards.\n * @param origin Domain of origin chain\n * @return statePayload Raw payload with latest active Guard state for origin\n */\n function getLatestState(uint32 origin) external view returns (bytes memory statePayload);\n}\n\n// node_modules/@openzeppelin/contracts/utils/Strings.sol\n\n// OpenZeppelin Contracts (last updated v4.9.0) (utils/Strings.sol)\n\n/**\n * @dev String operations.\n */\nlibrary Strings {\n bytes16 private constant _SYMBOLS = \"0123456789abcdef\";\n uint8 private constant _ADDRESS_LENGTH = 20;\n\n /**\n * @dev Converts a `uint256` to its ASCII `string` decimal representation.\n */\n function toString(uint256 value) internal pure returns (string memory) {\n unchecked {\n uint256 length = Math.log10(value) + 1;\n string memory buffer = new string(length);\n uint256 ptr;\n /// @solidity memory-safe-assembly\n assembly {\n ptr := add(buffer, add(32, length))\n }\n while (true) {\n ptr--;\n /// @solidity memory-safe-assembly\n assembly {\n mstore8(ptr, byte(mod(value, 10), _SYMBOLS))\n }\n value /= 10;\n if (value == 0) break;\n }\n return buffer;\n }\n }\n\n /**\n * @dev Converts a `int256` to its ASCII `string` decimal representation.\n */\n function toString(int256 value) internal pure returns (string memory) {\n return string(abi.encodePacked(value \u003c 0 ? \"-\" : \"\", toString(SignedMath.abs(value))));\n }\n\n /**\n * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation.\n */\n function toHexString(uint256 value) internal pure returns (string memory) {\n unchecked {\n return toHexString(value, Math.log256(value) + 1);\n }\n }\n\n /**\n * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length.\n */\n function toHexString(uint256 value, uint256 length) internal pure returns (string memory) {\n bytes memory buffer = new bytes(2 * length + 2);\n buffer[0] = \"0\";\n buffer[1] = \"x\";\n for (uint256 i = 2 * length + 1; i \u003e 1; --i) {\n buffer[i] = _SYMBOLS[value \u0026 0xf];\n value \u003e\u003e= 4;\n }\n require(value == 0, \"Strings: hex length insufficient\");\n return string(buffer);\n }\n\n /**\n * @dev Converts an `address` with fixed length of 20 bytes to its not checksummed ASCII `string` hexadecimal representation.\n */\n function toHexString(address addr) internal pure returns (string memory) {\n return toHexString(uint256(uint160(addr)), _ADDRESS_LENGTH);\n }\n\n /**\n * @dev Returns true if the two strings are equal.\n */\n function equal(string memory a, string memory b) internal pure returns (bool) {\n return keccak256(bytes(a)) == keccak256(bytes(b));\n }\n}\n\n// node_modules/@openzeppelin/contracts-upgradeable/utils/ContextUpgradeable.sol\n\n// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)\n\n/**\n * @dev Provides information about the current execution context, including the\n * sender of the transaction and its data. While these are generally available\n * via msg.sender and msg.data, they should not be accessed in such a direct\n * manner, since when dealing with meta-transactions the account sending and\n * paying for execution may not be the actual sender (as far as an application\n * is concerned).\n *\n * This contract is only required for intermediate, library-like contracts.\n */\nabstract contract ContextUpgradeable is Initializable {\n function __Context_init() internal onlyInitializing {\n }\n\n function __Context_init_unchained() internal onlyInitializing {\n }\n function _msgSender() internal view virtual returns (address) {\n return msg.sender;\n }\n\n function _msgData() internal view virtual returns (bytes calldata) {\n return msg.data;\n }\n\n /**\n * @dev This empty reserved space is put in place to allow future versions to add new\n * variables without shifting down storage in the inheritance chain.\n * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\n */\n uint256[50] private __gap;\n}\n\n// contracts/libs/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/utils/cryptography/ECDSA.sol\n\n// OpenZeppelin Contracts (last updated v4.9.0) (utils/cryptography/ECDSA.sol)\n\n/**\n * @dev Elliptic Curve Digital Signature Algorithm (ECDSA) operations.\n *\n * These functions can be used to verify that a message was signed by the holder\n * of the private keys of a given address.\n */\nlibrary ECDSA {\n enum RecoverError {\n NoError,\n InvalidSignature,\n InvalidSignatureLength,\n InvalidSignatureS,\n InvalidSignatureV // Deprecated in v4.8\n }\n\n function _throwError(RecoverError error) private pure {\n if (error == RecoverError.NoError) {\n return; // no error: do nothing\n } else if (error == RecoverError.InvalidSignature) {\n revert(\"ECDSA: invalid signature\");\n } else if (error == RecoverError.InvalidSignatureLength) {\n revert(\"ECDSA: invalid signature length\");\n } else if (error == RecoverError.InvalidSignatureS) {\n revert(\"ECDSA: invalid signature 's' value\");\n }\n }\n\n /**\n * @dev Returns the address that signed a hashed message (`hash`) with\n * `signature` or error string. This address can then be used for verification purposes.\n *\n * The `ecrecover` EVM opcode allows for malleable (non-unique) signatures:\n * this function rejects them by requiring the `s` value to be in the lower\n * half order, and the `v` value to be either 27 or 28.\n *\n * IMPORTANT: `hash` _must_ be the result of a hash operation for the\n * verification to be secure: it is possible to craft signatures that\n * recover to arbitrary addresses for non-hashed data. A safe way to ensure\n * this is by receiving a hash of the original message (which may otherwise\n * be too long), and then calling {toEthSignedMessageHash} on it.\n *\n * Documentation for signature generation:\n * - with https://web3js.readthedocs.io/en/v1.3.4/web3-eth-accounts.html#sign[Web3.js]\n * - with https://docs.ethers.io/v5/api/signer/#Signer-signMessage[ethers]\n *\n * _Available since v4.3._\n */\n function tryRecover(bytes32 hash, bytes memory signature) internal pure returns (address, RecoverError) {\n if (signature.length == 65) {\n bytes32 r;\n bytes32 s;\n uint8 v;\n // ecrecover takes the signature parameters, and the only way to get them\n // currently is to use assembly.\n /// @solidity memory-safe-assembly\n assembly {\n r := mload(add(signature, 0x20))\n s := mload(add(signature, 0x40))\n v := byte(0, mload(add(signature, 0x60)))\n }\n return tryRecover(hash, v, r, s);\n } else {\n return (address(0), RecoverError.InvalidSignatureLength);\n }\n }\n\n /**\n * @dev Returns the address that signed a hashed message (`hash`) with\n * `signature`. This address can then be used for verification purposes.\n *\n * The `ecrecover` EVM opcode allows for malleable (non-unique) signatures:\n * this function rejects them by requiring the `s` value to be in the lower\n * half order, and the `v` value to be either 27 or 28.\n *\n * IMPORTANT: `hash` _must_ be the result of a hash operation for the\n * verification to be secure: it is possible to craft signatures that\n * recover to arbitrary addresses for non-hashed data. A safe way to ensure\n * this is by receiving a hash of the original message (which may otherwise\n * be too long), and then calling {toEthSignedMessageHash} on it.\n */\n function recover(bytes32 hash, bytes memory signature) internal pure returns (address) {\n (address recovered, RecoverError error) = tryRecover(hash, signature);\n _throwError(error);\n return recovered;\n }\n\n /**\n * @dev Overload of {ECDSA-tryRecover} that receives the `r` and `vs` short-signature fields separately.\n *\n * See https://eips.ethereum.org/EIPS/eip-2098[EIP-2098 short signatures]\n *\n * _Available since v4.3._\n */\n function tryRecover(bytes32 hash, bytes32 r, bytes32 vs) internal pure returns (address, RecoverError) {\n bytes32 s = vs \u0026 bytes32(0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff);\n uint8 v = uint8((uint256(vs) \u003e\u003e 255) + 27);\n return tryRecover(hash, v, r, s);\n }\n\n /**\n * @dev Overload of {ECDSA-recover} that receives the `r and `vs` short-signature fields separately.\n *\n * _Available since v4.2._\n */\n function recover(bytes32 hash, bytes32 r, bytes32 vs) internal pure returns (address) {\n (address recovered, RecoverError error) = tryRecover(hash, r, vs);\n _throwError(error);\n return recovered;\n }\n\n /**\n * @dev Overload of {ECDSA-tryRecover} that receives the `v`,\n * `r` and `s` signature fields separately.\n *\n * _Available since v4.3._\n */\n function tryRecover(bytes32 hash, uint8 v, bytes32 r, bytes32 s) internal pure returns (address, RecoverError) {\n // EIP-2 still allows signature malleability for ecrecover(). Remove this possibility and make the signature\n // unique. Appendix F in the Ethereum Yellow paper (https://ethereum.github.io/yellowpaper/paper.pdf), defines\n // the valid range for s in (301): 0 \u003c s \u003c secp256k1n ÷ 2 + 1, and for v in (302): v ∈ {27, 28}. Most\n // signatures from current libraries generate a unique signature with an s-value in the lower half order.\n //\n // If your library generates malleable signatures, such as s-values in the upper range, calculate a new s-value\n // with 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141 - s1 and flip v from 27 to 28 or\n // vice versa. If your library also generates signatures with 0/1 for v instead 27/28, add 27 to v to accept\n // these malleable signatures as well.\n if (uint256(s) \u003e 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0) {\n return (address(0), RecoverError.InvalidSignatureS);\n }\n\n // If the signature is valid (and not malleable), return the signer address\n address signer = ecrecover(hash, v, r, s);\n if (signer == address(0)) {\n return (address(0), RecoverError.InvalidSignature);\n }\n\n return (signer, RecoverError.NoError);\n }\n\n /**\n * @dev Overload of {ECDSA-recover} that receives the `v`,\n * `r` and `s` signature fields separately.\n */\n function recover(bytes32 hash, uint8 v, bytes32 r, bytes32 s) internal pure returns (address) {\n (address recovered, RecoverError error) = tryRecover(hash, v, r, s);\n _throwError(error);\n return recovered;\n }\n\n /**\n * @dev Returns an Ethereum Signed Message, created from a `hash`. This\n * produces hash corresponding to the one signed with the\n * https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`]\n * JSON-RPC method as part of EIP-191.\n *\n * See {recover}.\n */\n function toEthSignedMessageHash(bytes32 hash) internal pure returns (bytes32 message) {\n // 32 is the length in bytes of hash,\n // enforced by the type signature above\n /// @solidity memory-safe-assembly\n assembly {\n mstore(0x00, \"\\x19Ethereum Signed Message:\\n32\")\n mstore(0x1c, hash)\n message := keccak256(0x00, 0x3c)\n }\n }\n\n /**\n * @dev Returns an Ethereum Signed Message, created from `s`. This\n * produces hash corresponding to the one signed with the\n * https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`]\n * JSON-RPC method as part of EIP-191.\n *\n * See {recover}.\n */\n function toEthSignedMessageHash(bytes memory s) internal pure returns (bytes32) {\n return keccak256(abi.encodePacked(\"\\x19Ethereum Signed Message:\\n\", Strings.toString(s.length), s));\n }\n\n /**\n * @dev Returns an Ethereum Signed Typed Data, created from a\n * `domainSeparator` and a `structHash`. This produces hash corresponding\n * to the one signed with the\n * https://eips.ethereum.org/EIPS/eip-712[`eth_signTypedData`]\n * JSON-RPC method as part of EIP-712.\n *\n * See {recover}.\n */\n function toTypedDataHash(bytes32 domainSeparator, bytes32 structHash) internal pure returns (bytes32 data) {\n /// @solidity memory-safe-assembly\n assembly {\n let ptr := mload(0x40)\n mstore(ptr, \"\\x19\\x01\")\n mstore(add(ptr, 0x02), domainSeparator)\n mstore(add(ptr, 0x22), structHash)\n data := keccak256(ptr, 0x42)\n }\n }\n\n /**\n * @dev Returns an Ethereum Signed Data with intended validator, created from a\n * `validator` and `data` according to the version 0 of EIP-191.\n *\n * See {recover}.\n */\n function toDataWithIntendedValidatorHash(address validator, bytes memory data) internal pure returns (bytes32) {\n return keccak256(abi.encodePacked(\"\\x19\\x00\", validator, data));\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/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/inbox/StatementInbox.sol\n\n// ══════════════════════════════ LIBRARY IMPORTS ══════════════════════════════\n\n// ═════════════════════════════ INTERNAL IMPORTS ══════════════════════════════\n\n// ═════════════════════════════ EXTERNAL IMPORTS ══════════════════════════════\n\n/// @notice `StatementInbox` is the entry point for all agent-signed statements. It verifies the\n/// agent signatures, and passes the unsigned statements to the contract to consume it via `acceptX` functions. Is is\n/// also used to verify the agent-signed statements and initiate the agent slashing, should the statement be invalid.\n/// `StatementInbox` is responsible for the following:\n/// - Accepting State and Receipt Reports to initiate a dispute between Guard and Notary.\n/// - Storing all the Guard Reports with the Guard signature leading to a dispute.\n/// - Verifying State/State Reports referencing the local chain and slashing the signer if statement is invalid.\n/// - Verifying Receipt/Receipt Reports referencing the local chain and slashing the signer if statement is invalid.\nabstract contract StatementInbox is MessagingBase, StatementInboxEvents, IStatementInbox {\n using AttestationLib for bytes;\n using ReceiptLib for bytes;\n using StateLib for bytes;\n using SnapshotLib for bytes;\n\n struct StoredReport {\n uint256 sigIndex;\n bytes statementPayload;\n }\n\n // ══════════════════════════════════════════════════ STORAGE ══════════════════════════════════════════════════════\n\n address public agentManager;\n address public origin;\n address public destination;\n\n // TODO: optimize this\n bytes[] internal _storedSignatures;\n StoredReport[] internal _storedReports;\n\n /// @dev gap for upgrade safety\n uint256[45] private __GAP; // solhint-disable-line var-name-mixedcase\n\n // ════════════════════════════════════════════════ INITIALIZER ════════════════════════════════════════════════════\n\n /// @dev Initializes the contract:\n /// - Sets up `msg.sender` as the owner of the contract.\n /// - Sets up `agentManager`, `origin`, and `destination`.\n // solhint-disable-next-line func-name-mixedcase\n function __StatementInbox_init(address agentManager_, address origin_, address destination_)\n internal\n onlyInitializing\n {\n agentManager = agentManager_;\n origin = origin_;\n destination = destination_;\n __Ownable2Step_init();\n }\n\n // ══════════════════════════════════════════ SUBMIT AGENT STATEMENTS ══════════════════════════════════════════════\n\n /// @inheritdoc IStatementInbox\n // solhint-disable-next-line ordering\n function submitStateReportWithSnapshot(\n uint8 stateIndex,\n bytes memory srSignature,\n bytes memory snapPayload,\n bytes memory snapSignature\n ) external returns (bool wasAccepted) {\n // This will revert if payload is not a snapshot\n Snapshot snapshot = snapPayload.castToSnapshot();\n // This will revert if the snapshot signer is not a known Notary\n (AgentStatus memory notaryStatus,) =\n _verifySnapshot({snapshot: snapshot, snapSignature: snapSignature, verifyNotary: true});\n // Notary needs to be Active/Unstaking\n notaryStatus.verifyActiveUnstaking();\n // Check if Notary is active on this chain\n _verifyNotaryDomain(notaryStatus.domain);\n // This will revert if state index is out of range\n State state = snapshot.state(stateIndex);\n // This will revert if the report signer is not an known Guard\n (AgentStatus memory guardStatus,) = _verifyStateReport(state, srSignature);\n // Check that Guard is active\n guardStatus.verifyActive();\n _saveReport(state.unwrap().clone(), srSignature);\n // This will revert if either actor is already in dispute\n IAgentManager(agentManager).openDispute(guardStatus.index, notaryStatus.index);\n return true;\n }\n\n /// @inheritdoc IStatementInbox\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 // This will revert if payload is not a snapshot\n Snapshot snapshot = snapPayload.castToSnapshot();\n // This will revert if state index is out of range\n State state = snapshot.state(stateIndex);\n // This will revert if the report signer is not an known Guard\n (AgentStatus memory guardStatus,) = _verifyStateReport(state, srSignature);\n // Check that Guard is active\n guardStatus.verifyActive();\n // This will revert if payload is not an attestation\n Attestation att = attPayload.castToAttestation();\n // This will revert if signer is not an known Notary\n (AgentStatus memory notaryStatus,) = _verifyAttestation(att, attSignature);\n // Notary needs to be Active/Unstaking\n notaryStatus.verifyActiveUnstaking();\n // Check if Notary is active on this chain\n _verifyNotaryDomain(notaryStatus.domain);\n if (snapshot.calculateRoot() != att.snapRoot()) revert IncorrectSnapshotRoot();\n _saveReport(state.unwrap().clone(), srSignature);\n // This will revert if either actor is already in dispute\n IAgentManager(agentManager).openDispute(guardStatus.index, notaryStatus.index);\n return true;\n }\n\n /// @inheritdoc IStatementInbox\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 // This will revert if payload is not a state\n State state = statePayload.castToState();\n // This will revert if the report signer is not an known Guard\n (AgentStatus memory guardStatus,) = _verifyStateReport(state, srSignature);\n // Check that Guard is active\n guardStatus.verifyActive();\n // This will revert if payload is not an attestation\n Attestation att = attPayload.castToAttestation();\n // This will revert if signer is not a known Notary\n (AgentStatus memory notaryStatus,) = _verifyAttestation(att, attSignature);\n // Notary needs to be Active/Unstaking\n notaryStatus.verifyActiveUnstaking();\n // Check if Notary is active on this chain\n _verifyNotaryDomain(notaryStatus.domain);\n // This will revert if any of these is true:\n // - Attestation root is not equal to Merkle Root derived from State and Snapshot Proof.\n // - Snapshot Proof's first element does not match the State metadata.\n // - Snapshot Proof length exceeds Snapshot tree Height.\n // - State index is out of range.\n _verifySnapshotMerkle(att, stateIndex, state, snapProof);\n _saveReport(statePayload, srSignature);\n // This will revert if either actor is already in dispute\n IAgentManager(agentManager).openDispute(guardStatus.index, notaryStatus.index);\n return true;\n }\n\n // ══════════════════════════════════════════ VERIFY AGENT STATEMENTS ══════════════════════════════════════════════\n\n /// @inheritdoc IStatementInbox\n function verifyReceipt(bytes memory rcptPayload, bytes memory rcptSignature)\n external\n returns (bool isValidReceipt)\n {\n // This will revert if payload is not a receipt\n Receipt rcpt = rcptPayload.castToReceipt();\n // This will revert if the attestation signer is not a known Notary\n (AgentStatus memory status, address notary) = _verifyReceipt(rcpt, rcptSignature);\n // Notary needs to be Active/Unstaking\n status.verifyActiveUnstaking();\n isValidReceipt = IExecutionHub(destination).isValidReceipt(rcptPayload);\n if (!isValidReceipt) {\n emit InvalidReceipt(rcptPayload, rcptSignature);\n IAgentManager(agentManager).slashAgent(status.domain, notary, msg.sender);\n }\n }\n\n /// @inheritdoc IStatementInbox\n function verifyReceiptReport(bytes memory rcptPayload, bytes memory rrSignature)\n external\n returns (bool isValidReport)\n {\n // This will revert if payload is not a receipt\n Receipt rcpt = rcptPayload.castToReceipt();\n // This will revert if the report signer is not a known Guard\n (AgentStatus memory status, address guard) = _verifyReceiptReport(rcpt, rrSignature);\n // Guard needs to be Active/Unstaking\n status.verifyActiveUnstaking();\n // Report is valid IF AND ONLY IF the reported receipt in invalid\n isValidReport = !IExecutionHub(destination).isValidReceipt(rcptPayload);\n if (!isValidReport) {\n emit InvalidReceiptReport(rcptPayload, rrSignature);\n IAgentManager(agentManager).slashAgent(status.domain, guard, msg.sender);\n }\n }\n\n /// @inheritdoc IStatementInbox\n function verifyStateWithAttestation(\n uint8 stateIndex,\n bytes memory snapPayload,\n bytes memory attPayload,\n bytes memory attSignature\n ) external returns (bool isValidState) {\n // This will revert if payload is not an attestation\n Attestation att = attPayload.castToAttestation();\n // This will revert if the attestation signer is not a known Notary\n (AgentStatus memory status, address notary) = _verifyAttestation(att, attSignature);\n // Notary needs to be Active/Unstaking\n status.verifyActiveUnstaking();\n // This will revert if payload is not a snapshot\n Snapshot snapshot = snapPayload.castToSnapshot();\n if (snapshot.calculateRoot() != att.snapRoot()) revert IncorrectSnapshotRoot();\n // This will revert if state does not refer to this chain\n bytes memory statePayload = snapshot.state(stateIndex).unwrap().clone();\n isValidState = IStateHub(origin).isValidState(statePayload);\n if (!isValidState) {\n emit InvalidStateWithAttestation(stateIndex, statePayload, attPayload, attSignature);\n IAgentManager(agentManager).slashAgent(status.domain, notary, msg.sender);\n }\n }\n\n /// @inheritdoc IStatementInbox\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 // This will revert if payload is not an attestation\n Attestation att = attPayload.castToAttestation();\n // This will revert if the attestation signer is not a known Notary\n (AgentStatus memory status, address notary) = _verifyAttestation(att, attSignature);\n // Notary needs to be Active/Unstaking\n status.verifyActiveUnstaking();\n // This will revert if payload is not a state\n State state = statePayload.castToState();\n // This will revert if any of these is true:\n // - Attestation root is not equal to Merkle Root derived from State and Snapshot Proof.\n // - Snapshot Proof's first element does not match the State metadata.\n // - Snapshot Proof length exceeds Snapshot tree Height.\n // - State index is out of range.\n _verifySnapshotMerkle(att, stateIndex, state, snapProof);\n // This will revert if state does not refer to this chain\n isValidState = IStateHub(origin).isValidState(statePayload);\n if (!isValidState) {\n emit InvalidStateWithAttestation(stateIndex, statePayload, attPayload, attSignature);\n IAgentManager(agentManager).slashAgent(status.domain, notary, msg.sender);\n }\n }\n\n /// @inheritdoc IStatementInbox\n function verifyStateWithSnapshot(uint8 stateIndex, bytes memory snapPayload, bytes memory snapSignature)\n external\n returns (bool isValidState)\n {\n // This will revert if payload is not a snapshot\n Snapshot snapshot = snapPayload.castToSnapshot();\n // This will revert if the snapshot signer is not a known Guard/Notary\n (AgentStatus memory status, address agent) =\n _verifySnapshot({snapshot: snapshot, snapSignature: snapSignature, verifyNotary: false});\n // Agent needs to be Active/Unstaking\n status.verifyActiveUnstaking();\n // This will revert if state does not refer to this chain\n isValidState = IStateHub(origin).isValidState(snapshot.state(stateIndex).unwrap().clone());\n if (!isValidState) {\n emit InvalidStateWithSnapshot(stateIndex, snapPayload, snapSignature);\n IAgentManager(agentManager).slashAgent(status.domain, agent, msg.sender);\n }\n }\n\n /// @inheritdoc IStatementInbox\n function verifyStateReport(bytes memory statePayload, bytes memory srSignature)\n external\n returns (bool isValidReport)\n {\n // This will revert if payload is not a state\n State state = statePayload.castToState();\n // This will revert if the report signer is not a known Guard\n (AgentStatus memory status, address guard) = _verifyStateReport(state, srSignature);\n // Guard needs to be Active/Unstaking\n status.verifyActiveUnstaking();\n // Report is valid IF AND ONLY IF the reported state in invalid\n // This will revert if the reported state does not refer to this chain\n isValidReport = !IStateHub(origin).isValidState(statePayload);\n if (!isValidReport) {\n emit InvalidStateReport(statePayload, srSignature);\n IAgentManager(agentManager).slashAgent(status.domain, guard, msg.sender);\n }\n }\n\n // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════\n\n /// @inheritdoc IStatementInbox\n function getReportsAmount() external view returns (uint256) {\n return _storedReports.length;\n }\n\n /// @inheritdoc IStatementInbox\n function getGuardReport(uint256 index)\n external\n view\n returns (bytes memory statementPayload, bytes memory reportSignature)\n {\n if (index \u003e= _storedReports.length) revert IndexOutOfRange();\n StoredReport memory storedReport = _storedReports[index];\n statementPayload = storedReport.statementPayload;\n reportSignature = _storedSignatures[storedReport.sigIndex];\n }\n\n /// @inheritdoc IStatementInbox\n function getStoredSignature(uint256 index) external view returns (bytes memory) {\n return _storedSignatures[index];\n }\n\n // ══════════════════════════════════════════════ INTERNAL LOGIC ═══════════════════════════════════════════════════\n\n /// @dev Saves the statement reported by Guard as invalid and the Guard Report signature.\n function _saveReport(bytes memory statementPayload, bytes memory reportSignature) internal {\n uint256 sigIndex = _saveSignature(reportSignature);\n _storedReports.push(StoredReport(sigIndex, statementPayload));\n }\n\n /// @dev Saves the signature and returns its index.\n function _saveSignature(bytes memory signature) internal returns (uint256 sigIndex) {\n sigIndex = _storedSignatures.length;\n _storedSignatures.push(signature);\n }\n\n // ═══════════════════════════════════════════════ AGENT CHECKS ════════════════════════════════════════════════════\n\n /**\n * @dev Recovers a signer from a hashed message, and a EIP-191 signature for it.\n * Will revert, if the signer is not a known agent.\n * @dev Agent flag could be any of these: Active/Unstaking/Resting/Fraudulent/Slashed\n * Further checks need to be performed in a caller function.\n * @param hashedStatement Hash of the statement that was signed by an Agent\n * @param signature Agent signature for the hashed statement\n * @return status Struct representing agent status:\n * - flag Unknown/Active/Unstaking/Resting/Fraudulent/Slashed\n * - domain Domain where agent is/was active\n * - index Index of agent in the Agent Merkle Tree\n * @return agent Agent that signed the statement\n */\n function _recoverAgent(bytes32 hashedStatement, bytes memory signature)\n internal\n view\n returns (AgentStatus memory status, address agent)\n {\n bytes32 ethSignedMsg = ECDSA.toEthSignedMessageHash(hashedStatement);\n agent = ECDSA.recover(ethSignedMsg, signature);\n status = IAgentManager(agentManager).agentStatus(agent);\n // Discard signature of unknown agents.\n // Further flag checks are supposed to be performed in a caller function.\n status.verifyKnown();\n }\n\n /// @dev Verifies that Notary signature is active on local domain.\n function _verifyNotaryDomain(uint32 notaryDomain) internal view {\n // Notary needs to be from the local domain (if contract is not deployed on Synapse Chain).\n // Or Notary could be from any domain (if contract is deployed on Synapse Chain).\n if (notaryDomain != localDomain \u0026\u0026 localDomain != synapseDomain) revert IncorrectAgentDomain();\n }\n\n // ════════════════════════════════════════ ATTESTATION RELATED CHECKS ═════════════════════════════════════════════\n\n /**\n * @dev Internal function to verify the signed attestation payload.\n * Reverts if any of these is true:\n * - Attestation signer is not a known Notary.\n * @param att Typed memory view over attestation payload\n * @param attSignature Notary signature for the attestation\n * @return status Struct representing agent status, see {_recoverAgent}\n * @return notary Notary that signed the snapshot\n */\n function _verifyAttestation(Attestation att, bytes memory attSignature)\n internal\n view\n returns (AgentStatus memory status, address notary)\n {\n // This will revert if signer is not a known agent\n (status, notary) = _recoverAgent(att.hashValid(), attSignature);\n // Attestation signer needs to be a Notary, not a Guard\n if (status.domain == 0) revert AgentNotNotary();\n }\n\n /**\n * @dev Internal function to verify the signed attestation report payload.\n * Reverts if any of these is true:\n * - Report signer is not a known Guard.\n * @param att Typed memory view over attestation payload that Guard reports as invalid\n * @param arSignature Guard signature for the \"invalid attestation\" report\n * @return status Struct representing guard status, see {_recoverAgent}\n * @return guard Guard that signed the report\n */\n function _verifyAttestationReport(Attestation att, bytes memory arSignature)\n internal\n view\n returns (AgentStatus memory status, address guard)\n {\n // This will revert if signer is not a known agent\n (status, guard) = _recoverAgent(att.hashInvalid(), arSignature);\n // Report signer needs to be a Guard, not a Notary\n if (status.domain != 0) revert AgentNotGuard();\n }\n\n // ══════════════════════════════════════════ RECEIPT RELATED CHECKS ═══════════════════════════════════════════════\n\n /**\n * @dev Internal function to verify the signed receipt payload.\n * Reverts if any of these is true:\n * - Receipt signer is not a known Notary.\n * @param rcpt Typed memory view over receipt payload\n * @param rcptSignature Notary signature for the receipt\n * @return status Struct representing agent status, see {_recoverAgent}\n * @return notary Notary that signed the snapshot\n */\n function _verifyReceipt(Receipt rcpt, bytes memory rcptSignature)\n internal\n view\n returns (AgentStatus memory status, address notary)\n {\n // This will revert if signer is not a known agent\n (status, notary) = _recoverAgent(rcpt.hashValid(), rcptSignature);\n // Receipt signer needs to be a Notary, not a Guard\n if (status.domain == 0) revert AgentNotNotary();\n }\n\n /**\n * @dev Internal function to verify the signed receipt report payload.\n * Reverts if any of these is true:\n * - Report signer is not a known Guard.\n * @param rcpt Typed memory view over receipt payload that Guard reports as invalid\n * @param rrSignature Guard signature for the \"invalid receipt\" report\n * @return status Struct representing guard status, see {_recoverAgent}\n * @return guard Guard that signed the report\n */\n function _verifyReceiptReport(Receipt rcpt, bytes memory rrSignature)\n internal\n view\n returns (AgentStatus memory status, address guard)\n {\n // This will revert if signer is not a known agent\n (status, guard) = _recoverAgent(rcpt.hashInvalid(), rrSignature);\n // Report signer needs to be a Guard, not a Notary\n if (status.domain != 0) revert AgentNotGuard();\n }\n\n // ═══════════════════════════════════════ STATE/SNAPSHOT RELATED CHECKS ═══════════════════════════════════════════\n\n /**\n * @dev Internal function to verify the signed snapshot report payload.\n * Reverts if any of these is true:\n * - Report signer is not a known Guard.\n * @param state Typed memory view over state payload that Guard reports as invalid\n * @param srSignature Guard signature for the report\n * @return status Struct representing guard status, see {_recoverAgent}\n * @return guard Guard that signed the report\n */\n function _verifyStateReport(State state, bytes memory srSignature)\n internal\n view\n returns (AgentStatus memory status, address guard)\n {\n // This will revert if signer is not a known agent\n (status, guard) = _recoverAgent(state.hashInvalid(), srSignature);\n // Report signer needs to be a Guard, not a Notary\n if (status.domain != 0) revert AgentNotGuard();\n }\n\n /**\n * @dev Internal function to verify the signed snapshot payload.\n * Reverts if any of these is true:\n * - Snapshot signer is not a known Agent.\n * - Snapshot signer is not a Notary (if verifyNotary is true).\n * @param snapshot Typed memory view over snapshot payload\n * @param snapSignature Agent signature for the snapshot\n * @param verifyNotary If true, snapshot signer needs to be a Notary, not a Guard\n * @return status Struct representing agent status, see {_recoverAgent}\n * @return agent Agent that signed the snapshot\n */\n function _verifySnapshot(Snapshot snapshot, bytes memory snapSignature, bool verifyNotary)\n internal\n view\n returns (AgentStatus memory status, address agent)\n {\n // This will revert if signer is not a known agent\n (status, agent) = _recoverAgent(snapshot.hashValid(), snapSignature);\n // If requested, snapshot signer needs to be a Notary, not a Guard\n if (verifyNotary \u0026\u0026 status.domain == 0) revert AgentNotNotary();\n }\n\n // ═══════════════════════════════════════════ MERKLE RELATED CHECKS ═══════════════════════════════════════════════\n\n /**\n * @dev Internal function to verify that snapshot roots match.\n * Reverts if any of these is true:\n * - Attestation root is not equal to Merkle Root derived from State and Snapshot Proof.\n * - Snapshot Proof's first element does not match the State metadata.\n * - Snapshot Proof length exceeds Snapshot tree Height.\n * - State index is out of range.\n * @param att Typed memory view over Attestation\n * @param stateIndex Index of state in the snapshot\n * @param state Typed memory view over the provided state payload\n * @param snapProof Raw payload with snapshot data\n */\n function _verifySnapshotMerkle(Attestation att, uint8 stateIndex, State state, bytes32[] memory snapProof)\n internal\n pure\n {\n // Snapshot proof first element should match State metadata (aka \"right sub-leaf\")\n (, bytes32 rightSubLeaf) = state.subLeafs();\n if (snapProof[0] != rightSubLeaf) revert IncorrectSnapshotProof();\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(state.root(), state.origin(), snapProof, stateIndex);\n // Snapshot root should match the attestation root\n if (att.snapRoot() != snapshotRoot) revert IncorrectSnapshotRoot();\n }\n}\n\n// contracts/inbox/Inbox.sol\n\n// ══════════════════════════════ LIBRARY IMPORTS ══════════════════════════════\n\n// ═════════════════════════════ INTERNAL IMPORTS ══════════════════════════════\n\n/// @notice `Inbox` is the child of `StatementInbox` contract, that is used on Synapse Chain.\n/// In addition to the functionality of `StatementInbox`, it also:\n/// - Accepts Guard and Notary Snapshots and passes them to `Summit` contract.\n/// - Accepts Notary-signed Receipts and passes them to `Summit` contract.\n/// - Accepts Receipt Reports to initiate a dispute between Guard and Notary.\n/// - Verifies Attestations and Attestation Reports, and slashes the signer if they are invalid.\ncontract Inbox is StatementInbox, InboxEvents, InterfaceInbox {\n using AttestationLib for bytes;\n using ReceiptLib for bytes;\n using SnapshotLib for bytes;\n\n // Struct to get around stack too deep error. TODO: revisit this\n struct ReceiptInfo {\n AgentStatus rcptNotaryStatus;\n address notary;\n uint32 attNonce;\n AgentStatus attNotaryStatus;\n }\n\n // ══════════════════════════════════════════════════ STORAGE ══════════════════════════════════════════════════════\n\n // The address of the Summit contract.\n address public summit;\n\n // ═════════════════════════════════════════ CONSTRUCTOR \u0026 INITIALIZER ═════════════════════════════════════════════\n\n constructor(uint32 synapseDomain_) MessagingBase(\"0.0.3\", synapseDomain_) {\n if (localDomain != synapseDomain) revert MustBeSynapseDomain();\n }\n\n /// @notice Initializes `Inbox` contract:\n /// - Sets `msg.sender` as the owner of the contract\n /// - Sets `agentManager`, `origin`, `destination` and `summit` addresses\n function initialize(address agentManager_, address origin_, address destination_, address summit_)\n external\n initializer\n {\n __StatementInbox_init(agentManager_, origin_, destination_);\n summit = summit_;\n }\n\n // ══════════════════════════════════════════ SUBMIT AGENT STATEMENTS ══════════════════════════════════════════════\n\n /// @inheritdoc InterfaceInbox\n function submitSnapshot(bytes memory snapPayload, bytes memory snapSignature)\n external\n returns (bytes memory attPayload, bytes32 agentRoot_, uint256[] memory snapGas)\n {\n // This will revert if payload is not a snapshot\n Snapshot snapshot = snapPayload.castToSnapshot();\n // This will revert if the signer is not a known Guard/Notary\n (AgentStatus memory status, address agent) =\n _verifySnapshot({snapshot: snapshot, snapSignature: snapSignature, verifyNotary: false});\n // Check that Agent is active\n status.verifyActive();\n // Store Agent signature for the Snapshot\n uint256 sigIndex = _saveSignature(snapSignature);\n if (status.domain == 0) {\n // Guard that is in Dispute could still submit new snapshots, so we don't check that\n InterfaceSummit(summit).acceptGuardSnapshot({\n guardIndex: status.index,\n sigIndex: sigIndex,\n snapPayload: snapPayload\n });\n } else {\n // Get current agentRoot from AgentManager\n agentRoot_ = IAgentManager(agentManager).agentRoot();\n // This will revert if Notary is in Dispute\n attPayload = InterfaceSummit(summit).acceptNotarySnapshot({\n notaryIndex: status.index,\n sigIndex: sigIndex,\n agentRoot: agentRoot_,\n snapPayload: snapPayload\n });\n ChainGas[] memory snapGas_ = snapshot.snapGas();\n // Pass created attestation to Destination to enable executing messages coming to Synapse Chain\n InterfaceDestination(destination).acceptAttestation(\n status.index, type(uint256).max, attPayload, agentRoot_, snapGas_\n );\n // Use assembly to cast ChainGas[] to uint256[] without copying. Highest bits are left zeroed.\n // solhint-disable-next-line no-inline-assembly\n assembly {\n snapGas := snapGas_\n }\n }\n emit SnapshotAccepted(status.domain, agent, snapPayload, snapSignature);\n }\n\n /// @inheritdoc InterfaceInbox\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 // Struct to get around stack too deep error.\n ReceiptInfo memory info;\n // This will revert if payload is not a receipt\n Receipt rcpt = rcptPayload.castToReceipt();\n // This will revert if the receipt signer is not a known Notary\n (info.rcptNotaryStatus, info.notary) = _verifyReceipt(rcpt, rcptSignature);\n // Receipt Notary needs to be Active\n info.rcptNotaryStatus.verifyActive();\n info.attNonce = IExecutionHub(destination).getAttestationNonce(rcpt.snapshotRoot());\n if (info.attNonce == 0) revert IncorrectSnapshotRoot();\n // Attestation Notary domain needs to match the destination domain\n info.attNotaryStatus = IAgentManager(agentManager).agentStatus(rcpt.attNotary());\n if (info.attNotaryStatus.domain != rcpt.destination()) revert IncorrectAgentDomain();\n // Check that the correct tip values for the message were provided\n _verifyReceiptTips(rcpt.messageHash(), paddedTips, headerHash, bodyHash);\n // Store Notary signature for the Receipt\n uint256 sigIndex = _saveSignature(rcptSignature);\n // This will revert if Receipt Notary is in Dispute\n wasAccepted = InterfaceSummit(summit).acceptReceipt({\n rcptNotaryIndex: info.rcptNotaryStatus.index,\n attNotaryIndex: info.attNotaryStatus.index,\n sigIndex: sigIndex,\n attNonce: info.attNonce,\n paddedTips: paddedTips,\n rcptPayload: rcptPayload\n });\n if (wasAccepted) {\n emit ReceiptAccepted(info.rcptNotaryStatus.domain, info.notary, rcptPayload, rcptSignature);\n }\n }\n\n /// @inheritdoc InterfaceInbox\n function submitReceiptReport(bytes memory rcptPayload, bytes memory rcptSignature, bytes memory rrSignature)\n external\n returns (bool wasAccepted)\n {\n // This will revert if payload is not a receipt\n Receipt rcpt = rcptPayload.castToReceipt();\n // This will revert if the receipt signer is not a known Guard\n (AgentStatus memory guardStatus,) = _verifyReceiptReport(rcpt, rrSignature);\n // Guard needs to be Active\n guardStatus.verifyActive();\n // This will revert if report signer is not a known Notary\n (AgentStatus memory notaryStatus,) = _verifyReceipt(rcpt, rcptSignature);\n // Notary needs to be Active/Unstaking\n notaryStatus.verifyActiveUnstaking();\n _saveReport(rcptPayload, rrSignature);\n // This will revert if either actor is already in dispute\n IAgentManager(agentManager).openDispute(guardStatus.index, notaryStatus.index);\n return true;\n }\n\n /// @inheritdoc InterfaceInbox\n function passReceipt(uint32 attNotaryIndex, uint32 attNonce, uint256 paddedTips, bytes memory rcptPayload)\n external\n returns (bool wasAccepted)\n {\n // Only Destination can pass receipts\n if (msg.sender != destination) revert CallerNotDestination();\n return InterfaceSummit(summit).acceptReceipt({\n rcptNotaryIndex: attNotaryIndex,\n attNotaryIndex: attNotaryIndex,\n sigIndex: type(uint256).max,\n attNonce: attNonce,\n paddedTips: paddedTips,\n rcptPayload: rcptPayload\n });\n }\n\n // ══════════════════════════════════════════ VERIFY AGENT STATEMENTS ══════════════════════════════════════════════\n\n /// @inheritdoc InterfaceInbox\n function verifyAttestation(bytes memory attPayload, bytes memory attSignature)\n external\n returns (bool isValidAttestation)\n {\n // This will revert if payload is not an attestation\n Attestation att = attPayload.castToAttestation();\n // This will revert if the attestation signer is not a known Notary\n (AgentStatus memory status, address notary) = _verifyAttestation(att, attSignature);\n // Notary needs to be Active/Unstaking\n status.verifyActiveUnstaking();\n isValidAttestation = ISnapshotHub(summit).isValidAttestation(attPayload);\n if (!isValidAttestation) {\n emit InvalidAttestation(attPayload, attSignature);\n IAgentManager(agentManager).slashAgent(status.domain, notary, msg.sender);\n }\n }\n\n /// @inheritdoc InterfaceInbox\n function verifyAttestationReport(bytes memory attPayload, bytes memory arSignature)\n external\n returns (bool isValidReport)\n {\n // This will revert if payload is not an attestation\n Attestation att = attPayload.castToAttestation();\n // This will revert if the report signer is not a known Guard\n (AgentStatus memory status, address guard) = _verifyAttestationReport(att, arSignature);\n // Guard needs to be Active/Unstaking\n status.verifyActiveUnstaking();\n // Report is valid IF AND ONLY IF the reported attestation in invalid\n isValidReport = !ISnapshotHub(summit).isValidAttestation(attPayload);\n if (!isValidReport) {\n emit InvalidAttestationReport(attPayload, arSignature);\n IAgentManager(agentManager).slashAgent(status.domain, guard, msg.sender);\n }\n }\n\n // ══════════════════════════════════════════════ INTERNAL VIEWS ═══════════════════════════════════════════════════\n\n /// @dev Verifies that tips proof matches the message hash.\n function _verifyReceiptTips(bytes32 msgHash, uint256 paddedTips, bytes32 headerHash, bytes32 bodyHash)\n internal\n pure\n {\n Tips tips = TipsLib.wrapPadded(paddedTips);\n // full message leaf is (header, baseMessage), while base message leaf is (tips, remainingBody).\n if (MerkleMath.getParent(headerHash, MerkleMath.getParent(tips.leaf(), bodyHash)) != msgHash) {\n revert IncorrectTipsProof();\n }\n }\n}\n","language":"Solidity","languageVersion":"0.8.17","compilerVersion":"0.8.17","compilerOptions":"--combined-json bin,bin-runtime,srcmap,srcmap-runtime,abi,userdoc,devdoc,metadata,hashes --optimize --optimize-runs 10000 --allow-paths ., ./, ../","srcMap":"238314:7877:0:-:0;;;;;;;;;;;;;;;-1:-1:-1;;;238314:7877:0;;;;;;;;;;;;;;;;;","srcMapRuntime":"238314: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/Inbox.sol\":\"SnapshotLib\"},\"evmVersion\":\"london\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\"},\"optimizer\":{\"enabled\":true,\"runs\":10000},\"remappings\":[]},\"sources\":{\"solidity/Inbox.sol\":{\"keccak256\":\"0x9b516081a036814c0169e20e484d4a5499066b7a6f48fada952b5e844a1ca3e5\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://32bde393b3f24ef4307d9626d4143f337b3c0bd34e17bb969fd5a15221d96987\",\"dweb:/ipfs/QmTkt2XZRtgsbSpmsVQUM3c4ebETQoDVYbmEV9yheBghnr\"]}},\"version\":1}"},"hashes":{}},"solidity/Inbox.sol:StateLib":{"code":"0x60566037600b82828239805160001a607314602a57634e487b7160e01b600052600060045260246000fd5b30600052607381538281f3fe73000000000000000000000000000000000000000030146080604052600080fdfea26469706673582212209eb042fcfba112f02dbddd50c463b1988d945ecf0cbbcc7a3aa1a7f75ebc322964736f6c63430008110033","runtime-code":"0x73000000000000000000000000000000000000000030146080604052600080fdfea26469706673582212209eb042fcfba112f02dbddd50c463b1988d945ecf0cbbcc7a3aa1a7f75ebc322964736f6c63430008110033","info":{"source":"// SPDX-License-Identifier: MIT\npragma solidity =0.8.17 ^0.8.0 ^0.8.1 ^0.8.2;\n\n// contracts/events/InboxEvents.sol\n\nabstract contract InboxEvents {\n /**\n * @notice Emitted when a snapshot is accepted by the Summit contract.\n * @param domain Domain where the signed Agent is active (ZERO for Guards)\n * @param agent Agent who signed the snapshot\n * @param snapPayload Raw payload with snapshot data\n * @param snapSignature Agent signature for the snapshot\n */\n event SnapshotAccepted(uint32 indexed domain, address indexed agent, bytes snapPayload, bytes snapSignature);\n\n /**\n * @notice Emitted when a snapshot is accepted by the Summit contract.\n * @param domain Domain where the signed Notary is active\n * @param notary Notary who signed the attestation\n * @param rcptPayload Raw payload with receipt data\n * @param rcptSignature Notary signature for the receipt\n */\n event ReceiptAccepted(uint32 domain, address notary, bytes rcptPayload, bytes rcptSignature);\n\n /**\n * @notice Emitted when a proof of invalid attestation is submitted.\n * @param attPayload Raw payload with Attestation data\n * @param attSignature Notary signature for the attestation\n */\n event InvalidAttestation(bytes attPayload, bytes attSignature);\n\n /**\n * @notice Emitted when a proof of invalid attestation report is submitted.\n * @param arPayload Raw payload with report data\n * @param arSignature Guard signature for the report\n */\n event InvalidAttestationReport(bytes arPayload, bytes arSignature);\n}\n\n// contracts/events/StatementInboxEvents.sol\n\nabstract contract StatementInboxEvents {\n // ════════════════════════════════════════════ STATEMENT ACCEPTED ═════════════════════════════════════════════════\n\n /**\n * @notice Emitted when a snapshot is accepted by the Destination contract.\n * @param domain Domain where the signed Notary is active\n * @param notary Notary who signed the attestation\n * @param attPayload Raw payload with attestation data\n * @param attSignature Notary signature for the attestation\n */\n event AttestationAccepted(uint32 domain, address notary, bytes attPayload, bytes attSignature);\n\n // ═════════════════════════════════════════ INVALID STATEMENT PROVED ══════════════════════════════════════════════\n\n /**\n * @notice Emitted when a proof of invalid receipt statement is submitted.\n * @param rcptPayload Raw payload with the receipt statement\n * @param rcptSignature Notary signature for the receipt statement\n */\n event InvalidReceipt(bytes rcptPayload, bytes rcptSignature);\n\n /**\n * @notice Emitted when a proof of invalid receipt report is submitted.\n * @param rrPayload Raw payload with report data\n * @param rrSignature Guard signature for the report\n */\n event InvalidReceiptReport(bytes rrPayload, bytes rrSignature);\n\n /**\n * @notice Emitted when a proof of invalid state in the signed attestation is submitted.\n * @param stateIndex Index of invalid state in the snapshot\n * @param statePayload Raw payload with state data\n * @param attPayload Raw payload with Attestation data for snapshot\n * @param attSignature Notary signature for the attestation\n */\n event InvalidStateWithAttestation(uint8 stateIndex, bytes statePayload, bytes attPayload, bytes attSignature);\n\n /**\n * @notice Emitted when a proof of invalid state in the signed snapshot is submitted.\n * @param stateIndex Index of invalid state in the snapshot\n * @param snapPayload Raw payload with snapshot data\n * @param snapSignature Agent signature for the snapshot\n */\n event InvalidStateWithSnapshot(uint8 stateIndex, bytes snapPayload, bytes snapSignature);\n\n /**\n * @notice Emitted when a proof of invalid state report is submitted.\n * @param srPayload Raw payload with report data\n * @param srSignature Guard signature for the report\n */\n event InvalidStateReport(bytes srPayload, bytes srSignature);\n}\n\n// contracts/interfaces/ISnapshotHub.sol\n\ninterface ISnapshotHub {\n /**\n * @notice Check that a given attestation is valid: matches the historical attestation\n * derived from an accepted Notary snapshot.\n * @dev Will revert if any of these is true:\n * - Attestation payload is not properly formatted.\n * @param attPayload Raw payload with attestation data\n * @return isValid Whether the provided attestation is valid\n */\n function isValidAttestation(bytes memory attPayload) external view returns (bool isValid);\n\n /**\n * @notice Returns saved attestation with the given nonce.\n * @dev Reverts if attestation with given nonce hasn't been created yet.\n * @param attNonce Nonce for the attestation\n * @return attPayload Raw payload with formatted Attestation data\n * @return agentRoot Agent root hash used for the attestation\n * @return snapGas Snapshot gas data used for the attestation\n */\n function getAttestation(uint32 attNonce)\n external\n view\n returns (bytes memory attPayload, bytes32 agentRoot, uint256[] memory snapGas);\n\n /**\n * @notice Returns the state with the highest known nonce submitted by a given Agent.\n * @param origin Domain of origin chain\n * @param agent Agent address\n * @return statePayload Raw payload with agent's latest state for origin\n */\n function getLatestAgentState(uint32 origin, address agent) external view returns (bytes memory statePayload);\n\n /**\n * @notice Returns latest saved attestation for a Notary.\n * @param notary Notary address\n * @return attPayload Raw payload with formatted Attestation data\n * @return agentRoot Agent root hash used for the attestation\n * @return snapGas Snapshot gas data used for the attestation\n */\n function getLatestNotaryAttestation(address notary)\n external\n view\n returns (bytes memory attPayload, bytes32 agentRoot, uint256[] memory snapGas);\n\n /**\n * @notice Returns Guard snapshot from the list of all accepted Guard snapshots.\n * @dev Reverts if snapshot with given index hasn't been accepted yet.\n * @param index Snapshot index in the list of all Guard snapshots\n * @return snapPayload Raw payload with Guard snapshot\n * @return snapSignature Raw payload with Guard signature for snapshot\n */\n function getGuardSnapshot(uint256 index)\n external\n view\n returns (bytes memory snapPayload, bytes memory snapSignature);\n\n /**\n * @notice Returns Notary snapshot from the list of all accepted Guard snapshots.\n * @dev Reverts if snapshot with given index hasn't been accepted yet.\n * @param index Snapshot index in the list of all Notary snapshots\n * @return snapPayload Raw payload with Notary snapshot\n * @return snapSignature Raw payload with Notary signature for snapshot\n */\n function getNotarySnapshot(uint256 index)\n external\n view\n returns (bytes memory snapPayload, bytes memory snapSignature);\n\n /**\n * @notice Returns Notary snapshot that was used for creating a given attestation.\n * @dev Reverts if any of these is true:\n * - Attestation payload is not properly formatted.\n * - Attestation is invalid (doesn't have a matching Notary snapshot).\n * @param attPayload Raw payload with attestation data\n * @return snapPayload Raw payload with Notary snapshot\n * @return snapSignature Raw payload with Notary signature for snapshot\n */\n function getNotarySnapshot(bytes memory attPayload)\n external\n view\n returns (bytes memory snapPayload, bytes memory snapSignature);\n\n /**\n * @notice Returns proof of inclusion of (root, origin) fields of a given snapshot's state\n * into the Snapshot Merkle Tree for a given attestation.\n * @dev Reverts if any of these is true:\n * - Attestation with given nonce hasn't been created yet.\n * - State index is out of range of snapshot list.\n * @param attNonce Nonce for the attestation\n * @param stateIndex Index of state in the attestation's snapshot\n * @return snapProof The snapshot proof\n */\n function getSnapshotProof(uint32 attNonce, uint8 stateIndex) external view returns (bytes32[] memory snapProof);\n}\n\n// contracts/interfaces/IStateHub.sol\n\ninterface IStateHub {\n /**\n * @notice Check that a given state is valid: matches the historical state of Origin contract.\n * Note: any Agent including an invalid state in their snapshot will be slashed\n * upon providing the snapshot and agent signature for it to Origin contract.\n * @dev Will revert if any of these is true:\n * - State payload is not properly formatted.\n * @param statePayload Raw payload with state data\n * @return isValid Whether the provided state is valid\n */\n function isValidState(bytes memory statePayload) external view returns (bool isValid);\n\n /**\n * @notice Returns the amount of saved states so far.\n * @dev This includes the initial state of \"empty Origin Merkle Tree\".\n */\n function statesAmount() external view returns (uint256);\n\n /**\n * @notice Suggest the data (state after latest sent message) to sign for an Agent.\n * Note: signing the suggested state data will will never lead to slashing of the actor,\n * assuming they have confirmed that the block, which number is included in the data,\n * is not subject to reorganization (which is different for every observed chain).\n * @return statePayload Raw payload with the latest state data\n */\n function suggestLatestState() external view returns (bytes memory statePayload);\n\n /**\n * @notice Given the historical nonce, suggest the state data to sign for an Agent.\n * Note: signing the suggested state data will will never lead to slashing of the actor,\n * assuming they have confirmed that the block, which number is included in the data,\n * is not subject to reorganization (which is different for every observed chain).\n * @param nonce Historical nonce to form a state\n * @return statePayload Raw payload with historical state data\n */\n function suggestState(uint32 nonce) external view returns (bytes memory statePayload);\n}\n\n// contracts/interfaces/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/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// node_modules/@openzeppelin/contracts/utils/math/Math.sol\n\n// OpenZeppelin Contracts (last updated v4.9.0) (utils/math/Math.sol)\n\n/**\n * @dev Standard math utilities missing in the Solidity language.\n */\nlibrary Math {\n enum Rounding {\n Down, // Toward negative infinity\n Up, // Toward infinity\n Zero // Toward zero\n }\n\n /**\n * @dev Returns the largest of two numbers.\n */\n function max(uint256 a, uint256 b) internal pure returns (uint256) {\n return a \u003e b ? a : b;\n }\n\n /**\n * @dev Returns the smallest of two numbers.\n */\n function min(uint256 a, uint256 b) internal pure returns (uint256) {\n return a \u003c b ? a : b;\n }\n\n /**\n * @dev Returns the average of two numbers. The result is rounded towards\n * zero.\n */\n function average(uint256 a, uint256 b) internal pure returns (uint256) {\n // (a + b) / 2 can overflow.\n return (a \u0026 b) + (a ^ b) / 2;\n }\n\n /**\n * @dev Returns the ceiling of the division of two numbers.\n *\n * This differs from standard division with `/` in that it rounds up instead\n * of rounding down.\n */\n function ceilDiv(uint256 a, uint256 b) internal pure returns (uint256) {\n // (a + b - 1) / b can overflow on addition, so we distribute.\n return a == 0 ? 0 : (a - 1) / b + 1;\n }\n\n /**\n * @notice Calculates floor(x * y / denominator) with full precision. Throws if result overflows a uint256 or denominator == 0\n * @dev Original credit to Remco Bloemen under MIT license (https://xn--2-umb.com/21/muldiv)\n * with further edits by Uniswap Labs also under MIT license.\n */\n function mulDiv(uint256 x, uint256 y, uint256 denominator) internal pure returns (uint256 result) {\n unchecked {\n // 512-bit multiply [prod1 prod0] = x * y. Compute the product mod 2^256 and mod 2^256 - 1, then use\n // use the Chinese Remainder Theorem to reconstruct the 512 bit result. The result is stored in two 256\n // variables such that product = prod1 * 2^256 + prod0.\n uint256 prod0; // Least significant 256 bits of the product\n uint256 prod1; // Most significant 256 bits of the product\n assembly {\n let mm := mulmod(x, y, not(0))\n prod0 := mul(x, y)\n prod1 := sub(sub(mm, prod0), lt(mm, prod0))\n }\n\n // Handle non-overflow cases, 256 by 256 division.\n if (prod1 == 0) {\n // Solidity will revert if denominator == 0, unlike the div opcode on its own.\n // The surrounding unchecked block does not change this fact.\n // See https://docs.soliditylang.org/en/latest/control-structures.html#checked-or-unchecked-arithmetic.\n return prod0 / denominator;\n }\n\n // Make sure the result is less than 2^256. Also prevents denominator == 0.\n require(denominator \u003e prod1, \"Math: mulDiv overflow\");\n\n ///////////////////////////////////////////////\n // 512 by 256 division.\n ///////////////////////////////////////////////\n\n // Make division exact by subtracting the remainder from [prod1 prod0].\n uint256 remainder;\n assembly {\n // Compute remainder using mulmod.\n remainder := mulmod(x, y, denominator)\n\n // Subtract 256 bit number from 512 bit number.\n prod1 := sub(prod1, gt(remainder, prod0))\n prod0 := sub(prod0, remainder)\n }\n\n // Factor powers of two out of denominator and compute largest power of two divisor of denominator. Always \u003e= 1.\n // See https://cs.stackexchange.com/q/138556/92363.\n\n // Does not overflow because the denominator cannot be zero at this stage in the function.\n uint256 twos = denominator \u0026 (~denominator + 1);\n assembly {\n // Divide denominator by twos.\n denominator := div(denominator, twos)\n\n // Divide [prod1 prod0] by twos.\n prod0 := div(prod0, twos)\n\n // Flip twos such that it is 2^256 / twos. If twos is zero, then it becomes one.\n twos := add(div(sub(0, twos), twos), 1)\n }\n\n // Shift in bits from prod1 into prod0.\n prod0 |= prod1 * twos;\n\n // Invert denominator mod 2^256. Now that denominator is an odd number, it has an inverse modulo 2^256 such\n // that denominator * inv = 1 mod 2^256. Compute the inverse by starting with a seed that is correct for\n // four bits. That is, denominator * inv = 1 mod 2^4.\n uint256 inverse = (3 * denominator) ^ 2;\n\n // Use the Newton-Raphson iteration to improve the precision. Thanks to Hensel's lifting lemma, this also works\n // in modular arithmetic, doubling the correct bits in each step.\n inverse *= 2 - denominator * inverse; // inverse mod 2^8\n inverse *= 2 - denominator * inverse; // inverse mod 2^16\n inverse *= 2 - denominator * inverse; // inverse mod 2^32\n inverse *= 2 - denominator * inverse; // inverse mod 2^64\n inverse *= 2 - denominator * inverse; // inverse mod 2^128\n inverse *= 2 - denominator * inverse; // inverse mod 2^256\n\n // Because the division is now exact we can divide by multiplying with the modular inverse of denominator.\n // This will give us the correct result modulo 2^256. Since the preconditions guarantee that the outcome is\n // less than 2^256, this is the final result. We don't need to compute the high bits of the result and prod1\n // is no longer required.\n result = prod0 * inverse;\n return result;\n }\n }\n\n /**\n * @notice Calculates x * y / denominator with full precision, following the selected rounding direction.\n */\n function mulDiv(uint256 x, uint256 y, uint256 denominator, Rounding rounding) internal pure returns (uint256) {\n uint256 result = mulDiv(x, y, denominator);\n if (rounding == Rounding.Up \u0026\u0026 mulmod(x, y, denominator) \u003e 0) {\n result += 1;\n }\n return result;\n }\n\n /**\n * @dev Returns the square root of a number. If the number is not a perfect square, the value is rounded down.\n *\n * Inspired by Henry S. Warren, Jr.'s \"Hacker's Delight\" (Chapter 11).\n */\n function sqrt(uint256 a) internal pure returns (uint256) {\n if (a == 0) {\n return 0;\n }\n\n // For our first guess, we get the biggest power of 2 which is smaller than the square root of the target.\n //\n // We know that the \"msb\" (most significant bit) of our target number `a` is a power of 2 such that we have\n // `msb(a) \u003c= a \u003c 2*msb(a)`. This value can be written `msb(a)=2**k` with `k=log2(a)`.\n //\n // This can be rewritten `2**log2(a) \u003c= a \u003c 2**(log2(a) + 1)`\n // → `sqrt(2**k) \u003c= sqrt(a) \u003c sqrt(2**(k+1))`\n // → `2**(k/2) \u003c= sqrt(a) \u003c 2**((k+1)/2) \u003c= 2**(k/2 + 1)`\n //\n // Consequently, `2**(log2(a) / 2)` is a good first approximation of `sqrt(a)` with at least 1 correct bit.\n uint256 result = 1 \u003c\u003c (log2(a) \u003e\u003e 1);\n\n // At this point `result` is an estimation with one bit of precision. We know the true value is a uint128,\n // since it is the square root of a uint256. Newton's method converges quadratically (precision doubles at\n // every iteration). We thus need at most 7 iteration to turn our partial result with one bit of precision\n // into the expected uint128 result.\n unchecked {\n result = (result + a / result) \u003e\u003e 1;\n result = (result + a / result) \u003e\u003e 1;\n result = (result + a / result) \u003e\u003e 1;\n result = (result + a / result) \u003e\u003e 1;\n result = (result + a / result) \u003e\u003e 1;\n result = (result + a / result) \u003e\u003e 1;\n result = (result + a / result) \u003e\u003e 1;\n return min(result, a / result);\n }\n }\n\n /**\n * @notice Calculates sqrt(a), following the selected rounding direction.\n */\n function sqrt(uint256 a, Rounding rounding) internal pure returns (uint256) {\n unchecked {\n uint256 result = sqrt(a);\n return result + (rounding == Rounding.Up \u0026\u0026 result * result \u003c a ? 1 : 0);\n }\n }\n\n /**\n * @dev Return the log in base 2, rounded down, of a positive value.\n * Returns 0 if given 0.\n */\n function log2(uint256 value) internal pure returns (uint256) {\n uint256 result = 0;\n unchecked {\n if (value \u003e\u003e 128 \u003e 0) {\n value \u003e\u003e= 128;\n result += 128;\n }\n if (value \u003e\u003e 64 \u003e 0) {\n value \u003e\u003e= 64;\n result += 64;\n }\n if (value \u003e\u003e 32 \u003e 0) {\n value \u003e\u003e= 32;\n result += 32;\n }\n if (value \u003e\u003e 16 \u003e 0) {\n value \u003e\u003e= 16;\n result += 16;\n }\n if (value \u003e\u003e 8 \u003e 0) {\n value \u003e\u003e= 8;\n result += 8;\n }\n if (value \u003e\u003e 4 \u003e 0) {\n value \u003e\u003e= 4;\n result += 4;\n }\n if (value \u003e\u003e 2 \u003e 0) {\n value \u003e\u003e= 2;\n result += 2;\n }\n if (value \u003e\u003e 1 \u003e 0) {\n result += 1;\n }\n }\n return result;\n }\n\n /**\n * @dev Return the log in base 2, following the selected rounding direction, of a positive value.\n * Returns 0 if given 0.\n */\n function log2(uint256 value, Rounding rounding) internal pure returns (uint256) {\n unchecked {\n uint256 result = log2(value);\n return result + (rounding == Rounding.Up \u0026\u0026 1 \u003c\u003c result \u003c value ? 1 : 0);\n }\n }\n\n /**\n * @dev Return the log in base 10, rounded down, of a positive value.\n * Returns 0 if given 0.\n */\n function log10(uint256 value) internal pure returns (uint256) {\n uint256 result = 0;\n unchecked {\n if (value \u003e= 10 ** 64) {\n value /= 10 ** 64;\n result += 64;\n }\n if (value \u003e= 10 ** 32) {\n value /= 10 ** 32;\n result += 32;\n }\n if (value \u003e= 10 ** 16) {\n value /= 10 ** 16;\n result += 16;\n }\n if (value \u003e= 10 ** 8) {\n value /= 10 ** 8;\n result += 8;\n }\n if (value \u003e= 10 ** 4) {\n value /= 10 ** 4;\n result += 4;\n }\n if (value \u003e= 10 ** 2) {\n value /= 10 ** 2;\n result += 2;\n }\n if (value \u003e= 10 ** 1) {\n result += 1;\n }\n }\n return result;\n }\n\n /**\n * @dev Return the log in base 10, following the selected rounding direction, of a positive value.\n * Returns 0 if given 0.\n */\n function log10(uint256 value, Rounding rounding) internal pure returns (uint256) {\n unchecked {\n uint256 result = log10(value);\n return result + (rounding == Rounding.Up \u0026\u0026 10 ** result \u003c value ? 1 : 0);\n }\n }\n\n /**\n * @dev Return the log in base 256, rounded down, of a positive value.\n * Returns 0 if given 0.\n *\n * Adding one to the result gives the number of pairs of hex symbols needed to represent `value` as a hex string.\n */\n function log256(uint256 value) internal pure returns (uint256) {\n uint256 result = 0;\n unchecked {\n if (value \u003e\u003e 128 \u003e 0) {\n value \u003e\u003e= 128;\n result += 16;\n }\n if (value \u003e\u003e 64 \u003e 0) {\n value \u003e\u003e= 64;\n result += 8;\n }\n if (value \u003e\u003e 32 \u003e 0) {\n value \u003e\u003e= 32;\n result += 4;\n }\n if (value \u003e\u003e 16 \u003e 0) {\n value \u003e\u003e= 16;\n result += 2;\n }\n if (value \u003e\u003e 8 \u003e 0) {\n result += 1;\n }\n }\n return result;\n }\n\n /**\n * @dev Return the log in base 256, following the selected rounding direction, of a positive value.\n * Returns 0 if given 0.\n */\n function log256(uint256 value, Rounding rounding) internal pure returns (uint256) {\n unchecked {\n uint256 result = log256(value);\n return result + (rounding == Rounding.Up \u0026\u0026 1 \u003c\u003c (result \u003c\u003c 3) \u003c value ? 1 : 0);\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/utils/math/SignedMath.sol\n\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/math/SignedMath.sol)\n\n/**\n * @dev Standard signed math utilities missing in the Solidity language.\n */\nlibrary SignedMath {\n /**\n * @dev Returns the largest of two signed numbers.\n */\n function max(int256 a, int256 b) internal pure returns (int256) {\n return a \u003e b ? a : b;\n }\n\n /**\n * @dev Returns the smallest of two signed numbers.\n */\n function min(int256 a, int256 b) internal pure returns (int256) {\n return a \u003c b ? a : b;\n }\n\n /**\n * @dev Returns the average of two signed numbers without overflow.\n * The result is rounded towards zero.\n */\n function average(int256 a, int256 b) internal pure returns (int256) {\n // Formula from the book \"Hacker's Delight\"\n int256 x = (a \u0026 b) + ((a ^ b) \u003e\u003e 1);\n return x + (int256(uint256(x) \u003e\u003e 255) \u0026 (a ^ b));\n }\n\n /**\n * @dev Returns the absolute unsigned value of a signed value.\n */\n function abs(int256 n) internal pure returns (uint256) {\n unchecked {\n // must be unchecked in order to support `n = type(int256).min`\n return uint256(n \u003e= 0 ? n : -n);\n }\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// 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/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/InterfaceSummit.sol\n\ninterface InterfaceSummit {\n // ══════════════════════════════════════════ ACCEPT AGENT STATEMENTS ══════════════════════════════════════════════\n\n /**\n * @notice Accepts a receipt, which local `AgentManager` verified to have been signed by an active Notary.\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 * - Notary who signed the receipt is referenced as the \"Receipt Notary\".\n * - Notary who signed the attestation on destination chain is referenced as the \"Attestation Notary\".\n * \u003e Will revert if any of these is true:\n * \u003e - Called by anyone other than local `AgentManager`.\n * \u003e - Receipt body payload is not properly formatted.\n * \u003e - Receipt signer is in Dispute.\n * \u003e - Receipt's snapshot root is unknown.\n * @param rcptNotaryIndex Index of Receipt Notary in Agent Merkle Tree\n * @param attNotaryIndex Index of Attestation Notary in Agent Merkle Tree\n * @param sigIndex Index of stored Notary signature\n * @param attNonce Nonce of the attestation used for proving the executed message\n * @param paddedTips Padded encoded paid tips information\n * @param rcptPayload Raw payload with message execution receipt\n * @return wasAccepted Whether the receipt was accepted\n */\n function acceptReceipt(\n uint32 rcptNotaryIndex,\n uint32 attNotaryIndex,\n uint256 sigIndex,\n uint32 attNonce,\n uint256 paddedTips,\n bytes memory rcptPayload\n ) external returns (bool wasAccepted);\n\n /**\n * @notice Accepts a snapshot, which local `AgentManager` verified to have been signed by an active Guard.\n * \u003e Snapshot is a list of states for a set of Origin contracts residing on any of the chains.\n * All the states in the Guard-signed snapshot become available for Notary signing.\n * \u003e Will revert if any of these is true:\n * \u003e - Called by anyone other than local `AgentManager`.\n * \u003e - Snapshot payload is not properly formatted.\n * \u003e - Snapshot contains a state older then the Guard has previously submitted.\n * @param guardIndex Index of Guard in Agent Merkle Tree\n * @param sigIndex Index of stored Agent signature\n * @param snapPayload Raw payload with snapshot data\n */\n function acceptGuardSnapshot(uint32 guardIndex, uint256 sigIndex, bytes memory snapPayload) external;\n\n /**\n * @notice Accepts a snapshot, which local `AgentManager` verified to have been signed by an active Notary.\n * \u003e Snapshot is a list of states for a set of Origin contracts residing on any of the chains.\n * Snapshot Merkle Root is calculated and saved for valid snapshots, i.e.\n * snapshots which are only using states previously submitted by any of the Guards.\n * - Notary could use states singed by the same of different Guards 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 - Called by anyone other than local `AgentManager`.\n * \u003e - Snapshot payload is not properly formatted.\n * \u003e - Snapshot contains a state older then the Notary has previously submitted.\n * \u003e - Snapshot contains a state that no Guard has previously submitted.\n * @param notaryIndex Index of Notary in Agent Merkle Tree\n * @param sigIndex Index of stored Agent signature\n * @param agentRoot Current root of the Agent Merkle Tree\n * @param snapPayload Raw payload with snapshot data\n * @return attPayload Raw payload with data for attestation derived from Notary snapshot.\n */\n function acceptNotarySnapshot(uint32 notaryIndex, uint256 sigIndex, bytes32 agentRoot, bytes memory snapPayload)\n external\n returns (bytes memory attPayload);\n\n // ════════════════════════════════════════════════ TIPS LOGIC ═════════════════════════════════════════════════════\n\n /**\n * @notice Distributes tips using the first Receipt from the \"receipt quarantine queue\".\n * Possible scenarios:\n * - Receipt queue is empty =\u003e does nothing\n * - Receipt optimistic period is not over =\u003e does nothing\n * - Either of Notaries present in Receipt was slashed =\u003e receipt is deleted from the queue\n * - Either of Notaries present in Receipt in Dispute =\u003e receipt is moved to the end of queue\n * - None of the above =\u003e receipt tips are distributed\n * @dev Returned value makes it possible to do the following: `while (distributeTips()) {}`\n * @return queuePopped Whether the first element was popped from the queue\n */\n function distributeTips() external returns (bool queuePopped);\n\n /**\n * @notice Withdraws locked base message tips from requested domain Origin to the recipient.\n * This is done by a call to a local Origin contract, or by a manager message to the remote chain.\n * @dev This will revert, if the pending balance of origin tips (earned-claimed) is lower than requested.\n * @param origin Domain of chain to withdraw tips on\n * @param amount Amount of tips to withdraw\n */\n function withdrawTips(uint32 origin, uint256 amount) external;\n\n // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════\n\n /**\n * @notice Returns earned and claimed tips for the actor.\n * Note: Tips for address(0) belong to the Treasury.\n * @param actor Address of the actor\n * @param origin Domain where the tips were initially paid\n * @return earned Total amount of origin tips the actor has earned so far\n * @return claimed Total amount of origin tips the actor has claimed so far\n */\n function actorTips(address actor, uint32 origin) external view returns (uint128 earned, uint128 claimed);\n\n /**\n * @notice Returns the amount of receipts in the \"Receipt Quarantine Queue\".\n */\n function receiptQueueLength() external view returns (uint256);\n\n /**\n * @notice Returns the state with the highest known nonce\n * submitted by any of the currently active Guards.\n * @param origin Domain of origin chain\n * @return statePayload Raw payload with latest active Guard state for origin\n */\n function getLatestState(uint32 origin) external view returns (bytes memory statePayload);\n}\n\n// node_modules/@openzeppelin/contracts/utils/Strings.sol\n\n// OpenZeppelin Contracts (last updated v4.9.0) (utils/Strings.sol)\n\n/**\n * @dev String operations.\n */\nlibrary Strings {\n bytes16 private constant _SYMBOLS = \"0123456789abcdef\";\n uint8 private constant _ADDRESS_LENGTH = 20;\n\n /**\n * @dev Converts a `uint256` to its ASCII `string` decimal representation.\n */\n function toString(uint256 value) internal pure returns (string memory) {\n unchecked {\n uint256 length = Math.log10(value) + 1;\n string memory buffer = new string(length);\n uint256 ptr;\n /// @solidity memory-safe-assembly\n assembly {\n ptr := add(buffer, add(32, length))\n }\n while (true) {\n ptr--;\n /// @solidity memory-safe-assembly\n assembly {\n mstore8(ptr, byte(mod(value, 10), _SYMBOLS))\n }\n value /= 10;\n if (value == 0) break;\n }\n return buffer;\n }\n }\n\n /**\n * @dev Converts a `int256` to its ASCII `string` decimal representation.\n */\n function toString(int256 value) internal pure returns (string memory) {\n return string(abi.encodePacked(value \u003c 0 ? \"-\" : \"\", toString(SignedMath.abs(value))));\n }\n\n /**\n * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation.\n */\n function toHexString(uint256 value) internal pure returns (string memory) {\n unchecked {\n return toHexString(value, Math.log256(value) + 1);\n }\n }\n\n /**\n * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length.\n */\n function toHexString(uint256 value, uint256 length) internal pure returns (string memory) {\n bytes memory buffer = new bytes(2 * length + 2);\n buffer[0] = \"0\";\n buffer[1] = \"x\";\n for (uint256 i = 2 * length + 1; i \u003e 1; --i) {\n buffer[i] = _SYMBOLS[value \u0026 0xf];\n value \u003e\u003e= 4;\n }\n require(value == 0, \"Strings: hex length insufficient\");\n return string(buffer);\n }\n\n /**\n * @dev Converts an `address` with fixed length of 20 bytes to its not checksummed ASCII `string` hexadecimal representation.\n */\n function toHexString(address addr) internal pure returns (string memory) {\n return toHexString(uint256(uint160(addr)), _ADDRESS_LENGTH);\n }\n\n /**\n * @dev Returns true if the two strings are equal.\n */\n function equal(string memory a, string memory b) internal pure returns (bool) {\n return keccak256(bytes(a)) == keccak256(bytes(b));\n }\n}\n\n// node_modules/@openzeppelin/contracts-upgradeable/utils/ContextUpgradeable.sol\n\n// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)\n\n/**\n * @dev Provides information about the current execution context, including the\n * sender of the transaction and its data. While these are generally available\n * via msg.sender and msg.data, they should not be accessed in such a direct\n * manner, since when dealing with meta-transactions the account sending and\n * paying for execution may not be the actual sender (as far as an application\n * is concerned).\n *\n * This contract is only required for intermediate, library-like contracts.\n */\nabstract contract ContextUpgradeable is Initializable {\n function __Context_init() internal onlyInitializing {\n }\n\n function __Context_init_unchained() internal onlyInitializing {\n }\n function _msgSender() internal view virtual returns (address) {\n return msg.sender;\n }\n\n function _msgData() internal view virtual returns (bytes calldata) {\n return msg.data;\n }\n\n /**\n * @dev This empty reserved space is put in place to allow future versions to add new\n * variables without shifting down storage in the inheritance chain.\n * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\n */\n uint256[50] private __gap;\n}\n\n// contracts/libs/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/utils/cryptography/ECDSA.sol\n\n// OpenZeppelin Contracts (last updated v4.9.0) (utils/cryptography/ECDSA.sol)\n\n/**\n * @dev Elliptic Curve Digital Signature Algorithm (ECDSA) operations.\n *\n * These functions can be used to verify that a message was signed by the holder\n * of the private keys of a given address.\n */\nlibrary ECDSA {\n enum RecoverError {\n NoError,\n InvalidSignature,\n InvalidSignatureLength,\n InvalidSignatureS,\n InvalidSignatureV // Deprecated in v4.8\n }\n\n function _throwError(RecoverError error) private pure {\n if (error == RecoverError.NoError) {\n return; // no error: do nothing\n } else if (error == RecoverError.InvalidSignature) {\n revert(\"ECDSA: invalid signature\");\n } else if (error == RecoverError.InvalidSignatureLength) {\n revert(\"ECDSA: invalid signature length\");\n } else if (error == RecoverError.InvalidSignatureS) {\n revert(\"ECDSA: invalid signature 's' value\");\n }\n }\n\n /**\n * @dev Returns the address that signed a hashed message (`hash`) with\n * `signature` or error string. This address can then be used for verification purposes.\n *\n * The `ecrecover` EVM opcode allows for malleable (non-unique) signatures:\n * this function rejects them by requiring the `s` value to be in the lower\n * half order, and the `v` value to be either 27 or 28.\n *\n * IMPORTANT: `hash` _must_ be the result of a hash operation for the\n * verification to be secure: it is possible to craft signatures that\n * recover to arbitrary addresses for non-hashed data. A safe way to ensure\n * this is by receiving a hash of the original message (which may otherwise\n * be too long), and then calling {toEthSignedMessageHash} on it.\n *\n * Documentation for signature generation:\n * - with https://web3js.readthedocs.io/en/v1.3.4/web3-eth-accounts.html#sign[Web3.js]\n * - with https://docs.ethers.io/v5/api/signer/#Signer-signMessage[ethers]\n *\n * _Available since v4.3._\n */\n function tryRecover(bytes32 hash, bytes memory signature) internal pure returns (address, RecoverError) {\n if (signature.length == 65) {\n bytes32 r;\n bytes32 s;\n uint8 v;\n // ecrecover takes the signature parameters, and the only way to get them\n // currently is to use assembly.\n /// @solidity memory-safe-assembly\n assembly {\n r := mload(add(signature, 0x20))\n s := mload(add(signature, 0x40))\n v := byte(0, mload(add(signature, 0x60)))\n }\n return tryRecover(hash, v, r, s);\n } else {\n return (address(0), RecoverError.InvalidSignatureLength);\n }\n }\n\n /**\n * @dev Returns the address that signed a hashed message (`hash`) with\n * `signature`. This address can then be used for verification purposes.\n *\n * The `ecrecover` EVM opcode allows for malleable (non-unique) signatures:\n * this function rejects them by requiring the `s` value to be in the lower\n * half order, and the `v` value to be either 27 or 28.\n *\n * IMPORTANT: `hash` _must_ be the result of a hash operation for the\n * verification to be secure: it is possible to craft signatures that\n * recover to arbitrary addresses for non-hashed data. A safe way to ensure\n * this is by receiving a hash of the original message (which may otherwise\n * be too long), and then calling {toEthSignedMessageHash} on it.\n */\n function recover(bytes32 hash, bytes memory signature) internal pure returns (address) {\n (address recovered, RecoverError error) = tryRecover(hash, signature);\n _throwError(error);\n return recovered;\n }\n\n /**\n * @dev Overload of {ECDSA-tryRecover} that receives the `r` and `vs` short-signature fields separately.\n *\n * See https://eips.ethereum.org/EIPS/eip-2098[EIP-2098 short signatures]\n *\n * _Available since v4.3._\n */\n function tryRecover(bytes32 hash, bytes32 r, bytes32 vs) internal pure returns (address, RecoverError) {\n bytes32 s = vs \u0026 bytes32(0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff);\n uint8 v = uint8((uint256(vs) \u003e\u003e 255) + 27);\n return tryRecover(hash, v, r, s);\n }\n\n /**\n * @dev Overload of {ECDSA-recover} that receives the `r and `vs` short-signature fields separately.\n *\n * _Available since v4.2._\n */\n function recover(bytes32 hash, bytes32 r, bytes32 vs) internal pure returns (address) {\n (address recovered, RecoverError error) = tryRecover(hash, r, vs);\n _throwError(error);\n return recovered;\n }\n\n /**\n * @dev Overload of {ECDSA-tryRecover} that receives the `v`,\n * `r` and `s` signature fields separately.\n *\n * _Available since v4.3._\n */\n function tryRecover(bytes32 hash, uint8 v, bytes32 r, bytes32 s) internal pure returns (address, RecoverError) {\n // EIP-2 still allows signature malleability for ecrecover(). Remove this possibility and make the signature\n // unique. Appendix F in the Ethereum Yellow paper (https://ethereum.github.io/yellowpaper/paper.pdf), defines\n // the valid range for s in (301): 0 \u003c s \u003c secp256k1n ÷ 2 + 1, and for v in (302): v ∈ {27, 28}. Most\n // signatures from current libraries generate a unique signature with an s-value in the lower half order.\n //\n // If your library generates malleable signatures, such as s-values in the upper range, calculate a new s-value\n // with 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141 - s1 and flip v from 27 to 28 or\n // vice versa. If your library also generates signatures with 0/1 for v instead 27/28, add 27 to v to accept\n // these malleable signatures as well.\n if (uint256(s) \u003e 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0) {\n return (address(0), RecoverError.InvalidSignatureS);\n }\n\n // If the signature is valid (and not malleable), return the signer address\n address signer = ecrecover(hash, v, r, s);\n if (signer == address(0)) {\n return (address(0), RecoverError.InvalidSignature);\n }\n\n return (signer, RecoverError.NoError);\n }\n\n /**\n * @dev Overload of {ECDSA-recover} that receives the `v`,\n * `r` and `s` signature fields separately.\n */\n function recover(bytes32 hash, uint8 v, bytes32 r, bytes32 s) internal pure returns (address) {\n (address recovered, RecoverError error) = tryRecover(hash, v, r, s);\n _throwError(error);\n return recovered;\n }\n\n /**\n * @dev Returns an Ethereum Signed Message, created from a `hash`. This\n * produces hash corresponding to the one signed with the\n * https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`]\n * JSON-RPC method as part of EIP-191.\n *\n * See {recover}.\n */\n function toEthSignedMessageHash(bytes32 hash) internal pure returns (bytes32 message) {\n // 32 is the length in bytes of hash,\n // enforced by the type signature above\n /// @solidity memory-safe-assembly\n assembly {\n mstore(0x00, \"\\x19Ethereum Signed Message:\\n32\")\n mstore(0x1c, hash)\n message := keccak256(0x00, 0x3c)\n }\n }\n\n /**\n * @dev Returns an Ethereum Signed Message, created from `s`. This\n * produces hash corresponding to the one signed with the\n * https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`]\n * JSON-RPC method as part of EIP-191.\n *\n * See {recover}.\n */\n function toEthSignedMessageHash(bytes memory s) internal pure returns (bytes32) {\n return keccak256(abi.encodePacked(\"\\x19Ethereum Signed Message:\\n\", Strings.toString(s.length), s));\n }\n\n /**\n * @dev Returns an Ethereum Signed Typed Data, created from a\n * `domainSeparator` and a `structHash`. This produces hash corresponding\n * to the one signed with the\n * https://eips.ethereum.org/EIPS/eip-712[`eth_signTypedData`]\n * JSON-RPC method as part of EIP-712.\n *\n * See {recover}.\n */\n function toTypedDataHash(bytes32 domainSeparator, bytes32 structHash) internal pure returns (bytes32 data) {\n /// @solidity memory-safe-assembly\n assembly {\n let ptr := mload(0x40)\n mstore(ptr, \"\\x19\\x01\")\n mstore(add(ptr, 0x02), domainSeparator)\n mstore(add(ptr, 0x22), structHash)\n data := keccak256(ptr, 0x42)\n }\n }\n\n /**\n * @dev Returns an Ethereum Signed Data with intended validator, created from a\n * `validator` and `data` according to the version 0 of EIP-191.\n *\n * See {recover}.\n */\n function toDataWithIntendedValidatorHash(address validator, bytes memory data) internal pure returns (bytes32) {\n return keccak256(abi.encodePacked(\"\\x19\\x00\", validator, data));\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/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/inbox/StatementInbox.sol\n\n// ══════════════════════════════ LIBRARY IMPORTS ══════════════════════════════\n\n// ═════════════════════════════ INTERNAL IMPORTS ══════════════════════════════\n\n// ═════════════════════════════ EXTERNAL IMPORTS ══════════════════════════════\n\n/// @notice `StatementInbox` is the entry point for all agent-signed statements. It verifies the\n/// agent signatures, and passes the unsigned statements to the contract to consume it via `acceptX` functions. Is is\n/// also used to verify the agent-signed statements and initiate the agent slashing, should the statement be invalid.\n/// `StatementInbox` is responsible for the following:\n/// - Accepting State and Receipt Reports to initiate a dispute between Guard and Notary.\n/// - Storing all the Guard Reports with the Guard signature leading to a dispute.\n/// - Verifying State/State Reports referencing the local chain and slashing the signer if statement is invalid.\n/// - Verifying Receipt/Receipt Reports referencing the local chain and slashing the signer if statement is invalid.\nabstract contract StatementInbox is MessagingBase, StatementInboxEvents, IStatementInbox {\n using AttestationLib for bytes;\n using ReceiptLib for bytes;\n using StateLib for bytes;\n using SnapshotLib for bytes;\n\n struct StoredReport {\n uint256 sigIndex;\n bytes statementPayload;\n }\n\n // ══════════════════════════════════════════════════ STORAGE ══════════════════════════════════════════════════════\n\n address public agentManager;\n address public origin;\n address public destination;\n\n // TODO: optimize this\n bytes[] internal _storedSignatures;\n StoredReport[] internal _storedReports;\n\n /// @dev gap for upgrade safety\n uint256[45] private __GAP; // solhint-disable-line var-name-mixedcase\n\n // ════════════════════════════════════════════════ INITIALIZER ════════════════════════════════════════════════════\n\n /// @dev Initializes the contract:\n /// - Sets up `msg.sender` as the owner of the contract.\n /// - Sets up `agentManager`, `origin`, and `destination`.\n // solhint-disable-next-line func-name-mixedcase\n function __StatementInbox_init(address agentManager_, address origin_, address destination_)\n internal\n onlyInitializing\n {\n agentManager = agentManager_;\n origin = origin_;\n destination = destination_;\n __Ownable2Step_init();\n }\n\n // ══════════════════════════════════════════ SUBMIT AGENT STATEMENTS ══════════════════════════════════════════════\n\n /// @inheritdoc IStatementInbox\n // solhint-disable-next-line ordering\n function submitStateReportWithSnapshot(\n uint8 stateIndex,\n bytes memory srSignature,\n bytes memory snapPayload,\n bytes memory snapSignature\n ) external returns (bool wasAccepted) {\n // This will revert if payload is not a snapshot\n Snapshot snapshot = snapPayload.castToSnapshot();\n // This will revert if the snapshot signer is not a known Notary\n (AgentStatus memory notaryStatus,) =\n _verifySnapshot({snapshot: snapshot, snapSignature: snapSignature, verifyNotary: true});\n // Notary needs to be Active/Unstaking\n notaryStatus.verifyActiveUnstaking();\n // Check if Notary is active on this chain\n _verifyNotaryDomain(notaryStatus.domain);\n // This will revert if state index is out of range\n State state = snapshot.state(stateIndex);\n // This will revert if the report signer is not an known Guard\n (AgentStatus memory guardStatus,) = _verifyStateReport(state, srSignature);\n // Check that Guard is active\n guardStatus.verifyActive();\n _saveReport(state.unwrap().clone(), srSignature);\n // This will revert if either actor is already in dispute\n IAgentManager(agentManager).openDispute(guardStatus.index, notaryStatus.index);\n return true;\n }\n\n /// @inheritdoc IStatementInbox\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 // This will revert if payload is not a snapshot\n Snapshot snapshot = snapPayload.castToSnapshot();\n // This will revert if state index is out of range\n State state = snapshot.state(stateIndex);\n // This will revert if the report signer is not an known Guard\n (AgentStatus memory guardStatus,) = _verifyStateReport(state, srSignature);\n // Check that Guard is active\n guardStatus.verifyActive();\n // This will revert if payload is not an attestation\n Attestation att = attPayload.castToAttestation();\n // This will revert if signer is not an known Notary\n (AgentStatus memory notaryStatus,) = _verifyAttestation(att, attSignature);\n // Notary needs to be Active/Unstaking\n notaryStatus.verifyActiveUnstaking();\n // Check if Notary is active on this chain\n _verifyNotaryDomain(notaryStatus.domain);\n if (snapshot.calculateRoot() != att.snapRoot()) revert IncorrectSnapshotRoot();\n _saveReport(state.unwrap().clone(), srSignature);\n // This will revert if either actor is already in dispute\n IAgentManager(agentManager).openDispute(guardStatus.index, notaryStatus.index);\n return true;\n }\n\n /// @inheritdoc IStatementInbox\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 // This will revert if payload is not a state\n State state = statePayload.castToState();\n // This will revert if the report signer is not an known Guard\n (AgentStatus memory guardStatus,) = _verifyStateReport(state, srSignature);\n // Check that Guard is active\n guardStatus.verifyActive();\n // This will revert if payload is not an attestation\n Attestation att = attPayload.castToAttestation();\n // This will revert if signer is not a known Notary\n (AgentStatus memory notaryStatus,) = _verifyAttestation(att, attSignature);\n // Notary needs to be Active/Unstaking\n notaryStatus.verifyActiveUnstaking();\n // Check if Notary is active on this chain\n _verifyNotaryDomain(notaryStatus.domain);\n // This will revert if any of these is true:\n // - Attestation root is not equal to Merkle Root derived from State and Snapshot Proof.\n // - Snapshot Proof's first element does not match the State metadata.\n // - Snapshot Proof length exceeds Snapshot tree Height.\n // - State index is out of range.\n _verifySnapshotMerkle(att, stateIndex, state, snapProof);\n _saveReport(statePayload, srSignature);\n // This will revert if either actor is already in dispute\n IAgentManager(agentManager).openDispute(guardStatus.index, notaryStatus.index);\n return true;\n }\n\n // ══════════════════════════════════════════ VERIFY AGENT STATEMENTS ══════════════════════════════════════════════\n\n /// @inheritdoc IStatementInbox\n function verifyReceipt(bytes memory rcptPayload, bytes memory rcptSignature)\n external\n returns (bool isValidReceipt)\n {\n // This will revert if payload is not a receipt\n Receipt rcpt = rcptPayload.castToReceipt();\n // This will revert if the attestation signer is not a known Notary\n (AgentStatus memory status, address notary) = _verifyReceipt(rcpt, rcptSignature);\n // Notary needs to be Active/Unstaking\n status.verifyActiveUnstaking();\n isValidReceipt = IExecutionHub(destination).isValidReceipt(rcptPayload);\n if (!isValidReceipt) {\n emit InvalidReceipt(rcptPayload, rcptSignature);\n IAgentManager(agentManager).slashAgent(status.domain, notary, msg.sender);\n }\n }\n\n /// @inheritdoc IStatementInbox\n function verifyReceiptReport(bytes memory rcptPayload, bytes memory rrSignature)\n external\n returns (bool isValidReport)\n {\n // This will revert if payload is not a receipt\n Receipt rcpt = rcptPayload.castToReceipt();\n // This will revert if the report signer is not a known Guard\n (AgentStatus memory status, address guard) = _verifyReceiptReport(rcpt, rrSignature);\n // Guard needs to be Active/Unstaking\n status.verifyActiveUnstaking();\n // Report is valid IF AND ONLY IF the reported receipt in invalid\n isValidReport = !IExecutionHub(destination).isValidReceipt(rcptPayload);\n if (!isValidReport) {\n emit InvalidReceiptReport(rcptPayload, rrSignature);\n IAgentManager(agentManager).slashAgent(status.domain, guard, msg.sender);\n }\n }\n\n /// @inheritdoc IStatementInbox\n function verifyStateWithAttestation(\n uint8 stateIndex,\n bytes memory snapPayload,\n bytes memory attPayload,\n bytes memory attSignature\n ) external returns (bool isValidState) {\n // This will revert if payload is not an attestation\n Attestation att = attPayload.castToAttestation();\n // This will revert if the attestation signer is not a known Notary\n (AgentStatus memory status, address notary) = _verifyAttestation(att, attSignature);\n // Notary needs to be Active/Unstaking\n status.verifyActiveUnstaking();\n // This will revert if payload is not a snapshot\n Snapshot snapshot = snapPayload.castToSnapshot();\n if (snapshot.calculateRoot() != att.snapRoot()) revert IncorrectSnapshotRoot();\n // This will revert if state does not refer to this chain\n bytes memory statePayload = snapshot.state(stateIndex).unwrap().clone();\n isValidState = IStateHub(origin).isValidState(statePayload);\n if (!isValidState) {\n emit InvalidStateWithAttestation(stateIndex, statePayload, attPayload, attSignature);\n IAgentManager(agentManager).slashAgent(status.domain, notary, msg.sender);\n }\n }\n\n /// @inheritdoc IStatementInbox\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 // This will revert if payload is not an attestation\n Attestation att = attPayload.castToAttestation();\n // This will revert if the attestation signer is not a known Notary\n (AgentStatus memory status, address notary) = _verifyAttestation(att, attSignature);\n // Notary needs to be Active/Unstaking\n status.verifyActiveUnstaking();\n // This will revert if payload is not a state\n State state = statePayload.castToState();\n // This will revert if any of these is true:\n // - Attestation root is not equal to Merkle Root derived from State and Snapshot Proof.\n // - Snapshot Proof's first element does not match the State metadata.\n // - Snapshot Proof length exceeds Snapshot tree Height.\n // - State index is out of range.\n _verifySnapshotMerkle(att, stateIndex, state, snapProof);\n // This will revert if state does not refer to this chain\n isValidState = IStateHub(origin).isValidState(statePayload);\n if (!isValidState) {\n emit InvalidStateWithAttestation(stateIndex, statePayload, attPayload, attSignature);\n IAgentManager(agentManager).slashAgent(status.domain, notary, msg.sender);\n }\n }\n\n /// @inheritdoc IStatementInbox\n function verifyStateWithSnapshot(uint8 stateIndex, bytes memory snapPayload, bytes memory snapSignature)\n external\n returns (bool isValidState)\n {\n // This will revert if payload is not a snapshot\n Snapshot snapshot = snapPayload.castToSnapshot();\n // This will revert if the snapshot signer is not a known Guard/Notary\n (AgentStatus memory status, address agent) =\n _verifySnapshot({snapshot: snapshot, snapSignature: snapSignature, verifyNotary: false});\n // Agent needs to be Active/Unstaking\n status.verifyActiveUnstaking();\n // This will revert if state does not refer to this chain\n isValidState = IStateHub(origin).isValidState(snapshot.state(stateIndex).unwrap().clone());\n if (!isValidState) {\n emit InvalidStateWithSnapshot(stateIndex, snapPayload, snapSignature);\n IAgentManager(agentManager).slashAgent(status.domain, agent, msg.sender);\n }\n }\n\n /// @inheritdoc IStatementInbox\n function verifyStateReport(bytes memory statePayload, bytes memory srSignature)\n external\n returns (bool isValidReport)\n {\n // This will revert if payload is not a state\n State state = statePayload.castToState();\n // This will revert if the report signer is not a known Guard\n (AgentStatus memory status, address guard) = _verifyStateReport(state, srSignature);\n // Guard needs to be Active/Unstaking\n status.verifyActiveUnstaking();\n // Report is valid IF AND ONLY IF the reported state in invalid\n // This will revert if the reported state does not refer to this chain\n isValidReport = !IStateHub(origin).isValidState(statePayload);\n if (!isValidReport) {\n emit InvalidStateReport(statePayload, srSignature);\n IAgentManager(agentManager).slashAgent(status.domain, guard, msg.sender);\n }\n }\n\n // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════\n\n /// @inheritdoc IStatementInbox\n function getReportsAmount() external view returns (uint256) {\n return _storedReports.length;\n }\n\n /// @inheritdoc IStatementInbox\n function getGuardReport(uint256 index)\n external\n view\n returns (bytes memory statementPayload, bytes memory reportSignature)\n {\n if (index \u003e= _storedReports.length) revert IndexOutOfRange();\n StoredReport memory storedReport = _storedReports[index];\n statementPayload = storedReport.statementPayload;\n reportSignature = _storedSignatures[storedReport.sigIndex];\n }\n\n /// @inheritdoc IStatementInbox\n function getStoredSignature(uint256 index) external view returns (bytes memory) {\n return _storedSignatures[index];\n }\n\n // ══════════════════════════════════════════════ INTERNAL LOGIC ═══════════════════════════════════════════════════\n\n /// @dev Saves the statement reported by Guard as invalid and the Guard Report signature.\n function _saveReport(bytes memory statementPayload, bytes memory reportSignature) internal {\n uint256 sigIndex = _saveSignature(reportSignature);\n _storedReports.push(StoredReport(sigIndex, statementPayload));\n }\n\n /// @dev Saves the signature and returns its index.\n function _saveSignature(bytes memory signature) internal returns (uint256 sigIndex) {\n sigIndex = _storedSignatures.length;\n _storedSignatures.push(signature);\n }\n\n // ═══════════════════════════════════════════════ AGENT CHECKS ════════════════════════════════════════════════════\n\n /**\n * @dev Recovers a signer from a hashed message, and a EIP-191 signature for it.\n * Will revert, if the signer is not a known agent.\n * @dev Agent flag could be any of these: Active/Unstaking/Resting/Fraudulent/Slashed\n * Further checks need to be performed in a caller function.\n * @param hashedStatement Hash of the statement that was signed by an Agent\n * @param signature Agent signature for the hashed statement\n * @return status Struct representing agent status:\n * - flag Unknown/Active/Unstaking/Resting/Fraudulent/Slashed\n * - domain Domain where agent is/was active\n * - index Index of agent in the Agent Merkle Tree\n * @return agent Agent that signed the statement\n */\n function _recoverAgent(bytes32 hashedStatement, bytes memory signature)\n internal\n view\n returns (AgentStatus memory status, address agent)\n {\n bytes32 ethSignedMsg = ECDSA.toEthSignedMessageHash(hashedStatement);\n agent = ECDSA.recover(ethSignedMsg, signature);\n status = IAgentManager(agentManager).agentStatus(agent);\n // Discard signature of unknown agents.\n // Further flag checks are supposed to be performed in a caller function.\n status.verifyKnown();\n }\n\n /// @dev Verifies that Notary signature is active on local domain.\n function _verifyNotaryDomain(uint32 notaryDomain) internal view {\n // Notary needs to be from the local domain (if contract is not deployed on Synapse Chain).\n // Or Notary could be from any domain (if contract is deployed on Synapse Chain).\n if (notaryDomain != localDomain \u0026\u0026 localDomain != synapseDomain) revert IncorrectAgentDomain();\n }\n\n // ════════════════════════════════════════ ATTESTATION RELATED CHECKS ═════════════════════════════════════════════\n\n /**\n * @dev Internal function to verify the signed attestation payload.\n * Reverts if any of these is true:\n * - Attestation signer is not a known Notary.\n * @param att Typed memory view over attestation payload\n * @param attSignature Notary signature for the attestation\n * @return status Struct representing agent status, see {_recoverAgent}\n * @return notary Notary that signed the snapshot\n */\n function _verifyAttestation(Attestation att, bytes memory attSignature)\n internal\n view\n returns (AgentStatus memory status, address notary)\n {\n // This will revert if signer is not a known agent\n (status, notary) = _recoverAgent(att.hashValid(), attSignature);\n // Attestation signer needs to be a Notary, not a Guard\n if (status.domain == 0) revert AgentNotNotary();\n }\n\n /**\n * @dev Internal function to verify the signed attestation report payload.\n * Reverts if any of these is true:\n * - Report signer is not a known Guard.\n * @param att Typed memory view over attestation payload that Guard reports as invalid\n * @param arSignature Guard signature for the \"invalid attestation\" report\n * @return status Struct representing guard status, see {_recoverAgent}\n * @return guard Guard that signed the report\n */\n function _verifyAttestationReport(Attestation att, bytes memory arSignature)\n internal\n view\n returns (AgentStatus memory status, address guard)\n {\n // This will revert if signer is not a known agent\n (status, guard) = _recoverAgent(att.hashInvalid(), arSignature);\n // Report signer needs to be a Guard, not a Notary\n if (status.domain != 0) revert AgentNotGuard();\n }\n\n // ══════════════════════════════════════════ RECEIPT RELATED CHECKS ═══════════════════════════════════════════════\n\n /**\n * @dev Internal function to verify the signed receipt payload.\n * Reverts if any of these is true:\n * - Receipt signer is not a known Notary.\n * @param rcpt Typed memory view over receipt payload\n * @param rcptSignature Notary signature for the receipt\n * @return status Struct representing agent status, see {_recoverAgent}\n * @return notary Notary that signed the snapshot\n */\n function _verifyReceipt(Receipt rcpt, bytes memory rcptSignature)\n internal\n view\n returns (AgentStatus memory status, address notary)\n {\n // This will revert if signer is not a known agent\n (status, notary) = _recoverAgent(rcpt.hashValid(), rcptSignature);\n // Receipt signer needs to be a Notary, not a Guard\n if (status.domain == 0) revert AgentNotNotary();\n }\n\n /**\n * @dev Internal function to verify the signed receipt report payload.\n * Reverts if any of these is true:\n * - Report signer is not a known Guard.\n * @param rcpt Typed memory view over receipt payload that Guard reports as invalid\n * @param rrSignature Guard signature for the \"invalid receipt\" report\n * @return status Struct representing guard status, see {_recoverAgent}\n * @return guard Guard that signed the report\n */\n function _verifyReceiptReport(Receipt rcpt, bytes memory rrSignature)\n internal\n view\n returns (AgentStatus memory status, address guard)\n {\n // This will revert if signer is not a known agent\n (status, guard) = _recoverAgent(rcpt.hashInvalid(), rrSignature);\n // Report signer needs to be a Guard, not a Notary\n if (status.domain != 0) revert AgentNotGuard();\n }\n\n // ═══════════════════════════════════════ STATE/SNAPSHOT RELATED CHECKS ═══════════════════════════════════════════\n\n /**\n * @dev Internal function to verify the signed snapshot report payload.\n * Reverts if any of these is true:\n * - Report signer is not a known Guard.\n * @param state Typed memory view over state payload that Guard reports as invalid\n * @param srSignature Guard signature for the report\n * @return status Struct representing guard status, see {_recoverAgent}\n * @return guard Guard that signed the report\n */\n function _verifyStateReport(State state, bytes memory srSignature)\n internal\n view\n returns (AgentStatus memory status, address guard)\n {\n // This will revert if signer is not a known agent\n (status, guard) = _recoverAgent(state.hashInvalid(), srSignature);\n // Report signer needs to be a Guard, not a Notary\n if (status.domain != 0) revert AgentNotGuard();\n }\n\n /**\n * @dev Internal function to verify the signed snapshot payload.\n * Reverts if any of these is true:\n * - Snapshot signer is not a known Agent.\n * - Snapshot signer is not a Notary (if verifyNotary is true).\n * @param snapshot Typed memory view over snapshot payload\n * @param snapSignature Agent signature for the snapshot\n * @param verifyNotary If true, snapshot signer needs to be a Notary, not a Guard\n * @return status Struct representing agent status, see {_recoverAgent}\n * @return agent Agent that signed the snapshot\n */\n function _verifySnapshot(Snapshot snapshot, bytes memory snapSignature, bool verifyNotary)\n internal\n view\n returns (AgentStatus memory status, address agent)\n {\n // This will revert if signer is not a known agent\n (status, agent) = _recoverAgent(snapshot.hashValid(), snapSignature);\n // If requested, snapshot signer needs to be a Notary, not a Guard\n if (verifyNotary \u0026\u0026 status.domain == 0) revert AgentNotNotary();\n }\n\n // ═══════════════════════════════════════════ MERKLE RELATED CHECKS ═══════════════════════════════════════════════\n\n /**\n * @dev Internal function to verify that snapshot roots match.\n * Reverts if any of these is true:\n * - Attestation root is not equal to Merkle Root derived from State and Snapshot Proof.\n * - Snapshot Proof's first element does not match the State metadata.\n * - Snapshot Proof length exceeds Snapshot tree Height.\n * - State index is out of range.\n * @param att Typed memory view over Attestation\n * @param stateIndex Index of state in the snapshot\n * @param state Typed memory view over the provided state payload\n * @param snapProof Raw payload with snapshot data\n */\n function _verifySnapshotMerkle(Attestation att, uint8 stateIndex, State state, bytes32[] memory snapProof)\n internal\n pure\n {\n // Snapshot proof first element should match State metadata (aka \"right sub-leaf\")\n (, bytes32 rightSubLeaf) = state.subLeafs();\n if (snapProof[0] != rightSubLeaf) revert IncorrectSnapshotProof();\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(state.root(), state.origin(), snapProof, stateIndex);\n // Snapshot root should match the attestation root\n if (att.snapRoot() != snapshotRoot) revert IncorrectSnapshotRoot();\n }\n}\n\n// contracts/inbox/Inbox.sol\n\n// ══════════════════════════════ LIBRARY IMPORTS ══════════════════════════════\n\n// ═════════════════════════════ INTERNAL IMPORTS ══════════════════════════════\n\n/// @notice `Inbox` is the child of `StatementInbox` contract, that is used on Synapse Chain.\n/// In addition to the functionality of `StatementInbox`, it also:\n/// - Accepts Guard and Notary Snapshots and passes them to `Summit` contract.\n/// - Accepts Notary-signed Receipts and passes them to `Summit` contract.\n/// - Accepts Receipt Reports to initiate a dispute between Guard and Notary.\n/// - Verifies Attestations and Attestation Reports, and slashes the signer if they are invalid.\ncontract Inbox is StatementInbox, InboxEvents, InterfaceInbox {\n using AttestationLib for bytes;\n using ReceiptLib for bytes;\n using SnapshotLib for bytes;\n\n // Struct to get around stack too deep error. TODO: revisit this\n struct ReceiptInfo {\n AgentStatus rcptNotaryStatus;\n address notary;\n uint32 attNonce;\n AgentStatus attNotaryStatus;\n }\n\n // ══════════════════════════════════════════════════ STORAGE ══════════════════════════════════════════════════════\n\n // The address of the Summit contract.\n address public summit;\n\n // ═════════════════════════════════════════ CONSTRUCTOR \u0026 INITIALIZER ═════════════════════════════════════════════\n\n constructor(uint32 synapseDomain_) MessagingBase(\"0.0.3\", synapseDomain_) {\n if (localDomain != synapseDomain) revert MustBeSynapseDomain();\n }\n\n /// @notice Initializes `Inbox` contract:\n /// - Sets `msg.sender` as the owner of the contract\n /// - Sets `agentManager`, `origin`, `destination` and `summit` addresses\n function initialize(address agentManager_, address origin_, address destination_, address summit_)\n external\n initializer\n {\n __StatementInbox_init(agentManager_, origin_, destination_);\n summit = summit_;\n }\n\n // ══════════════════════════════════════════ SUBMIT AGENT STATEMENTS ══════════════════════════════════════════════\n\n /// @inheritdoc InterfaceInbox\n function submitSnapshot(bytes memory snapPayload, bytes memory snapSignature)\n external\n returns (bytes memory attPayload, bytes32 agentRoot_, uint256[] memory snapGas)\n {\n // This will revert if payload is not a snapshot\n Snapshot snapshot = snapPayload.castToSnapshot();\n // This will revert if the signer is not a known Guard/Notary\n (AgentStatus memory status, address agent) =\n _verifySnapshot({snapshot: snapshot, snapSignature: snapSignature, verifyNotary: false});\n // Check that Agent is active\n status.verifyActive();\n // Store Agent signature for the Snapshot\n uint256 sigIndex = _saveSignature(snapSignature);\n if (status.domain == 0) {\n // Guard that is in Dispute could still submit new snapshots, so we don't check that\n InterfaceSummit(summit).acceptGuardSnapshot({\n guardIndex: status.index,\n sigIndex: sigIndex,\n snapPayload: snapPayload\n });\n } else {\n // Get current agentRoot from AgentManager\n agentRoot_ = IAgentManager(agentManager).agentRoot();\n // This will revert if Notary is in Dispute\n attPayload = InterfaceSummit(summit).acceptNotarySnapshot({\n notaryIndex: status.index,\n sigIndex: sigIndex,\n agentRoot: agentRoot_,\n snapPayload: snapPayload\n });\n ChainGas[] memory snapGas_ = snapshot.snapGas();\n // Pass created attestation to Destination to enable executing messages coming to Synapse Chain\n InterfaceDestination(destination).acceptAttestation(\n status.index, type(uint256).max, attPayload, agentRoot_, snapGas_\n );\n // Use assembly to cast ChainGas[] to uint256[] without copying. Highest bits are left zeroed.\n // solhint-disable-next-line no-inline-assembly\n assembly {\n snapGas := snapGas_\n }\n }\n emit SnapshotAccepted(status.domain, agent, snapPayload, snapSignature);\n }\n\n /// @inheritdoc InterfaceInbox\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 // Struct to get around stack too deep error.\n ReceiptInfo memory info;\n // This will revert if payload is not a receipt\n Receipt rcpt = rcptPayload.castToReceipt();\n // This will revert if the receipt signer is not a known Notary\n (info.rcptNotaryStatus, info.notary) = _verifyReceipt(rcpt, rcptSignature);\n // Receipt Notary needs to be Active\n info.rcptNotaryStatus.verifyActive();\n info.attNonce = IExecutionHub(destination).getAttestationNonce(rcpt.snapshotRoot());\n if (info.attNonce == 0) revert IncorrectSnapshotRoot();\n // Attestation Notary domain needs to match the destination domain\n info.attNotaryStatus = IAgentManager(agentManager).agentStatus(rcpt.attNotary());\n if (info.attNotaryStatus.domain != rcpt.destination()) revert IncorrectAgentDomain();\n // Check that the correct tip values for the message were provided\n _verifyReceiptTips(rcpt.messageHash(), paddedTips, headerHash, bodyHash);\n // Store Notary signature for the Receipt\n uint256 sigIndex = _saveSignature(rcptSignature);\n // This will revert if Receipt Notary is in Dispute\n wasAccepted = InterfaceSummit(summit).acceptReceipt({\n rcptNotaryIndex: info.rcptNotaryStatus.index,\n attNotaryIndex: info.attNotaryStatus.index,\n sigIndex: sigIndex,\n attNonce: info.attNonce,\n paddedTips: paddedTips,\n rcptPayload: rcptPayload\n });\n if (wasAccepted) {\n emit ReceiptAccepted(info.rcptNotaryStatus.domain, info.notary, rcptPayload, rcptSignature);\n }\n }\n\n /// @inheritdoc InterfaceInbox\n function submitReceiptReport(bytes memory rcptPayload, bytes memory rcptSignature, bytes memory rrSignature)\n external\n returns (bool wasAccepted)\n {\n // This will revert if payload is not a receipt\n Receipt rcpt = rcptPayload.castToReceipt();\n // This will revert if the receipt signer is not a known Guard\n (AgentStatus memory guardStatus,) = _verifyReceiptReport(rcpt, rrSignature);\n // Guard needs to be Active\n guardStatus.verifyActive();\n // This will revert if report signer is not a known Notary\n (AgentStatus memory notaryStatus,) = _verifyReceipt(rcpt, rcptSignature);\n // Notary needs to be Active/Unstaking\n notaryStatus.verifyActiveUnstaking();\n _saveReport(rcptPayload, rrSignature);\n // This will revert if either actor is already in dispute\n IAgentManager(agentManager).openDispute(guardStatus.index, notaryStatus.index);\n return true;\n }\n\n /// @inheritdoc InterfaceInbox\n function passReceipt(uint32 attNotaryIndex, uint32 attNonce, uint256 paddedTips, bytes memory rcptPayload)\n external\n returns (bool wasAccepted)\n {\n // Only Destination can pass receipts\n if (msg.sender != destination) revert CallerNotDestination();\n return InterfaceSummit(summit).acceptReceipt({\n rcptNotaryIndex: attNotaryIndex,\n attNotaryIndex: attNotaryIndex,\n sigIndex: type(uint256).max,\n attNonce: attNonce,\n paddedTips: paddedTips,\n rcptPayload: rcptPayload\n });\n }\n\n // ══════════════════════════════════════════ VERIFY AGENT STATEMENTS ══════════════════════════════════════════════\n\n /// @inheritdoc InterfaceInbox\n function verifyAttestation(bytes memory attPayload, bytes memory attSignature)\n external\n returns (bool isValidAttestation)\n {\n // This will revert if payload is not an attestation\n Attestation att = attPayload.castToAttestation();\n // This will revert if the attestation signer is not a known Notary\n (AgentStatus memory status, address notary) = _verifyAttestation(att, attSignature);\n // Notary needs to be Active/Unstaking\n status.verifyActiveUnstaking();\n isValidAttestation = ISnapshotHub(summit).isValidAttestation(attPayload);\n if (!isValidAttestation) {\n emit InvalidAttestation(attPayload, attSignature);\n IAgentManager(agentManager).slashAgent(status.domain, notary, msg.sender);\n }\n }\n\n /// @inheritdoc InterfaceInbox\n function verifyAttestationReport(bytes memory attPayload, bytes memory arSignature)\n external\n returns (bool isValidReport)\n {\n // This will revert if payload is not an attestation\n Attestation att = attPayload.castToAttestation();\n // This will revert if the report signer is not a known Guard\n (AgentStatus memory status, address guard) = _verifyAttestationReport(att, arSignature);\n // Guard needs to be Active/Unstaking\n status.verifyActiveUnstaking();\n // Report is valid IF AND ONLY IF the reported attestation in invalid\n isValidReport = !ISnapshotHub(summit).isValidAttestation(attPayload);\n if (!isValidReport) {\n emit InvalidAttestationReport(attPayload, arSignature);\n IAgentManager(agentManager).slashAgent(status.domain, guard, msg.sender);\n }\n }\n\n // ══════════════════════════════════════════════ INTERNAL VIEWS ═══════════════════════════════════════════════════\n\n /// @dev Verifies that tips proof matches the message hash.\n function _verifyReceiptTips(bytes32 msgHash, uint256 paddedTips, bytes32 headerHash, bytes32 bodyHash)\n internal\n pure\n {\n Tips tips = TipsLib.wrapPadded(paddedTips);\n // full message leaf is (header, baseMessage), while base message leaf is (tips, remainingBody).\n if (MerkleMath.getParent(headerHash, MerkleMath.getParent(tips.leaf(), bodyHash)) != msgHash) {\n revert IncorrectTipsProof();\n }\n }\n}\n","language":"Solidity","languageVersion":"0.8.17","compilerVersion":"0.8.17","compilerOptions":"--combined-json bin,bin-runtime,srcmap,srcmap-runtime,abi,userdoc,devdoc,metadata,hashes --optimize --optimize-runs 10000 --allow-paths ., ./, ../","srcMap":"228587:7325:0:-:0;;;;;;;;;;;;;;;-1:-1:-1;;;228587:7325:0;;;;;;;;;;;;;;;;;","srcMapRuntime":"228587: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/Inbox.sol\":\"StateLib\"},\"evmVersion\":\"london\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\"},\"optimizer\":{\"enabled\":true,\"runs\":10000},\"remappings\":[]},\"sources\":{\"solidity/Inbox.sol\":{\"keccak256\":\"0x9b516081a036814c0169e20e484d4a5499066b7a6f48fada952b5e844a1ca3e5\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://32bde393b3f24ef4307d9626d4143f337b3c0bd34e17bb969fd5a15221d96987\",\"dweb:/ipfs/QmTkt2XZRtgsbSpmsVQUM3c4ebETQoDVYbmEV9yheBghnr\"]}},\"version\":1}"},"hashes":{}},"solidity/Inbox.sol:StatementInbox":{"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/InboxEvents.sol\n\nabstract contract InboxEvents {\n /**\n * @notice Emitted when a snapshot is accepted by the Summit contract.\n * @param domain Domain where the signed Agent is active (ZERO for Guards)\n * @param agent Agent who signed the snapshot\n * @param snapPayload Raw payload with snapshot data\n * @param snapSignature Agent signature for the snapshot\n */\n event SnapshotAccepted(uint32 indexed domain, address indexed agent, bytes snapPayload, bytes snapSignature);\n\n /**\n * @notice Emitted when a snapshot is accepted by the Summit contract.\n * @param domain Domain where the signed Notary is active\n * @param notary Notary who signed the attestation\n * @param rcptPayload Raw payload with receipt data\n * @param rcptSignature Notary signature for the receipt\n */\n event ReceiptAccepted(uint32 domain, address notary, bytes rcptPayload, bytes rcptSignature);\n\n /**\n * @notice Emitted when a proof of invalid attestation is submitted.\n * @param attPayload Raw payload with Attestation data\n * @param attSignature Notary signature for the attestation\n */\n event InvalidAttestation(bytes attPayload, bytes attSignature);\n\n /**\n * @notice Emitted when a proof of invalid attestation report is submitted.\n * @param arPayload Raw payload with report data\n * @param arSignature Guard signature for the report\n */\n event InvalidAttestationReport(bytes arPayload, bytes arSignature);\n}\n\n// contracts/events/StatementInboxEvents.sol\n\nabstract contract StatementInboxEvents {\n // ════════════════════════════════════════════ STATEMENT ACCEPTED ═════════════════════════════════════════════════\n\n /**\n * @notice Emitted when a snapshot is accepted by the Destination contract.\n * @param domain Domain where the signed Notary is active\n * @param notary Notary who signed the attestation\n * @param attPayload Raw payload with attestation data\n * @param attSignature Notary signature for the attestation\n */\n event AttestationAccepted(uint32 domain, address notary, bytes attPayload, bytes attSignature);\n\n // ═════════════════════════════════════════ INVALID STATEMENT PROVED ══════════════════════════════════════════════\n\n /**\n * @notice Emitted when a proof of invalid receipt statement is submitted.\n * @param rcptPayload Raw payload with the receipt statement\n * @param rcptSignature Notary signature for the receipt statement\n */\n event InvalidReceipt(bytes rcptPayload, bytes rcptSignature);\n\n /**\n * @notice Emitted when a proof of invalid receipt report is submitted.\n * @param rrPayload Raw payload with report data\n * @param rrSignature Guard signature for the report\n */\n event InvalidReceiptReport(bytes rrPayload, bytes rrSignature);\n\n /**\n * @notice Emitted when a proof of invalid state in the signed attestation is submitted.\n * @param stateIndex Index of invalid state in the snapshot\n * @param statePayload Raw payload with state data\n * @param attPayload Raw payload with Attestation data for snapshot\n * @param attSignature Notary signature for the attestation\n */\n event InvalidStateWithAttestation(uint8 stateIndex, bytes statePayload, bytes attPayload, bytes attSignature);\n\n /**\n * @notice Emitted when a proof of invalid state in the signed snapshot is submitted.\n * @param stateIndex Index of invalid state in the snapshot\n * @param snapPayload Raw payload with snapshot data\n * @param snapSignature Agent signature for the snapshot\n */\n event InvalidStateWithSnapshot(uint8 stateIndex, bytes snapPayload, bytes snapSignature);\n\n /**\n * @notice Emitted when a proof of invalid state report is submitted.\n * @param srPayload Raw payload with report data\n * @param srSignature Guard signature for the report\n */\n event InvalidStateReport(bytes srPayload, bytes srSignature);\n}\n\n// contracts/interfaces/ISnapshotHub.sol\n\ninterface ISnapshotHub {\n /**\n * @notice Check that a given attestation is valid: matches the historical attestation\n * derived from an accepted Notary snapshot.\n * @dev Will revert if any of these is true:\n * - Attestation payload is not properly formatted.\n * @param attPayload Raw payload with attestation data\n * @return isValid Whether the provided attestation is valid\n */\n function isValidAttestation(bytes memory attPayload) external view returns (bool isValid);\n\n /**\n * @notice Returns saved attestation with the given nonce.\n * @dev Reverts if attestation with given nonce hasn't been created yet.\n * @param attNonce Nonce for the attestation\n * @return attPayload Raw payload with formatted Attestation data\n * @return agentRoot Agent root hash used for the attestation\n * @return snapGas Snapshot gas data used for the attestation\n */\n function getAttestation(uint32 attNonce)\n external\n view\n returns (bytes memory attPayload, bytes32 agentRoot, uint256[] memory snapGas);\n\n /**\n * @notice Returns the state with the highest known nonce submitted by a given Agent.\n * @param origin Domain of origin chain\n * @param agent Agent address\n * @return statePayload Raw payload with agent's latest state for origin\n */\n function getLatestAgentState(uint32 origin, address agent) external view returns (bytes memory statePayload);\n\n /**\n * @notice Returns latest saved attestation for a Notary.\n * @param notary Notary address\n * @return attPayload Raw payload with formatted Attestation data\n * @return agentRoot Agent root hash used for the attestation\n * @return snapGas Snapshot gas data used for the attestation\n */\n function getLatestNotaryAttestation(address notary)\n external\n view\n returns (bytes memory attPayload, bytes32 agentRoot, uint256[] memory snapGas);\n\n /**\n * @notice Returns Guard snapshot from the list of all accepted Guard snapshots.\n * @dev Reverts if snapshot with given index hasn't been accepted yet.\n * @param index Snapshot index in the list of all Guard snapshots\n * @return snapPayload Raw payload with Guard snapshot\n * @return snapSignature Raw payload with Guard signature for snapshot\n */\n function getGuardSnapshot(uint256 index)\n external\n view\n returns (bytes memory snapPayload, bytes memory snapSignature);\n\n /**\n * @notice Returns Notary snapshot from the list of all accepted Guard snapshots.\n * @dev Reverts if snapshot with given index hasn't been accepted yet.\n * @param index Snapshot index in the list of all Notary snapshots\n * @return snapPayload Raw payload with Notary snapshot\n * @return snapSignature Raw payload with Notary signature for snapshot\n */\n function getNotarySnapshot(uint256 index)\n external\n view\n returns (bytes memory snapPayload, bytes memory snapSignature);\n\n /**\n * @notice Returns Notary snapshot that was used for creating a given attestation.\n * @dev Reverts if any of these is true:\n * - Attestation payload is not properly formatted.\n * - Attestation is invalid (doesn't have a matching Notary snapshot).\n * @param attPayload Raw payload with attestation data\n * @return snapPayload Raw payload with Notary snapshot\n * @return snapSignature Raw payload with Notary signature for snapshot\n */\n function getNotarySnapshot(bytes memory attPayload)\n external\n view\n returns (bytes memory snapPayload, bytes memory snapSignature);\n\n /**\n * @notice Returns proof of inclusion of (root, origin) fields of a given snapshot's state\n * into the Snapshot Merkle Tree for a given attestation.\n * @dev Reverts if any of these is true:\n * - Attestation with given nonce hasn't been created yet.\n * - State index is out of range of snapshot list.\n * @param attNonce Nonce for the attestation\n * @param stateIndex Index of state in the attestation's snapshot\n * @return snapProof The snapshot proof\n */\n function getSnapshotProof(uint32 attNonce, uint8 stateIndex) external view returns (bytes32[] memory snapProof);\n}\n\n// contracts/interfaces/IStateHub.sol\n\ninterface IStateHub {\n /**\n * @notice Check that a given state is valid: matches the historical state of Origin contract.\n * Note: any Agent including an invalid state in their snapshot will be slashed\n * upon providing the snapshot and agent signature for it to Origin contract.\n * @dev Will revert if any of these is true:\n * - State payload is not properly formatted.\n * @param statePayload Raw payload with state data\n * @return isValid Whether the provided state is valid\n */\n function isValidState(bytes memory statePayload) external view returns (bool isValid);\n\n /**\n * @notice Returns the amount of saved states so far.\n * @dev This includes the initial state of \"empty Origin Merkle Tree\".\n */\n function statesAmount() external view returns (uint256);\n\n /**\n * @notice Suggest the data (state after latest sent message) to sign for an Agent.\n * Note: signing the suggested state data will will never lead to slashing of the actor,\n * assuming they have confirmed that the block, which number is included in the data,\n * is not subject to reorganization (which is different for every observed chain).\n * @return statePayload Raw payload with the latest state data\n */\n function suggestLatestState() external view returns (bytes memory statePayload);\n\n /**\n * @notice Given the historical nonce, suggest the state data to sign for an Agent.\n * Note: signing the suggested state data will will never lead to slashing of the actor,\n * assuming they have confirmed that the block, which number is included in the data,\n * is not subject to reorganization (which is different for every observed chain).\n * @param nonce Historical nonce to form a state\n * @return statePayload Raw payload with historical state data\n */\n function suggestState(uint32 nonce) external view returns (bytes memory statePayload);\n}\n\n// contracts/interfaces/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/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// node_modules/@openzeppelin/contracts/utils/math/Math.sol\n\n// OpenZeppelin Contracts (last updated v4.9.0) (utils/math/Math.sol)\n\n/**\n * @dev Standard math utilities missing in the Solidity language.\n */\nlibrary Math {\n enum Rounding {\n Down, // Toward negative infinity\n Up, // Toward infinity\n Zero // Toward zero\n }\n\n /**\n * @dev Returns the largest of two numbers.\n */\n function max(uint256 a, uint256 b) internal pure returns (uint256) {\n return a \u003e b ? a : b;\n }\n\n /**\n * @dev Returns the smallest of two numbers.\n */\n function min(uint256 a, uint256 b) internal pure returns (uint256) {\n return a \u003c b ? a : b;\n }\n\n /**\n * @dev Returns the average of two numbers. The result is rounded towards\n * zero.\n */\n function average(uint256 a, uint256 b) internal pure returns (uint256) {\n // (a + b) / 2 can overflow.\n return (a \u0026 b) + (a ^ b) / 2;\n }\n\n /**\n * @dev Returns the ceiling of the division of two numbers.\n *\n * This differs from standard division with `/` in that it rounds up instead\n * of rounding down.\n */\n function ceilDiv(uint256 a, uint256 b) internal pure returns (uint256) {\n // (a + b - 1) / b can overflow on addition, so we distribute.\n return a == 0 ? 0 : (a - 1) / b + 1;\n }\n\n /**\n * @notice Calculates floor(x * y / denominator) with full precision. Throws if result overflows a uint256 or denominator == 0\n * @dev Original credit to Remco Bloemen under MIT license (https://xn--2-umb.com/21/muldiv)\n * with further edits by Uniswap Labs also under MIT license.\n */\n function mulDiv(uint256 x, uint256 y, uint256 denominator) internal pure returns (uint256 result) {\n unchecked {\n // 512-bit multiply [prod1 prod0] = x * y. Compute the product mod 2^256 and mod 2^256 - 1, then use\n // use the Chinese Remainder Theorem to reconstruct the 512 bit result. The result is stored in two 256\n // variables such that product = prod1 * 2^256 + prod0.\n uint256 prod0; // Least significant 256 bits of the product\n uint256 prod1; // Most significant 256 bits of the product\n assembly {\n let mm := mulmod(x, y, not(0))\n prod0 := mul(x, y)\n prod1 := sub(sub(mm, prod0), lt(mm, prod0))\n }\n\n // Handle non-overflow cases, 256 by 256 division.\n if (prod1 == 0) {\n // Solidity will revert if denominator == 0, unlike the div opcode on its own.\n // The surrounding unchecked block does not change this fact.\n // See https://docs.soliditylang.org/en/latest/control-structures.html#checked-or-unchecked-arithmetic.\n return prod0 / denominator;\n }\n\n // Make sure the result is less than 2^256. Also prevents denominator == 0.\n require(denominator \u003e prod1, \"Math: mulDiv overflow\");\n\n ///////////////////////////////////////////////\n // 512 by 256 division.\n ///////////////////////////////////////////////\n\n // Make division exact by subtracting the remainder from [prod1 prod0].\n uint256 remainder;\n assembly {\n // Compute remainder using mulmod.\n remainder := mulmod(x, y, denominator)\n\n // Subtract 256 bit number from 512 bit number.\n prod1 := sub(prod1, gt(remainder, prod0))\n prod0 := sub(prod0, remainder)\n }\n\n // Factor powers of two out of denominator and compute largest power of two divisor of denominator. Always \u003e= 1.\n // See https://cs.stackexchange.com/q/138556/92363.\n\n // Does not overflow because the denominator cannot be zero at this stage in the function.\n uint256 twos = denominator \u0026 (~denominator + 1);\n assembly {\n // Divide denominator by twos.\n denominator := div(denominator, twos)\n\n // Divide [prod1 prod0] by twos.\n prod0 := div(prod0, twos)\n\n // Flip twos such that it is 2^256 / twos. If twos is zero, then it becomes one.\n twos := add(div(sub(0, twos), twos), 1)\n }\n\n // Shift in bits from prod1 into prod0.\n prod0 |= prod1 * twos;\n\n // Invert denominator mod 2^256. Now that denominator is an odd number, it has an inverse modulo 2^256 such\n // that denominator * inv = 1 mod 2^256. Compute the inverse by starting with a seed that is correct for\n // four bits. That is, denominator * inv = 1 mod 2^4.\n uint256 inverse = (3 * denominator) ^ 2;\n\n // Use the Newton-Raphson iteration to improve the precision. Thanks to Hensel's lifting lemma, this also works\n // in modular arithmetic, doubling the correct bits in each step.\n inverse *= 2 - denominator * inverse; // inverse mod 2^8\n inverse *= 2 - denominator * inverse; // inverse mod 2^16\n inverse *= 2 - denominator * inverse; // inverse mod 2^32\n inverse *= 2 - denominator * inverse; // inverse mod 2^64\n inverse *= 2 - denominator * inverse; // inverse mod 2^128\n inverse *= 2 - denominator * inverse; // inverse mod 2^256\n\n // Because the division is now exact we can divide by multiplying with the modular inverse of denominator.\n // This will give us the correct result modulo 2^256. Since the preconditions guarantee that the outcome is\n // less than 2^256, this is the final result. We don't need to compute the high bits of the result and prod1\n // is no longer required.\n result = prod0 * inverse;\n return result;\n }\n }\n\n /**\n * @notice Calculates x * y / denominator with full precision, following the selected rounding direction.\n */\n function mulDiv(uint256 x, uint256 y, uint256 denominator, Rounding rounding) internal pure returns (uint256) {\n uint256 result = mulDiv(x, y, denominator);\n if (rounding == Rounding.Up \u0026\u0026 mulmod(x, y, denominator) \u003e 0) {\n result += 1;\n }\n return result;\n }\n\n /**\n * @dev Returns the square root of a number. If the number is not a perfect square, the value is rounded down.\n *\n * Inspired by Henry S. Warren, Jr.'s \"Hacker's Delight\" (Chapter 11).\n */\n function sqrt(uint256 a) internal pure returns (uint256) {\n if (a == 0) {\n return 0;\n }\n\n // For our first guess, we get the biggest power of 2 which is smaller than the square root of the target.\n //\n // We know that the \"msb\" (most significant bit) of our target number `a` is a power of 2 such that we have\n // `msb(a) \u003c= a \u003c 2*msb(a)`. This value can be written `msb(a)=2**k` with `k=log2(a)`.\n //\n // This can be rewritten `2**log2(a) \u003c= a \u003c 2**(log2(a) + 1)`\n // → `sqrt(2**k) \u003c= sqrt(a) \u003c sqrt(2**(k+1))`\n // → `2**(k/2) \u003c= sqrt(a) \u003c 2**((k+1)/2) \u003c= 2**(k/2 + 1)`\n //\n // Consequently, `2**(log2(a) / 2)` is a good first approximation of `sqrt(a)` with at least 1 correct bit.\n uint256 result = 1 \u003c\u003c (log2(a) \u003e\u003e 1);\n\n // At this point `result` is an estimation with one bit of precision. We know the true value is a uint128,\n // since it is the square root of a uint256. Newton's method converges quadratically (precision doubles at\n // every iteration). We thus need at most 7 iteration to turn our partial result with one bit of precision\n // into the expected uint128 result.\n unchecked {\n result = (result + a / result) \u003e\u003e 1;\n result = (result + a / result) \u003e\u003e 1;\n result = (result + a / result) \u003e\u003e 1;\n result = (result + a / result) \u003e\u003e 1;\n result = (result + a / result) \u003e\u003e 1;\n result = (result + a / result) \u003e\u003e 1;\n result = (result + a / result) \u003e\u003e 1;\n return min(result, a / result);\n }\n }\n\n /**\n * @notice Calculates sqrt(a), following the selected rounding direction.\n */\n function sqrt(uint256 a, Rounding rounding) internal pure returns (uint256) {\n unchecked {\n uint256 result = sqrt(a);\n return result + (rounding == Rounding.Up \u0026\u0026 result * result \u003c a ? 1 : 0);\n }\n }\n\n /**\n * @dev Return the log in base 2, rounded down, of a positive value.\n * Returns 0 if given 0.\n */\n function log2(uint256 value) internal pure returns (uint256) {\n uint256 result = 0;\n unchecked {\n if (value \u003e\u003e 128 \u003e 0) {\n value \u003e\u003e= 128;\n result += 128;\n }\n if (value \u003e\u003e 64 \u003e 0) {\n value \u003e\u003e= 64;\n result += 64;\n }\n if (value \u003e\u003e 32 \u003e 0) {\n value \u003e\u003e= 32;\n result += 32;\n }\n if (value \u003e\u003e 16 \u003e 0) {\n value \u003e\u003e= 16;\n result += 16;\n }\n if (value \u003e\u003e 8 \u003e 0) {\n value \u003e\u003e= 8;\n result += 8;\n }\n if (value \u003e\u003e 4 \u003e 0) {\n value \u003e\u003e= 4;\n result += 4;\n }\n if (value \u003e\u003e 2 \u003e 0) {\n value \u003e\u003e= 2;\n result += 2;\n }\n if (value \u003e\u003e 1 \u003e 0) {\n result += 1;\n }\n }\n return result;\n }\n\n /**\n * @dev Return the log in base 2, following the selected rounding direction, of a positive value.\n * Returns 0 if given 0.\n */\n function log2(uint256 value, Rounding rounding) internal pure returns (uint256) {\n unchecked {\n uint256 result = log2(value);\n return result + (rounding == Rounding.Up \u0026\u0026 1 \u003c\u003c result \u003c value ? 1 : 0);\n }\n }\n\n /**\n * @dev Return the log in base 10, rounded down, of a positive value.\n * Returns 0 if given 0.\n */\n function log10(uint256 value) internal pure returns (uint256) {\n uint256 result = 0;\n unchecked {\n if (value \u003e= 10 ** 64) {\n value /= 10 ** 64;\n result += 64;\n }\n if (value \u003e= 10 ** 32) {\n value /= 10 ** 32;\n result += 32;\n }\n if (value \u003e= 10 ** 16) {\n value /= 10 ** 16;\n result += 16;\n }\n if (value \u003e= 10 ** 8) {\n value /= 10 ** 8;\n result += 8;\n }\n if (value \u003e= 10 ** 4) {\n value /= 10 ** 4;\n result += 4;\n }\n if (value \u003e= 10 ** 2) {\n value /= 10 ** 2;\n result += 2;\n }\n if (value \u003e= 10 ** 1) {\n result += 1;\n }\n }\n return result;\n }\n\n /**\n * @dev Return the log in base 10, following the selected rounding direction, of a positive value.\n * Returns 0 if given 0.\n */\n function log10(uint256 value, Rounding rounding) internal pure returns (uint256) {\n unchecked {\n uint256 result = log10(value);\n return result + (rounding == Rounding.Up \u0026\u0026 10 ** result \u003c value ? 1 : 0);\n }\n }\n\n /**\n * @dev Return the log in base 256, rounded down, of a positive value.\n * Returns 0 if given 0.\n *\n * Adding one to the result gives the number of pairs of hex symbols needed to represent `value` as a hex string.\n */\n function log256(uint256 value) internal pure returns (uint256) {\n uint256 result = 0;\n unchecked {\n if (value \u003e\u003e 128 \u003e 0) {\n value \u003e\u003e= 128;\n result += 16;\n }\n if (value \u003e\u003e 64 \u003e 0) {\n value \u003e\u003e= 64;\n result += 8;\n }\n if (value \u003e\u003e 32 \u003e 0) {\n value \u003e\u003e= 32;\n result += 4;\n }\n if (value \u003e\u003e 16 \u003e 0) {\n value \u003e\u003e= 16;\n result += 2;\n }\n if (value \u003e\u003e 8 \u003e 0) {\n result += 1;\n }\n }\n return result;\n }\n\n /**\n * @dev Return the log in base 256, following the selected rounding direction, of a positive value.\n * Returns 0 if given 0.\n */\n function log256(uint256 value, Rounding rounding) internal pure returns (uint256) {\n unchecked {\n uint256 result = log256(value);\n return result + (rounding == Rounding.Up \u0026\u0026 1 \u003c\u003c (result \u003c\u003c 3) \u003c value ? 1 : 0);\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/utils/math/SignedMath.sol\n\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/math/SignedMath.sol)\n\n/**\n * @dev Standard signed math utilities missing in the Solidity language.\n */\nlibrary SignedMath {\n /**\n * @dev Returns the largest of two signed numbers.\n */\n function max(int256 a, int256 b) internal pure returns (int256) {\n return a \u003e b ? a : b;\n }\n\n /**\n * @dev Returns the smallest of two signed numbers.\n */\n function min(int256 a, int256 b) internal pure returns (int256) {\n return a \u003c b ? a : b;\n }\n\n /**\n * @dev Returns the average of two signed numbers without overflow.\n * The result is rounded towards zero.\n */\n function average(int256 a, int256 b) internal pure returns (int256) {\n // Formula from the book \"Hacker's Delight\"\n int256 x = (a \u0026 b) + ((a ^ b) \u003e\u003e 1);\n return x + (int256(uint256(x) \u003e\u003e 255) \u0026 (a ^ b));\n }\n\n /**\n * @dev Returns the absolute unsigned value of a signed value.\n */\n function abs(int256 n) internal pure returns (uint256) {\n unchecked {\n // must be unchecked in order to support `n = type(int256).min`\n return uint256(n \u003e= 0 ? n : -n);\n }\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// 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/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/InterfaceSummit.sol\n\ninterface InterfaceSummit {\n // ══════════════════════════════════════════ ACCEPT AGENT STATEMENTS ══════════════════════════════════════════════\n\n /**\n * @notice Accepts a receipt, which local `AgentManager` verified to have been signed by an active Notary.\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 * - Notary who signed the receipt is referenced as the \"Receipt Notary\".\n * - Notary who signed the attestation on destination chain is referenced as the \"Attestation Notary\".\n * \u003e Will revert if any of these is true:\n * \u003e - Called by anyone other than local `AgentManager`.\n * \u003e - Receipt body payload is not properly formatted.\n * \u003e - Receipt signer is in Dispute.\n * \u003e - Receipt's snapshot root is unknown.\n * @param rcptNotaryIndex Index of Receipt Notary in Agent Merkle Tree\n * @param attNotaryIndex Index of Attestation Notary in Agent Merkle Tree\n * @param sigIndex Index of stored Notary signature\n * @param attNonce Nonce of the attestation used for proving the executed message\n * @param paddedTips Padded encoded paid tips information\n * @param rcptPayload Raw payload with message execution receipt\n * @return wasAccepted Whether the receipt was accepted\n */\n function acceptReceipt(\n uint32 rcptNotaryIndex,\n uint32 attNotaryIndex,\n uint256 sigIndex,\n uint32 attNonce,\n uint256 paddedTips,\n bytes memory rcptPayload\n ) external returns (bool wasAccepted);\n\n /**\n * @notice Accepts a snapshot, which local `AgentManager` verified to have been signed by an active Guard.\n * \u003e Snapshot is a list of states for a set of Origin contracts residing on any of the chains.\n * All the states in the Guard-signed snapshot become available for Notary signing.\n * \u003e Will revert if any of these is true:\n * \u003e - Called by anyone other than local `AgentManager`.\n * \u003e - Snapshot payload is not properly formatted.\n * \u003e - Snapshot contains a state older then the Guard has previously submitted.\n * @param guardIndex Index of Guard in Agent Merkle Tree\n * @param sigIndex Index of stored Agent signature\n * @param snapPayload Raw payload with snapshot data\n */\n function acceptGuardSnapshot(uint32 guardIndex, uint256 sigIndex, bytes memory snapPayload) external;\n\n /**\n * @notice Accepts a snapshot, which local `AgentManager` verified to have been signed by an active Notary.\n * \u003e Snapshot is a list of states for a set of Origin contracts residing on any of the chains.\n * Snapshot Merkle Root is calculated and saved for valid snapshots, i.e.\n * snapshots which are only using states previously submitted by any of the Guards.\n * - Notary could use states singed by the same of different Guards 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 - Called by anyone other than local `AgentManager`.\n * \u003e - Snapshot payload is not properly formatted.\n * \u003e - Snapshot contains a state older then the Notary has previously submitted.\n * \u003e - Snapshot contains a state that no Guard has previously submitted.\n * @param notaryIndex Index of Notary in Agent Merkle Tree\n * @param sigIndex Index of stored Agent signature\n * @param agentRoot Current root of the Agent Merkle Tree\n * @param snapPayload Raw payload with snapshot data\n * @return attPayload Raw payload with data for attestation derived from Notary snapshot.\n */\n function acceptNotarySnapshot(uint32 notaryIndex, uint256 sigIndex, bytes32 agentRoot, bytes memory snapPayload)\n external\n returns (bytes memory attPayload);\n\n // ════════════════════════════════════════════════ TIPS LOGIC ═════════════════════════════════════════════════════\n\n /**\n * @notice Distributes tips using the first Receipt from the \"receipt quarantine queue\".\n * Possible scenarios:\n * - Receipt queue is empty =\u003e does nothing\n * - Receipt optimistic period is not over =\u003e does nothing\n * - Either of Notaries present in Receipt was slashed =\u003e receipt is deleted from the queue\n * - Either of Notaries present in Receipt in Dispute =\u003e receipt is moved to the end of queue\n * - None of the above =\u003e receipt tips are distributed\n * @dev Returned value makes it possible to do the following: `while (distributeTips()) {}`\n * @return queuePopped Whether the first element was popped from the queue\n */\n function distributeTips() external returns (bool queuePopped);\n\n /**\n * @notice Withdraws locked base message tips from requested domain Origin to the recipient.\n * This is done by a call to a local Origin contract, or by a manager message to the remote chain.\n * @dev This will revert, if the pending balance of origin tips (earned-claimed) is lower than requested.\n * @param origin Domain of chain to withdraw tips on\n * @param amount Amount of tips to withdraw\n */\n function withdrawTips(uint32 origin, uint256 amount) external;\n\n // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════\n\n /**\n * @notice Returns earned and claimed tips for the actor.\n * Note: Tips for address(0) belong to the Treasury.\n * @param actor Address of the actor\n * @param origin Domain where the tips were initially paid\n * @return earned Total amount of origin tips the actor has earned so far\n * @return claimed Total amount of origin tips the actor has claimed so far\n */\n function actorTips(address actor, uint32 origin) external view returns (uint128 earned, uint128 claimed);\n\n /**\n * @notice Returns the amount of receipts in the \"Receipt Quarantine Queue\".\n */\n function receiptQueueLength() external view returns (uint256);\n\n /**\n * @notice Returns the state with the highest known nonce\n * submitted by any of the currently active Guards.\n * @param origin Domain of origin chain\n * @return statePayload Raw payload with latest active Guard state for origin\n */\n function getLatestState(uint32 origin) external view returns (bytes memory statePayload);\n}\n\n// node_modules/@openzeppelin/contracts/utils/Strings.sol\n\n// OpenZeppelin Contracts (last updated v4.9.0) (utils/Strings.sol)\n\n/**\n * @dev String operations.\n */\nlibrary Strings {\n bytes16 private constant _SYMBOLS = \"0123456789abcdef\";\n uint8 private constant _ADDRESS_LENGTH = 20;\n\n /**\n * @dev Converts a `uint256` to its ASCII `string` decimal representation.\n */\n function toString(uint256 value) internal pure returns (string memory) {\n unchecked {\n uint256 length = Math.log10(value) + 1;\n string memory buffer = new string(length);\n uint256 ptr;\n /// @solidity memory-safe-assembly\n assembly {\n ptr := add(buffer, add(32, length))\n }\n while (true) {\n ptr--;\n /// @solidity memory-safe-assembly\n assembly {\n mstore8(ptr, byte(mod(value, 10), _SYMBOLS))\n }\n value /= 10;\n if (value == 0) break;\n }\n return buffer;\n }\n }\n\n /**\n * @dev Converts a `int256` to its ASCII `string` decimal representation.\n */\n function toString(int256 value) internal pure returns (string memory) {\n return string(abi.encodePacked(value \u003c 0 ? \"-\" : \"\", toString(SignedMath.abs(value))));\n }\n\n /**\n * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation.\n */\n function toHexString(uint256 value) internal pure returns (string memory) {\n unchecked {\n return toHexString(value, Math.log256(value) + 1);\n }\n }\n\n /**\n * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length.\n */\n function toHexString(uint256 value, uint256 length) internal pure returns (string memory) {\n bytes memory buffer = new bytes(2 * length + 2);\n buffer[0] = \"0\";\n buffer[1] = \"x\";\n for (uint256 i = 2 * length + 1; i \u003e 1; --i) {\n buffer[i] = _SYMBOLS[value \u0026 0xf];\n value \u003e\u003e= 4;\n }\n require(value == 0, \"Strings: hex length insufficient\");\n return string(buffer);\n }\n\n /**\n * @dev Converts an `address` with fixed length of 20 bytes to its not checksummed ASCII `string` hexadecimal representation.\n */\n function toHexString(address addr) internal pure returns (string memory) {\n return toHexString(uint256(uint160(addr)), _ADDRESS_LENGTH);\n }\n\n /**\n * @dev Returns true if the two strings are equal.\n */\n function equal(string memory a, string memory b) internal pure returns (bool) {\n return keccak256(bytes(a)) == keccak256(bytes(b));\n }\n}\n\n// node_modules/@openzeppelin/contracts-upgradeable/utils/ContextUpgradeable.sol\n\n// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)\n\n/**\n * @dev Provides information about the current execution context, including the\n * sender of the transaction and its data. While these are generally available\n * via msg.sender and msg.data, they should not be accessed in such a direct\n * manner, since when dealing with meta-transactions the account sending and\n * paying for execution may not be the actual sender (as far as an application\n * is concerned).\n *\n * This contract is only required for intermediate, library-like contracts.\n */\nabstract contract ContextUpgradeable is Initializable {\n function __Context_init() internal onlyInitializing {\n }\n\n function __Context_init_unchained() internal onlyInitializing {\n }\n function _msgSender() internal view virtual returns (address) {\n return msg.sender;\n }\n\n function _msgData() internal view virtual returns (bytes calldata) {\n return msg.data;\n }\n\n /**\n * @dev This empty reserved space is put in place to allow future versions to add new\n * variables without shifting down storage in the inheritance chain.\n * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\n */\n uint256[50] private __gap;\n}\n\n// contracts/libs/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/utils/cryptography/ECDSA.sol\n\n// OpenZeppelin Contracts (last updated v4.9.0) (utils/cryptography/ECDSA.sol)\n\n/**\n * @dev Elliptic Curve Digital Signature Algorithm (ECDSA) operations.\n *\n * These functions can be used to verify that a message was signed by the holder\n * of the private keys of a given address.\n */\nlibrary ECDSA {\n enum RecoverError {\n NoError,\n InvalidSignature,\n InvalidSignatureLength,\n InvalidSignatureS,\n InvalidSignatureV // Deprecated in v4.8\n }\n\n function _throwError(RecoverError error) private pure {\n if (error == RecoverError.NoError) {\n return; // no error: do nothing\n } else if (error == RecoverError.InvalidSignature) {\n revert(\"ECDSA: invalid signature\");\n } else if (error == RecoverError.InvalidSignatureLength) {\n revert(\"ECDSA: invalid signature length\");\n } else if (error == RecoverError.InvalidSignatureS) {\n revert(\"ECDSA: invalid signature 's' value\");\n }\n }\n\n /**\n * @dev Returns the address that signed a hashed message (`hash`) with\n * `signature` or error string. This address can then be used for verification purposes.\n *\n * The `ecrecover` EVM opcode allows for malleable (non-unique) signatures:\n * this function rejects them by requiring the `s` value to be in the lower\n * half order, and the `v` value to be either 27 or 28.\n *\n * IMPORTANT: `hash` _must_ be the result of a hash operation for the\n * verification to be secure: it is possible to craft signatures that\n * recover to arbitrary addresses for non-hashed data. A safe way to ensure\n * this is by receiving a hash of the original message (which may otherwise\n * be too long), and then calling {toEthSignedMessageHash} on it.\n *\n * Documentation for signature generation:\n * - with https://web3js.readthedocs.io/en/v1.3.4/web3-eth-accounts.html#sign[Web3.js]\n * - with https://docs.ethers.io/v5/api/signer/#Signer-signMessage[ethers]\n *\n * _Available since v4.3._\n */\n function tryRecover(bytes32 hash, bytes memory signature) internal pure returns (address, RecoverError) {\n if (signature.length == 65) {\n bytes32 r;\n bytes32 s;\n uint8 v;\n // ecrecover takes the signature parameters, and the only way to get them\n // currently is to use assembly.\n /// @solidity memory-safe-assembly\n assembly {\n r := mload(add(signature, 0x20))\n s := mload(add(signature, 0x40))\n v := byte(0, mload(add(signature, 0x60)))\n }\n return tryRecover(hash, v, r, s);\n } else {\n return (address(0), RecoverError.InvalidSignatureLength);\n }\n }\n\n /**\n * @dev Returns the address that signed a hashed message (`hash`) with\n * `signature`. This address can then be used for verification purposes.\n *\n * The `ecrecover` EVM opcode allows for malleable (non-unique) signatures:\n * this function rejects them by requiring the `s` value to be in the lower\n * half order, and the `v` value to be either 27 or 28.\n *\n * IMPORTANT: `hash` _must_ be the result of a hash operation for the\n * verification to be secure: it is possible to craft signatures that\n * recover to arbitrary addresses for non-hashed data. A safe way to ensure\n * this is by receiving a hash of the original message (which may otherwise\n * be too long), and then calling {toEthSignedMessageHash} on it.\n */\n function recover(bytes32 hash, bytes memory signature) internal pure returns (address) {\n (address recovered, RecoverError error) = tryRecover(hash, signature);\n _throwError(error);\n return recovered;\n }\n\n /**\n * @dev Overload of {ECDSA-tryRecover} that receives the `r` and `vs` short-signature fields separately.\n *\n * See https://eips.ethereum.org/EIPS/eip-2098[EIP-2098 short signatures]\n *\n * _Available since v4.3._\n */\n function tryRecover(bytes32 hash, bytes32 r, bytes32 vs) internal pure returns (address, RecoverError) {\n bytes32 s = vs \u0026 bytes32(0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff);\n uint8 v = uint8((uint256(vs) \u003e\u003e 255) + 27);\n return tryRecover(hash, v, r, s);\n }\n\n /**\n * @dev Overload of {ECDSA-recover} that receives the `r and `vs` short-signature fields separately.\n *\n * _Available since v4.2._\n */\n function recover(bytes32 hash, bytes32 r, bytes32 vs) internal pure returns (address) {\n (address recovered, RecoverError error) = tryRecover(hash, r, vs);\n _throwError(error);\n return recovered;\n }\n\n /**\n * @dev Overload of {ECDSA-tryRecover} that receives the `v`,\n * `r` and `s` signature fields separately.\n *\n * _Available since v4.3._\n */\n function tryRecover(bytes32 hash, uint8 v, bytes32 r, bytes32 s) internal pure returns (address, RecoverError) {\n // EIP-2 still allows signature malleability for ecrecover(). Remove this possibility and make the signature\n // unique. Appendix F in the Ethereum Yellow paper (https://ethereum.github.io/yellowpaper/paper.pdf), defines\n // the valid range for s in (301): 0 \u003c s \u003c secp256k1n ÷ 2 + 1, and for v in (302): v ∈ {27, 28}. Most\n // signatures from current libraries generate a unique signature with an s-value in the lower half order.\n //\n // If your library generates malleable signatures, such as s-values in the upper range, calculate a new s-value\n // with 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141 - s1 and flip v from 27 to 28 or\n // vice versa. If your library also generates signatures with 0/1 for v instead 27/28, add 27 to v to accept\n // these malleable signatures as well.\n if (uint256(s) \u003e 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0) {\n return (address(0), RecoverError.InvalidSignatureS);\n }\n\n // If the signature is valid (and not malleable), return the signer address\n address signer = ecrecover(hash, v, r, s);\n if (signer == address(0)) {\n return (address(0), RecoverError.InvalidSignature);\n }\n\n return (signer, RecoverError.NoError);\n }\n\n /**\n * @dev Overload of {ECDSA-recover} that receives the `v`,\n * `r` and `s` signature fields separately.\n */\n function recover(bytes32 hash, uint8 v, bytes32 r, bytes32 s) internal pure returns (address) {\n (address recovered, RecoverError error) = tryRecover(hash, v, r, s);\n _throwError(error);\n return recovered;\n }\n\n /**\n * @dev Returns an Ethereum Signed Message, created from a `hash`. This\n * produces hash corresponding to the one signed with the\n * https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`]\n * JSON-RPC method as part of EIP-191.\n *\n * See {recover}.\n */\n function toEthSignedMessageHash(bytes32 hash) internal pure returns (bytes32 message) {\n // 32 is the length in bytes of hash,\n // enforced by the type signature above\n /// @solidity memory-safe-assembly\n assembly {\n mstore(0x00, \"\\x19Ethereum Signed Message:\\n32\")\n mstore(0x1c, hash)\n message := keccak256(0x00, 0x3c)\n }\n }\n\n /**\n * @dev Returns an Ethereum Signed Message, created from `s`. This\n * produces hash corresponding to the one signed with the\n * https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`]\n * JSON-RPC method as part of EIP-191.\n *\n * See {recover}.\n */\n function toEthSignedMessageHash(bytes memory s) internal pure returns (bytes32) {\n return keccak256(abi.encodePacked(\"\\x19Ethereum Signed Message:\\n\", Strings.toString(s.length), s));\n }\n\n /**\n * @dev Returns an Ethereum Signed Typed Data, created from a\n * `domainSeparator` and a `structHash`. This produces hash corresponding\n * to the one signed with the\n * https://eips.ethereum.org/EIPS/eip-712[`eth_signTypedData`]\n * JSON-RPC method as part of EIP-712.\n *\n * See {recover}.\n */\n function toTypedDataHash(bytes32 domainSeparator, bytes32 structHash) internal pure returns (bytes32 data) {\n /// @solidity memory-safe-assembly\n assembly {\n let ptr := mload(0x40)\n mstore(ptr, \"\\x19\\x01\")\n mstore(add(ptr, 0x02), domainSeparator)\n mstore(add(ptr, 0x22), structHash)\n data := keccak256(ptr, 0x42)\n }\n }\n\n /**\n * @dev Returns an Ethereum Signed Data with intended validator, created from a\n * `validator` and `data` according to the version 0 of EIP-191.\n *\n * See {recover}.\n */\n function toDataWithIntendedValidatorHash(address validator, bytes memory data) internal pure returns (bytes32) {\n return keccak256(abi.encodePacked(\"\\x19\\x00\", validator, data));\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/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/inbox/StatementInbox.sol\n\n// ══════════════════════════════ LIBRARY IMPORTS ══════════════════════════════\n\n// ═════════════════════════════ INTERNAL IMPORTS ══════════════════════════════\n\n// ═════════════════════════════ EXTERNAL IMPORTS ══════════════════════════════\n\n/// @notice `StatementInbox` is the entry point for all agent-signed statements. It verifies the\n/// agent signatures, and passes the unsigned statements to the contract to consume it via `acceptX` functions. Is is\n/// also used to verify the agent-signed statements and initiate the agent slashing, should the statement be invalid.\n/// `StatementInbox` is responsible for the following:\n/// - Accepting State and Receipt Reports to initiate a dispute between Guard and Notary.\n/// - Storing all the Guard Reports with the Guard signature leading to a dispute.\n/// - Verifying State/State Reports referencing the local chain and slashing the signer if statement is invalid.\n/// - Verifying Receipt/Receipt Reports referencing the local chain and slashing the signer if statement is invalid.\nabstract contract StatementInbox is MessagingBase, StatementInboxEvents, IStatementInbox {\n using AttestationLib for bytes;\n using ReceiptLib for bytes;\n using StateLib for bytes;\n using SnapshotLib for bytes;\n\n struct StoredReport {\n uint256 sigIndex;\n bytes statementPayload;\n }\n\n // ══════════════════════════════════════════════════ STORAGE ══════════════════════════════════════════════════════\n\n address public agentManager;\n address public origin;\n address public destination;\n\n // TODO: optimize this\n bytes[] internal _storedSignatures;\n StoredReport[] internal _storedReports;\n\n /// @dev gap for upgrade safety\n uint256[45] private __GAP; // solhint-disable-line var-name-mixedcase\n\n // ════════════════════════════════════════════════ INITIALIZER ════════════════════════════════════════════════════\n\n /// @dev Initializes the contract:\n /// - Sets up `msg.sender` as the owner of the contract.\n /// - Sets up `agentManager`, `origin`, and `destination`.\n // solhint-disable-next-line func-name-mixedcase\n function __StatementInbox_init(address agentManager_, address origin_, address destination_)\n internal\n onlyInitializing\n {\n agentManager = agentManager_;\n origin = origin_;\n destination = destination_;\n __Ownable2Step_init();\n }\n\n // ══════════════════════════════════════════ SUBMIT AGENT STATEMENTS ══════════════════════════════════════════════\n\n /// @inheritdoc IStatementInbox\n // solhint-disable-next-line ordering\n function submitStateReportWithSnapshot(\n uint8 stateIndex,\n bytes memory srSignature,\n bytes memory snapPayload,\n bytes memory snapSignature\n ) external returns (bool wasAccepted) {\n // This will revert if payload is not a snapshot\n Snapshot snapshot = snapPayload.castToSnapshot();\n // This will revert if the snapshot signer is not a known Notary\n (AgentStatus memory notaryStatus,) =\n _verifySnapshot({snapshot: snapshot, snapSignature: snapSignature, verifyNotary: true});\n // Notary needs to be Active/Unstaking\n notaryStatus.verifyActiveUnstaking();\n // Check if Notary is active on this chain\n _verifyNotaryDomain(notaryStatus.domain);\n // This will revert if state index is out of range\n State state = snapshot.state(stateIndex);\n // This will revert if the report signer is not an known Guard\n (AgentStatus memory guardStatus,) = _verifyStateReport(state, srSignature);\n // Check that Guard is active\n guardStatus.verifyActive();\n _saveReport(state.unwrap().clone(), srSignature);\n // This will revert if either actor is already in dispute\n IAgentManager(agentManager).openDispute(guardStatus.index, notaryStatus.index);\n return true;\n }\n\n /// @inheritdoc IStatementInbox\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 // This will revert if payload is not a snapshot\n Snapshot snapshot = snapPayload.castToSnapshot();\n // This will revert if state index is out of range\n State state = snapshot.state(stateIndex);\n // This will revert if the report signer is not an known Guard\n (AgentStatus memory guardStatus,) = _verifyStateReport(state, srSignature);\n // Check that Guard is active\n guardStatus.verifyActive();\n // This will revert if payload is not an attestation\n Attestation att = attPayload.castToAttestation();\n // This will revert if signer is not an known Notary\n (AgentStatus memory notaryStatus,) = _verifyAttestation(att, attSignature);\n // Notary needs to be Active/Unstaking\n notaryStatus.verifyActiveUnstaking();\n // Check if Notary is active on this chain\n _verifyNotaryDomain(notaryStatus.domain);\n if (snapshot.calculateRoot() != att.snapRoot()) revert IncorrectSnapshotRoot();\n _saveReport(state.unwrap().clone(), srSignature);\n // This will revert if either actor is already in dispute\n IAgentManager(agentManager).openDispute(guardStatus.index, notaryStatus.index);\n return true;\n }\n\n /// @inheritdoc IStatementInbox\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 // This will revert if payload is not a state\n State state = statePayload.castToState();\n // This will revert if the report signer is not an known Guard\n (AgentStatus memory guardStatus,) = _verifyStateReport(state, srSignature);\n // Check that Guard is active\n guardStatus.verifyActive();\n // This will revert if payload is not an attestation\n Attestation att = attPayload.castToAttestation();\n // This will revert if signer is not a known Notary\n (AgentStatus memory notaryStatus,) = _verifyAttestation(att, attSignature);\n // Notary needs to be Active/Unstaking\n notaryStatus.verifyActiveUnstaking();\n // Check if Notary is active on this chain\n _verifyNotaryDomain(notaryStatus.domain);\n // This will revert if any of these is true:\n // - Attestation root is not equal to Merkle Root derived from State and Snapshot Proof.\n // - Snapshot Proof's first element does not match the State metadata.\n // - Snapshot Proof length exceeds Snapshot tree Height.\n // - State index is out of range.\n _verifySnapshotMerkle(att, stateIndex, state, snapProof);\n _saveReport(statePayload, srSignature);\n // This will revert if either actor is already in dispute\n IAgentManager(agentManager).openDispute(guardStatus.index, notaryStatus.index);\n return true;\n }\n\n // ══════════════════════════════════════════ VERIFY AGENT STATEMENTS ══════════════════════════════════════════════\n\n /// @inheritdoc IStatementInbox\n function verifyReceipt(bytes memory rcptPayload, bytes memory rcptSignature)\n external\n returns (bool isValidReceipt)\n {\n // This will revert if payload is not a receipt\n Receipt rcpt = rcptPayload.castToReceipt();\n // This will revert if the attestation signer is not a known Notary\n (AgentStatus memory status, address notary) = _verifyReceipt(rcpt, rcptSignature);\n // Notary needs to be Active/Unstaking\n status.verifyActiveUnstaking();\n isValidReceipt = IExecutionHub(destination).isValidReceipt(rcptPayload);\n if (!isValidReceipt) {\n emit InvalidReceipt(rcptPayload, rcptSignature);\n IAgentManager(agentManager).slashAgent(status.domain, notary, msg.sender);\n }\n }\n\n /// @inheritdoc IStatementInbox\n function verifyReceiptReport(bytes memory rcptPayload, bytes memory rrSignature)\n external\n returns (bool isValidReport)\n {\n // This will revert if payload is not a receipt\n Receipt rcpt = rcptPayload.castToReceipt();\n // This will revert if the report signer is not a known Guard\n (AgentStatus memory status, address guard) = _verifyReceiptReport(rcpt, rrSignature);\n // Guard needs to be Active/Unstaking\n status.verifyActiveUnstaking();\n // Report is valid IF AND ONLY IF the reported receipt in invalid\n isValidReport = !IExecutionHub(destination).isValidReceipt(rcptPayload);\n if (!isValidReport) {\n emit InvalidReceiptReport(rcptPayload, rrSignature);\n IAgentManager(agentManager).slashAgent(status.domain, guard, msg.sender);\n }\n }\n\n /// @inheritdoc IStatementInbox\n function verifyStateWithAttestation(\n uint8 stateIndex,\n bytes memory snapPayload,\n bytes memory attPayload,\n bytes memory attSignature\n ) external returns (bool isValidState) {\n // This will revert if payload is not an attestation\n Attestation att = attPayload.castToAttestation();\n // This will revert if the attestation signer is not a known Notary\n (AgentStatus memory status, address notary) = _verifyAttestation(att, attSignature);\n // Notary needs to be Active/Unstaking\n status.verifyActiveUnstaking();\n // This will revert if payload is not a snapshot\n Snapshot snapshot = snapPayload.castToSnapshot();\n if (snapshot.calculateRoot() != att.snapRoot()) revert IncorrectSnapshotRoot();\n // This will revert if state does not refer to this chain\n bytes memory statePayload = snapshot.state(stateIndex).unwrap().clone();\n isValidState = IStateHub(origin).isValidState(statePayload);\n if (!isValidState) {\n emit InvalidStateWithAttestation(stateIndex, statePayload, attPayload, attSignature);\n IAgentManager(agentManager).slashAgent(status.domain, notary, msg.sender);\n }\n }\n\n /// @inheritdoc IStatementInbox\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 // This will revert if payload is not an attestation\n Attestation att = attPayload.castToAttestation();\n // This will revert if the attestation signer is not a known Notary\n (AgentStatus memory status, address notary) = _verifyAttestation(att, attSignature);\n // Notary needs to be Active/Unstaking\n status.verifyActiveUnstaking();\n // This will revert if payload is not a state\n State state = statePayload.castToState();\n // This will revert if any of these is true:\n // - Attestation root is not equal to Merkle Root derived from State and Snapshot Proof.\n // - Snapshot Proof's first element does not match the State metadata.\n // - Snapshot Proof length exceeds Snapshot tree Height.\n // - State index is out of range.\n _verifySnapshotMerkle(att, stateIndex, state, snapProof);\n // This will revert if state does not refer to this chain\n isValidState = IStateHub(origin).isValidState(statePayload);\n if (!isValidState) {\n emit InvalidStateWithAttestation(stateIndex, statePayload, attPayload, attSignature);\n IAgentManager(agentManager).slashAgent(status.domain, notary, msg.sender);\n }\n }\n\n /// @inheritdoc IStatementInbox\n function verifyStateWithSnapshot(uint8 stateIndex, bytes memory snapPayload, bytes memory snapSignature)\n external\n returns (bool isValidState)\n {\n // This will revert if payload is not a snapshot\n Snapshot snapshot = snapPayload.castToSnapshot();\n // This will revert if the snapshot signer is not a known Guard/Notary\n (AgentStatus memory status, address agent) =\n _verifySnapshot({snapshot: snapshot, snapSignature: snapSignature, verifyNotary: false});\n // Agent needs to be Active/Unstaking\n status.verifyActiveUnstaking();\n // This will revert if state does not refer to this chain\n isValidState = IStateHub(origin).isValidState(snapshot.state(stateIndex).unwrap().clone());\n if (!isValidState) {\n emit InvalidStateWithSnapshot(stateIndex, snapPayload, snapSignature);\n IAgentManager(agentManager).slashAgent(status.domain, agent, msg.sender);\n }\n }\n\n /// @inheritdoc IStatementInbox\n function verifyStateReport(bytes memory statePayload, bytes memory srSignature)\n external\n returns (bool isValidReport)\n {\n // This will revert if payload is not a state\n State state = statePayload.castToState();\n // This will revert if the report signer is not a known Guard\n (AgentStatus memory status, address guard) = _verifyStateReport(state, srSignature);\n // Guard needs to be Active/Unstaking\n status.verifyActiveUnstaking();\n // Report is valid IF AND ONLY IF the reported state in invalid\n // This will revert if the reported state does not refer to this chain\n isValidReport = !IStateHub(origin).isValidState(statePayload);\n if (!isValidReport) {\n emit InvalidStateReport(statePayload, srSignature);\n IAgentManager(agentManager).slashAgent(status.domain, guard, msg.sender);\n }\n }\n\n // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════\n\n /// @inheritdoc IStatementInbox\n function getReportsAmount() external view returns (uint256) {\n return _storedReports.length;\n }\n\n /// @inheritdoc IStatementInbox\n function getGuardReport(uint256 index)\n external\n view\n returns (bytes memory statementPayload, bytes memory reportSignature)\n {\n if (index \u003e= _storedReports.length) revert IndexOutOfRange();\n StoredReport memory storedReport = _storedReports[index];\n statementPayload = storedReport.statementPayload;\n reportSignature = _storedSignatures[storedReport.sigIndex];\n }\n\n /// @inheritdoc IStatementInbox\n function getStoredSignature(uint256 index) external view returns (bytes memory) {\n return _storedSignatures[index];\n }\n\n // ══════════════════════════════════════════════ INTERNAL LOGIC ═══════════════════════════════════════════════════\n\n /// @dev Saves the statement reported by Guard as invalid and the Guard Report signature.\n function _saveReport(bytes memory statementPayload, bytes memory reportSignature) internal {\n uint256 sigIndex = _saveSignature(reportSignature);\n _storedReports.push(StoredReport(sigIndex, statementPayload));\n }\n\n /// @dev Saves the signature and returns its index.\n function _saveSignature(bytes memory signature) internal returns (uint256 sigIndex) {\n sigIndex = _storedSignatures.length;\n _storedSignatures.push(signature);\n }\n\n // ═══════════════════════════════════════════════ AGENT CHECKS ════════════════════════════════════════════════════\n\n /**\n * @dev Recovers a signer from a hashed message, and a EIP-191 signature for it.\n * Will revert, if the signer is not a known agent.\n * @dev Agent flag could be any of these: Active/Unstaking/Resting/Fraudulent/Slashed\n * Further checks need to be performed in a caller function.\n * @param hashedStatement Hash of the statement that was signed by an Agent\n * @param signature Agent signature for the hashed statement\n * @return status Struct representing agent status:\n * - flag Unknown/Active/Unstaking/Resting/Fraudulent/Slashed\n * - domain Domain where agent is/was active\n * - index Index of agent in the Agent Merkle Tree\n * @return agent Agent that signed the statement\n */\n function _recoverAgent(bytes32 hashedStatement, bytes memory signature)\n internal\n view\n returns (AgentStatus memory status, address agent)\n {\n bytes32 ethSignedMsg = ECDSA.toEthSignedMessageHash(hashedStatement);\n agent = ECDSA.recover(ethSignedMsg, signature);\n status = IAgentManager(agentManager).agentStatus(agent);\n // Discard signature of unknown agents.\n // Further flag checks are supposed to be performed in a caller function.\n status.verifyKnown();\n }\n\n /// @dev Verifies that Notary signature is active on local domain.\n function _verifyNotaryDomain(uint32 notaryDomain) internal view {\n // Notary needs to be from the local domain (if contract is not deployed on Synapse Chain).\n // Or Notary could be from any domain (if contract is deployed on Synapse Chain).\n if (notaryDomain != localDomain \u0026\u0026 localDomain != synapseDomain) revert IncorrectAgentDomain();\n }\n\n // ════════════════════════════════════════ ATTESTATION RELATED CHECKS ═════════════════════════════════════════════\n\n /**\n * @dev Internal function to verify the signed attestation payload.\n * Reverts if any of these is true:\n * - Attestation signer is not a known Notary.\n * @param att Typed memory view over attestation payload\n * @param attSignature Notary signature for the attestation\n * @return status Struct representing agent status, see {_recoverAgent}\n * @return notary Notary that signed the snapshot\n */\n function _verifyAttestation(Attestation att, bytes memory attSignature)\n internal\n view\n returns (AgentStatus memory status, address notary)\n {\n // This will revert if signer is not a known agent\n (status, notary) = _recoverAgent(att.hashValid(), attSignature);\n // Attestation signer needs to be a Notary, not a Guard\n if (status.domain == 0) revert AgentNotNotary();\n }\n\n /**\n * @dev Internal function to verify the signed attestation report payload.\n * Reverts if any of these is true:\n * - Report signer is not a known Guard.\n * @param att Typed memory view over attestation payload that Guard reports as invalid\n * @param arSignature Guard signature for the \"invalid attestation\" report\n * @return status Struct representing guard status, see {_recoverAgent}\n * @return guard Guard that signed the report\n */\n function _verifyAttestationReport(Attestation att, bytes memory arSignature)\n internal\n view\n returns (AgentStatus memory status, address guard)\n {\n // This will revert if signer is not a known agent\n (status, guard) = _recoverAgent(att.hashInvalid(), arSignature);\n // Report signer needs to be a Guard, not a Notary\n if (status.domain != 0) revert AgentNotGuard();\n }\n\n // ══════════════════════════════════════════ RECEIPT RELATED CHECKS ═══════════════════════════════════════════════\n\n /**\n * @dev Internal function to verify the signed receipt payload.\n * Reverts if any of these is true:\n * - Receipt signer is not a known Notary.\n * @param rcpt Typed memory view over receipt payload\n * @param rcptSignature Notary signature for the receipt\n * @return status Struct representing agent status, see {_recoverAgent}\n * @return notary Notary that signed the snapshot\n */\n function _verifyReceipt(Receipt rcpt, bytes memory rcptSignature)\n internal\n view\n returns (AgentStatus memory status, address notary)\n {\n // This will revert if signer is not a known agent\n (status, notary) = _recoverAgent(rcpt.hashValid(), rcptSignature);\n // Receipt signer needs to be a Notary, not a Guard\n if (status.domain == 0) revert AgentNotNotary();\n }\n\n /**\n * @dev Internal function to verify the signed receipt report payload.\n * Reverts if any of these is true:\n * - Report signer is not a known Guard.\n * @param rcpt Typed memory view over receipt payload that Guard reports as invalid\n * @param rrSignature Guard signature for the \"invalid receipt\" report\n * @return status Struct representing guard status, see {_recoverAgent}\n * @return guard Guard that signed the report\n */\n function _verifyReceiptReport(Receipt rcpt, bytes memory rrSignature)\n internal\n view\n returns (AgentStatus memory status, address guard)\n {\n // This will revert if signer is not a known agent\n (status, guard) = _recoverAgent(rcpt.hashInvalid(), rrSignature);\n // Report signer needs to be a Guard, not a Notary\n if (status.domain != 0) revert AgentNotGuard();\n }\n\n // ═══════════════════════════════════════ STATE/SNAPSHOT RELATED CHECKS ═══════════════════════════════════════════\n\n /**\n * @dev Internal function to verify the signed snapshot report payload.\n * Reverts if any of these is true:\n * - Report signer is not a known Guard.\n * @param state Typed memory view over state payload that Guard reports as invalid\n * @param srSignature Guard signature for the report\n * @return status Struct representing guard status, see {_recoverAgent}\n * @return guard Guard that signed the report\n */\n function _verifyStateReport(State state, bytes memory srSignature)\n internal\n view\n returns (AgentStatus memory status, address guard)\n {\n // This will revert if signer is not a known agent\n (status, guard) = _recoverAgent(state.hashInvalid(), srSignature);\n // Report signer needs to be a Guard, not a Notary\n if (status.domain != 0) revert AgentNotGuard();\n }\n\n /**\n * @dev Internal function to verify the signed snapshot payload.\n * Reverts if any of these is true:\n * - Snapshot signer is not a known Agent.\n * - Snapshot signer is not a Notary (if verifyNotary is true).\n * @param snapshot Typed memory view over snapshot payload\n * @param snapSignature Agent signature for the snapshot\n * @param verifyNotary If true, snapshot signer needs to be a Notary, not a Guard\n * @return status Struct representing agent status, see {_recoverAgent}\n * @return agent Agent that signed the snapshot\n */\n function _verifySnapshot(Snapshot snapshot, bytes memory snapSignature, bool verifyNotary)\n internal\n view\n returns (AgentStatus memory status, address agent)\n {\n // This will revert if signer is not a known agent\n (status, agent) = _recoverAgent(snapshot.hashValid(), snapSignature);\n // If requested, snapshot signer needs to be a Notary, not a Guard\n if (verifyNotary \u0026\u0026 status.domain == 0) revert AgentNotNotary();\n }\n\n // ═══════════════════════════════════════════ MERKLE RELATED CHECKS ═══════════════════════════════════════════════\n\n /**\n * @dev Internal function to verify that snapshot roots match.\n * Reverts if any of these is true:\n * - Attestation root is not equal to Merkle Root derived from State and Snapshot Proof.\n * - Snapshot Proof's first element does not match the State metadata.\n * - Snapshot Proof length exceeds Snapshot tree Height.\n * - State index is out of range.\n * @param att Typed memory view over Attestation\n * @param stateIndex Index of state in the snapshot\n * @param state Typed memory view over the provided state payload\n * @param snapProof Raw payload with snapshot data\n */\n function _verifySnapshotMerkle(Attestation att, uint8 stateIndex, State state, bytes32[] memory snapProof)\n internal\n pure\n {\n // Snapshot proof first element should match State metadata (aka \"right sub-leaf\")\n (, bytes32 rightSubLeaf) = state.subLeafs();\n if (snapProof[0] != rightSubLeaf) revert IncorrectSnapshotProof();\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(state.root(), state.origin(), snapProof, stateIndex);\n // Snapshot root should match the attestation root\n if (att.snapRoot() != snapshotRoot) revert IncorrectSnapshotRoot();\n }\n}\n\n// contracts/inbox/Inbox.sol\n\n// ══════════════════════════════ LIBRARY IMPORTS ══════════════════════════════\n\n// ═════════════════════════════ INTERNAL IMPORTS ══════════════════════════════\n\n/// @notice `Inbox` is the child of `StatementInbox` contract, that is used on Synapse Chain.\n/// In addition to the functionality of `StatementInbox`, it also:\n/// - Accepts Guard and Notary Snapshots and passes them to `Summit` contract.\n/// - Accepts Notary-signed Receipts and passes them to `Summit` contract.\n/// - Accepts Receipt Reports to initiate a dispute between Guard and Notary.\n/// - Verifies Attestations and Attestation Reports, and slashes the signer if they are invalid.\ncontract Inbox is StatementInbox, InboxEvents, InterfaceInbox {\n using AttestationLib for bytes;\n using ReceiptLib for bytes;\n using SnapshotLib for bytes;\n\n // Struct to get around stack too deep error. TODO: revisit this\n struct ReceiptInfo {\n AgentStatus rcptNotaryStatus;\n address notary;\n uint32 attNonce;\n AgentStatus attNotaryStatus;\n }\n\n // ══════════════════════════════════════════════════ STORAGE ══════════════════════════════════════════════════════\n\n // The address of the Summit contract.\n address public summit;\n\n // ═════════════════════════════════════════ CONSTRUCTOR \u0026 INITIALIZER ═════════════════════════════════════════════\n\n constructor(uint32 synapseDomain_) MessagingBase(\"0.0.3\", synapseDomain_) {\n if (localDomain != synapseDomain) revert MustBeSynapseDomain();\n }\n\n /// @notice Initializes `Inbox` contract:\n /// - Sets `msg.sender` as the owner of the contract\n /// - Sets `agentManager`, `origin`, `destination` and `summit` addresses\n function initialize(address agentManager_, address origin_, address destination_, address summit_)\n external\n initializer\n {\n __StatementInbox_init(agentManager_, origin_, destination_);\n summit = summit_;\n }\n\n // ══════════════════════════════════════════ SUBMIT AGENT STATEMENTS ══════════════════════════════════════════════\n\n /// @inheritdoc InterfaceInbox\n function submitSnapshot(bytes memory snapPayload, bytes memory snapSignature)\n external\n returns (bytes memory attPayload, bytes32 agentRoot_, uint256[] memory snapGas)\n {\n // This will revert if payload is not a snapshot\n Snapshot snapshot = snapPayload.castToSnapshot();\n // This will revert if the signer is not a known Guard/Notary\n (AgentStatus memory status, address agent) =\n _verifySnapshot({snapshot: snapshot, snapSignature: snapSignature, verifyNotary: false});\n // Check that Agent is active\n status.verifyActive();\n // Store Agent signature for the Snapshot\n uint256 sigIndex = _saveSignature(snapSignature);\n if (status.domain == 0) {\n // Guard that is in Dispute could still submit new snapshots, so we don't check that\n InterfaceSummit(summit).acceptGuardSnapshot({\n guardIndex: status.index,\n sigIndex: sigIndex,\n snapPayload: snapPayload\n });\n } else {\n // Get current agentRoot from AgentManager\n agentRoot_ = IAgentManager(agentManager).agentRoot();\n // This will revert if Notary is in Dispute\n attPayload = InterfaceSummit(summit).acceptNotarySnapshot({\n notaryIndex: status.index,\n sigIndex: sigIndex,\n agentRoot: agentRoot_,\n snapPayload: snapPayload\n });\n ChainGas[] memory snapGas_ = snapshot.snapGas();\n // Pass created attestation to Destination to enable executing messages coming to Synapse Chain\n InterfaceDestination(destination).acceptAttestation(\n status.index, type(uint256).max, attPayload, agentRoot_, snapGas_\n );\n // Use assembly to cast ChainGas[] to uint256[] without copying. Highest bits are left zeroed.\n // solhint-disable-next-line no-inline-assembly\n assembly {\n snapGas := snapGas_\n }\n }\n emit SnapshotAccepted(status.domain, agent, snapPayload, snapSignature);\n }\n\n /// @inheritdoc InterfaceInbox\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 // Struct to get around stack too deep error.\n ReceiptInfo memory info;\n // This will revert if payload is not a receipt\n Receipt rcpt = rcptPayload.castToReceipt();\n // This will revert if the receipt signer is not a known Notary\n (info.rcptNotaryStatus, info.notary) = _verifyReceipt(rcpt, rcptSignature);\n // Receipt Notary needs to be Active\n info.rcptNotaryStatus.verifyActive();\n info.attNonce = IExecutionHub(destination).getAttestationNonce(rcpt.snapshotRoot());\n if (info.attNonce == 0) revert IncorrectSnapshotRoot();\n // Attestation Notary domain needs to match the destination domain\n info.attNotaryStatus = IAgentManager(agentManager).agentStatus(rcpt.attNotary());\n if (info.attNotaryStatus.domain != rcpt.destination()) revert IncorrectAgentDomain();\n // Check that the correct tip values for the message were provided\n _verifyReceiptTips(rcpt.messageHash(), paddedTips, headerHash, bodyHash);\n // Store Notary signature for the Receipt\n uint256 sigIndex = _saveSignature(rcptSignature);\n // This will revert if Receipt Notary is in Dispute\n wasAccepted = InterfaceSummit(summit).acceptReceipt({\n rcptNotaryIndex: info.rcptNotaryStatus.index,\n attNotaryIndex: info.attNotaryStatus.index,\n sigIndex: sigIndex,\n attNonce: info.attNonce,\n paddedTips: paddedTips,\n rcptPayload: rcptPayload\n });\n if (wasAccepted) {\n emit ReceiptAccepted(info.rcptNotaryStatus.domain, info.notary, rcptPayload, rcptSignature);\n }\n }\n\n /// @inheritdoc InterfaceInbox\n function submitReceiptReport(bytes memory rcptPayload, bytes memory rcptSignature, bytes memory rrSignature)\n external\n returns (bool wasAccepted)\n {\n // This will revert if payload is not a receipt\n Receipt rcpt = rcptPayload.castToReceipt();\n // This will revert if the receipt signer is not a known Guard\n (AgentStatus memory guardStatus,) = _verifyReceiptReport(rcpt, rrSignature);\n // Guard needs to be Active\n guardStatus.verifyActive();\n // This will revert if report signer is not a known Notary\n (AgentStatus memory notaryStatus,) = _verifyReceipt(rcpt, rcptSignature);\n // Notary needs to be Active/Unstaking\n notaryStatus.verifyActiveUnstaking();\n _saveReport(rcptPayload, rrSignature);\n // This will revert if either actor is already in dispute\n IAgentManager(agentManager).openDispute(guardStatus.index, notaryStatus.index);\n return true;\n }\n\n /// @inheritdoc InterfaceInbox\n function passReceipt(uint32 attNotaryIndex, uint32 attNonce, uint256 paddedTips, bytes memory rcptPayload)\n external\n returns (bool wasAccepted)\n {\n // Only Destination can pass receipts\n if (msg.sender != destination) revert CallerNotDestination();\n return InterfaceSummit(summit).acceptReceipt({\n rcptNotaryIndex: attNotaryIndex,\n attNotaryIndex: attNotaryIndex,\n sigIndex: type(uint256).max,\n attNonce: attNonce,\n paddedTips: paddedTips,\n rcptPayload: rcptPayload\n });\n }\n\n // ══════════════════════════════════════════ VERIFY AGENT STATEMENTS ══════════════════════════════════════════════\n\n /// @inheritdoc InterfaceInbox\n function verifyAttestation(bytes memory attPayload, bytes memory attSignature)\n external\n returns (bool isValidAttestation)\n {\n // This will revert if payload is not an attestation\n Attestation att = attPayload.castToAttestation();\n // This will revert if the attestation signer is not a known Notary\n (AgentStatus memory status, address notary) = _verifyAttestation(att, attSignature);\n // Notary needs to be Active/Unstaking\n status.verifyActiveUnstaking();\n isValidAttestation = ISnapshotHub(summit).isValidAttestation(attPayload);\n if (!isValidAttestation) {\n emit InvalidAttestation(attPayload, attSignature);\n IAgentManager(agentManager).slashAgent(status.domain, notary, msg.sender);\n }\n }\n\n /// @inheritdoc InterfaceInbox\n function verifyAttestationReport(bytes memory attPayload, bytes memory arSignature)\n external\n returns (bool isValidReport)\n {\n // This will revert if payload is not an attestation\n Attestation att = attPayload.castToAttestation();\n // This will revert if the report signer is not a known Guard\n (AgentStatus memory status, address guard) = _verifyAttestationReport(att, arSignature);\n // Guard needs to be Active/Unstaking\n status.verifyActiveUnstaking();\n // Report is valid IF AND ONLY IF the reported attestation in invalid\n isValidReport = !ISnapshotHub(summit).isValidAttestation(attPayload);\n if (!isValidReport) {\n emit InvalidAttestationReport(attPayload, arSignature);\n IAgentManager(agentManager).slashAgent(status.domain, guard, msg.sender);\n }\n }\n\n // ══════════════════════════════════════════════ INTERNAL VIEWS ═══════════════════════════════════════════════════\n\n /// @dev Verifies that tips proof matches the message hash.\n function _verifyReceiptTips(bytes32 msgHash, uint256 paddedTips, bytes32 headerHash, bytes32 bodyHash)\n internal\n pure\n {\n Tips tips = TipsLib.wrapPadded(paddedTips);\n // full message leaf is (header, baseMessage), while base message leaf is (tips, remainingBody).\n if (MerkleMath.getParent(headerHash, MerkleMath.getParent(tips.leaf(), bodyHash)) != msgHash) {\n revert IncorrectTipsProof();\n }\n }\n}\n","language":"Solidity","languageVersion":"0.8.17","compilerVersion":"0.8.17","compilerOptions":"--combined-json bin,bin-runtime,srcmap,srcmap-runtime,abi,userdoc,devdoc,metadata,hashes --optimize --optimize-runs 10000 --allow-paths ., ./, ../","srcMap":"","srcMapRuntime":"","abiDefinition":[{"inputs":[],"name":"AgentNotActive","type":"error"},{"inputs":[],"name":"AgentNotActiveNorUnstaking","type":"error"},{"inputs":[],"name":"AgentNotGuard","type":"error"},{"inputs":[],"name":"AgentNotNotary","type":"error"},{"inputs":[],"name":"AgentUnknown","type":"error"},{"inputs":[],"name":"IncorrectAgentDomain","type":"error"},{"inputs":[],"name":"IncorrectSnapshotProof","type":"error"},{"inputs":[],"name":"IncorrectSnapshotRoot","type":"error"},{"inputs":[],"name":"IncorrectVersionLength","type":"error"},{"inputs":[],"name":"IndexOutOfRange","type":"error"},{"inputs":[],"name":"IndexedTooMuch","type":"error"},{"inputs":[],"name":"OccupiedMemory","type":"error"},{"inputs":[],"name":"PrecompileOutOfGas","type":"error"},{"inputs":[],"name":"TreeHeightTooLow","type":"error"},{"inputs":[],"name":"UnallocatedMemory","type":"error"},{"inputs":[],"name":"UnformattedAttestation","type":"error"},{"inputs":[],"name":"UnformattedReceipt","type":"error"},{"inputs":[],"name":"UnformattedSnapshot","type":"error"},{"inputs":[],"name":"UnformattedState","type":"error"},{"inputs":[],"name":"ViewOverrun","type":"error"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint32","name":"domain","type":"uint32"},{"indexed":false,"internalType":"address","name":"notary","type":"address"},{"indexed":false,"internalType":"bytes","name":"attPayload","type":"bytes"},{"indexed":false,"internalType":"bytes","name":"attSignature","type":"bytes"}],"name":"AttestationAccepted","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint8","name":"version","type":"uint8"}],"name":"Initialized","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"bytes","name":"rcptPayload","type":"bytes"},{"indexed":false,"internalType":"bytes","name":"rcptSignature","type":"bytes"}],"name":"InvalidReceipt","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"bytes","name":"rrPayload","type":"bytes"},{"indexed":false,"internalType":"bytes","name":"rrSignature","type":"bytes"}],"name":"InvalidReceiptReport","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"bytes","name":"srPayload","type":"bytes"},{"indexed":false,"internalType":"bytes","name":"srSignature","type":"bytes"}],"name":"InvalidStateReport","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint8","name":"stateIndex","type":"uint8"},{"indexed":false,"internalType":"bytes","name":"statePayload","type":"bytes"},{"indexed":false,"internalType":"bytes","name":"attPayload","type":"bytes"},{"indexed":false,"internalType":"bytes","name":"attSignature","type":"bytes"}],"name":"InvalidStateWithAttestation","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint8","name":"stateIndex","type":"uint8"},{"indexed":false,"internalType":"bytes","name":"snapPayload","type":"bytes"},{"indexed":false,"internalType":"bytes","name":"snapSignature","type":"bytes"}],"name":"InvalidStateWithSnapshot","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":[],"name":"destination","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"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":[],"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":"origin","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","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":"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":[],"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":[{"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"},{"inputs":[],"name":"version","outputs":[{"internalType":"string","name":"versionString","type":"string"}],"stateMutability":"view","type":"function"}],"userDoc":{"events":{"AttestationAccepted(uint32,address,bytes,bytes)":{"notice":"Emitted when a snapshot is accepted by the Destination contract."},"InvalidReceipt(bytes,bytes)":{"notice":"Emitted when a proof of invalid receipt statement is submitted."},"InvalidReceiptReport(bytes,bytes)":{"notice":"Emitted when a proof of invalid receipt report is submitted."},"InvalidStateReport(bytes,bytes)":{"notice":"Emitted when a proof of invalid state report is submitted."},"InvalidStateWithAttestation(uint8,bytes,bytes,bytes)":{"notice":"Emitted when a proof of invalid state in the signed attestation is submitted."},"InvalidStateWithSnapshot(uint8,bytes,bytes)":{"notice":"Emitted when a proof of invalid state in the signed snapshot is submitted."}},"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."},"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`."},"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."}},"notice":"`StatementInbox` is the entry point for all agent-signed statements. It verifies the agent signatures, and passes the unsigned statements to the contract to consume it via `acceptX` functions. Is is also used to verify the agent-signed statements and initiate the agent slashing, should the statement be invalid. `StatementInbox` is responsible for the following: - Accepting State and Receipt Reports to initiate a dispute between Guard and Notary. - Storing all the Guard Reports with the Guard signature leading to a dispute. - Verifying State/State Reports referencing the local chain and slashing the signer if statement is invalid. - Verifying Receipt/Receipt Reports referencing the local chain and slashing the signer if statement is invalid.","version":1},"developerDoc":{"kind":"dev","methods":{"acceptOwnership()":{"details":"The new owner accepts the ownership transfer."},"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"}},"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"},"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)"}},"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."},"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."}}},"stateVariables":{"__GAP":{"details":"gap for upgrade safety"}},"version":1},"metadata":"{\"compiler\":{\"version\":\"0.8.17+commit.8df45f5f\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[],\"name\":\"AgentNotActive\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"AgentNotActiveNorUnstaking\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"AgentNotGuard\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"AgentNotNotary\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"AgentUnknown\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"IncorrectAgentDomain\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"IncorrectSnapshotProof\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"IncorrectSnapshotRoot\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"IncorrectVersionLength\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"IndexOutOfRange\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"IndexedTooMuch\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OccupiedMemory\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"PrecompileOutOfGas\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"TreeHeightTooLow\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"UnallocatedMemory\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"UnformattedAttestation\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"UnformattedReceipt\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"UnformattedSnapshot\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"UnformattedState\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ViewOverrun\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint32\",\"name\":\"domain\",\"type\":\"uint32\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"notary\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"attPayload\",\"type\":\"bytes\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"attSignature\",\"type\":\"bytes\"}],\"name\":\"AttestationAccepted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint8\",\"name\":\"version\",\"type\":\"uint8\"}],\"name\":\"Initialized\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"rcptPayload\",\"type\":\"bytes\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"rcptSignature\",\"type\":\"bytes\"}],\"name\":\"InvalidReceipt\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"rrPayload\",\"type\":\"bytes\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"rrSignature\",\"type\":\"bytes\"}],\"name\":\"InvalidReceiptReport\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"srPayload\",\"type\":\"bytes\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"srSignature\",\"type\":\"bytes\"}],\"name\":\"InvalidStateReport\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint8\",\"name\":\"stateIndex\",\"type\":\"uint8\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"statePayload\",\"type\":\"bytes\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"attPayload\",\"type\":\"bytes\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"attSignature\",\"type\":\"bytes\"}],\"name\":\"InvalidStateWithAttestation\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint8\",\"name\":\"stateIndex\",\"type\":\"uint8\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"snapPayload\",\"type\":\"bytes\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"snapSignature\",\"type\":\"bytes\"}],\"name\":\"InvalidStateWithSnapshot\",\"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\":[],\"name\":\"destination\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"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\":[],\"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\":\"origin\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"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\":\"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\":[],\"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\":[{\"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\"},{\"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.\"},\"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\"}},\"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\"},\"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)\"}},\"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.\"},\"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.\"}}},\"stateVariables\":{\"__GAP\":{\"details\":\"gap for upgrade safety\"}},\"version\":1},\"userdoc\":{\"events\":{\"AttestationAccepted(uint32,address,bytes,bytes)\":{\"notice\":\"Emitted when a snapshot is accepted by the Destination contract.\"},\"InvalidReceipt(bytes,bytes)\":{\"notice\":\"Emitted when a proof of invalid receipt statement is submitted.\"},\"InvalidReceiptReport(bytes,bytes)\":{\"notice\":\"Emitted when a proof of invalid receipt report is submitted.\"},\"InvalidStateReport(bytes,bytes)\":{\"notice\":\"Emitted when a proof of invalid state report is submitted.\"},\"InvalidStateWithAttestation(uint8,bytes,bytes,bytes)\":{\"notice\":\"Emitted when a proof of invalid state in the signed attestation is submitted.\"},\"InvalidStateWithSnapshot(uint8,bytes,bytes)\":{\"notice\":\"Emitted when a proof of invalid state in the signed snapshot is submitted.\"}},\"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.\"},\"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`.\"},\"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.\"}},\"notice\":\"`StatementInbox` is the entry point for all agent-signed statements. It verifies the agent signatures, and passes the unsigned statements to the contract to consume it via `acceptX` functions. Is is also used to verify the agent-signed statements and initiate the agent slashing, should the statement be invalid. `StatementInbox` is responsible for the following: - Accepting State and Receipt Reports to initiate a dispute between Guard and Notary. - Storing all the Guard Reports with the Guard signature leading to a dispute. - Verifying State/State Reports referencing the local chain and slashing the signer if statement is invalid. - Verifying Receipt/Receipt Reports referencing the local chain and slashing the signer if statement is invalid.\",\"version\":1}},\"settings\":{\"compilationTarget\":{\"solidity/Inbox.sol\":\"StatementInbox\"},\"evmVersion\":\"london\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\"},\"optimizer\":{\"enabled\":true,\"runs\":10000},\"remappings\":[]},\"sources\":{\"solidity/Inbox.sol\":{\"keccak256\":\"0x9b516081a036814c0169e20e484d4a5499066b7a6f48fada952b5e844a1ca3e5\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://32bde393b3f24ef4307d9626d4143f337b3c0bd34e17bb969fd5a15221d96987\",\"dweb:/ipfs/QmTkt2XZRtgsbSpmsVQUM3c4ebETQoDVYbmEV9yheBghnr\"]}},\"version\":1}"},"hashes":{"acceptOwnership()":"79ba5097","agentManager()":"7622f78d","destination()":"b269681d","getGuardReport(uint256)":"c495912b","getReportsAmount()":"756ed01d","getStoredSignature(uint256)":"ddeffa66","localDomain()":"8d3638f4","multicall((bool,bytes)[])":"60fc8466","origin()":"938b5f32","owner()":"8da5cb5b","pendingOwner()":"e30c3978","renounceOwnership()":"715018a6","submitStateReportWithAttestation(uint8,bytes,bytes,bytes,bytes)":"243b9224","submitStateReportWithSnapshot(uint8,bytes,bytes,bytes)":"333138e2","submitStateReportWithSnapshotProof(uint8,bytes,bytes,bytes32[],bytes,bytes)":"be7e63da","synapseDomain()":"717b8638","transferOwnership(address)":"f2fde38b","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","version()":"54fd4d50"}},"solidity/Inbox.sol:StatementInboxEvents":{"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/InboxEvents.sol\n\nabstract contract InboxEvents {\n /**\n * @notice Emitted when a snapshot is accepted by the Summit contract.\n * @param domain Domain where the signed Agent is active (ZERO for Guards)\n * @param agent Agent who signed the snapshot\n * @param snapPayload Raw payload with snapshot data\n * @param snapSignature Agent signature for the snapshot\n */\n event SnapshotAccepted(uint32 indexed domain, address indexed agent, bytes snapPayload, bytes snapSignature);\n\n /**\n * @notice Emitted when a snapshot is accepted by the Summit contract.\n * @param domain Domain where the signed Notary is active\n * @param notary Notary who signed the attestation\n * @param rcptPayload Raw payload with receipt data\n * @param rcptSignature Notary signature for the receipt\n */\n event ReceiptAccepted(uint32 domain, address notary, bytes rcptPayload, bytes rcptSignature);\n\n /**\n * @notice Emitted when a proof of invalid attestation is submitted.\n * @param attPayload Raw payload with Attestation data\n * @param attSignature Notary signature for the attestation\n */\n event InvalidAttestation(bytes attPayload, bytes attSignature);\n\n /**\n * @notice Emitted when a proof of invalid attestation report is submitted.\n * @param arPayload Raw payload with report data\n * @param arSignature Guard signature for the report\n */\n event InvalidAttestationReport(bytes arPayload, bytes arSignature);\n}\n\n// contracts/events/StatementInboxEvents.sol\n\nabstract contract StatementInboxEvents {\n // ════════════════════════════════════════════ STATEMENT ACCEPTED ═════════════════════════════════════════════════\n\n /**\n * @notice Emitted when a snapshot is accepted by the Destination contract.\n * @param domain Domain where the signed Notary is active\n * @param notary Notary who signed the attestation\n * @param attPayload Raw payload with attestation data\n * @param attSignature Notary signature for the attestation\n */\n event AttestationAccepted(uint32 domain, address notary, bytes attPayload, bytes attSignature);\n\n // ═════════════════════════════════════════ INVALID STATEMENT PROVED ══════════════════════════════════════════════\n\n /**\n * @notice Emitted when a proof of invalid receipt statement is submitted.\n * @param rcptPayload Raw payload with the receipt statement\n * @param rcptSignature Notary signature for the receipt statement\n */\n event InvalidReceipt(bytes rcptPayload, bytes rcptSignature);\n\n /**\n * @notice Emitted when a proof of invalid receipt report is submitted.\n * @param rrPayload Raw payload with report data\n * @param rrSignature Guard signature for the report\n */\n event InvalidReceiptReport(bytes rrPayload, bytes rrSignature);\n\n /**\n * @notice Emitted when a proof of invalid state in the signed attestation is submitted.\n * @param stateIndex Index of invalid state in the snapshot\n * @param statePayload Raw payload with state data\n * @param attPayload Raw payload with Attestation data for snapshot\n * @param attSignature Notary signature for the attestation\n */\n event InvalidStateWithAttestation(uint8 stateIndex, bytes statePayload, bytes attPayload, bytes attSignature);\n\n /**\n * @notice Emitted when a proof of invalid state in the signed snapshot is submitted.\n * @param stateIndex Index of invalid state in the snapshot\n * @param snapPayload Raw payload with snapshot data\n * @param snapSignature Agent signature for the snapshot\n */\n event InvalidStateWithSnapshot(uint8 stateIndex, bytes snapPayload, bytes snapSignature);\n\n /**\n * @notice Emitted when a proof of invalid state report is submitted.\n * @param srPayload Raw payload with report data\n * @param srSignature Guard signature for the report\n */\n event InvalidStateReport(bytes srPayload, bytes srSignature);\n}\n\n// contracts/interfaces/ISnapshotHub.sol\n\ninterface ISnapshotHub {\n /**\n * @notice Check that a given attestation is valid: matches the historical attestation\n * derived from an accepted Notary snapshot.\n * @dev Will revert if any of these is true:\n * - Attestation payload is not properly formatted.\n * @param attPayload Raw payload with attestation data\n * @return isValid Whether the provided attestation is valid\n */\n function isValidAttestation(bytes memory attPayload) external view returns (bool isValid);\n\n /**\n * @notice Returns saved attestation with the given nonce.\n * @dev Reverts if attestation with given nonce hasn't been created yet.\n * @param attNonce Nonce for the attestation\n * @return attPayload Raw payload with formatted Attestation data\n * @return agentRoot Agent root hash used for the attestation\n * @return snapGas Snapshot gas data used for the attestation\n */\n function getAttestation(uint32 attNonce)\n external\n view\n returns (bytes memory attPayload, bytes32 agentRoot, uint256[] memory snapGas);\n\n /**\n * @notice Returns the state with the highest known nonce submitted by a given Agent.\n * @param origin Domain of origin chain\n * @param agent Agent address\n * @return statePayload Raw payload with agent's latest state for origin\n */\n function getLatestAgentState(uint32 origin, address agent) external view returns (bytes memory statePayload);\n\n /**\n * @notice Returns latest saved attestation for a Notary.\n * @param notary Notary address\n * @return attPayload Raw payload with formatted Attestation data\n * @return agentRoot Agent root hash used for the attestation\n * @return snapGas Snapshot gas data used for the attestation\n */\n function getLatestNotaryAttestation(address notary)\n external\n view\n returns (bytes memory attPayload, bytes32 agentRoot, uint256[] memory snapGas);\n\n /**\n * @notice Returns Guard snapshot from the list of all accepted Guard snapshots.\n * @dev Reverts if snapshot with given index hasn't been accepted yet.\n * @param index Snapshot index in the list of all Guard snapshots\n * @return snapPayload Raw payload with Guard snapshot\n * @return snapSignature Raw payload with Guard signature for snapshot\n */\n function getGuardSnapshot(uint256 index)\n external\n view\n returns (bytes memory snapPayload, bytes memory snapSignature);\n\n /**\n * @notice Returns Notary snapshot from the list of all accepted Guard snapshots.\n * @dev Reverts if snapshot with given index hasn't been accepted yet.\n * @param index Snapshot index in the list of all Notary snapshots\n * @return snapPayload Raw payload with Notary snapshot\n * @return snapSignature Raw payload with Notary signature for snapshot\n */\n function getNotarySnapshot(uint256 index)\n external\n view\n returns (bytes memory snapPayload, bytes memory snapSignature);\n\n /**\n * @notice Returns Notary snapshot that was used for creating a given attestation.\n * @dev Reverts if any of these is true:\n * - Attestation payload is not properly formatted.\n * - Attestation is invalid (doesn't have a matching Notary snapshot).\n * @param attPayload Raw payload with attestation data\n * @return snapPayload Raw payload with Notary snapshot\n * @return snapSignature Raw payload with Notary signature for snapshot\n */\n function getNotarySnapshot(bytes memory attPayload)\n external\n view\n returns (bytes memory snapPayload, bytes memory snapSignature);\n\n /**\n * @notice Returns proof of inclusion of (root, origin) fields of a given snapshot's state\n * into the Snapshot Merkle Tree for a given attestation.\n * @dev Reverts if any of these is true:\n * - Attestation with given nonce hasn't been created yet.\n * - State index is out of range of snapshot list.\n * @param attNonce Nonce for the attestation\n * @param stateIndex Index of state in the attestation's snapshot\n * @return snapProof The snapshot proof\n */\n function getSnapshotProof(uint32 attNonce, uint8 stateIndex) external view returns (bytes32[] memory snapProof);\n}\n\n// contracts/interfaces/IStateHub.sol\n\ninterface IStateHub {\n /**\n * @notice Check that a given state is valid: matches the historical state of Origin contract.\n * Note: any Agent including an invalid state in their snapshot will be slashed\n * upon providing the snapshot and agent signature for it to Origin contract.\n * @dev Will revert if any of these is true:\n * - State payload is not properly formatted.\n * @param statePayload Raw payload with state data\n * @return isValid Whether the provided state is valid\n */\n function isValidState(bytes memory statePayload) external view returns (bool isValid);\n\n /**\n * @notice Returns the amount of saved states so far.\n * @dev This includes the initial state of \"empty Origin Merkle Tree\".\n */\n function statesAmount() external view returns (uint256);\n\n /**\n * @notice Suggest the data (state after latest sent message) to sign for an Agent.\n * Note: signing the suggested state data will will never lead to slashing of the actor,\n * assuming they have confirmed that the block, which number is included in the data,\n * is not subject to reorganization (which is different for every observed chain).\n * @return statePayload Raw payload with the latest state data\n */\n function suggestLatestState() external view returns (bytes memory statePayload);\n\n /**\n * @notice Given the historical nonce, suggest the state data to sign for an Agent.\n * Note: signing the suggested state data will will never lead to slashing of the actor,\n * assuming they have confirmed that the block, which number is included in the data,\n * is not subject to reorganization (which is different for every observed chain).\n * @param nonce Historical nonce to form a state\n * @return statePayload Raw payload with historical state data\n */\n function suggestState(uint32 nonce) external view returns (bytes memory statePayload);\n}\n\n// contracts/interfaces/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/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// node_modules/@openzeppelin/contracts/utils/math/Math.sol\n\n// OpenZeppelin Contracts (last updated v4.9.0) (utils/math/Math.sol)\n\n/**\n * @dev Standard math utilities missing in the Solidity language.\n */\nlibrary Math {\n enum Rounding {\n Down, // Toward negative infinity\n Up, // Toward infinity\n Zero // Toward zero\n }\n\n /**\n * @dev Returns the largest of two numbers.\n */\n function max(uint256 a, uint256 b) internal pure returns (uint256) {\n return a \u003e b ? a : b;\n }\n\n /**\n * @dev Returns the smallest of two numbers.\n */\n function min(uint256 a, uint256 b) internal pure returns (uint256) {\n return a \u003c b ? a : b;\n }\n\n /**\n * @dev Returns the average of two numbers. The result is rounded towards\n * zero.\n */\n function average(uint256 a, uint256 b) internal pure returns (uint256) {\n // (a + b) / 2 can overflow.\n return (a \u0026 b) + (a ^ b) / 2;\n }\n\n /**\n * @dev Returns the ceiling of the division of two numbers.\n *\n * This differs from standard division with `/` in that it rounds up instead\n * of rounding down.\n */\n function ceilDiv(uint256 a, uint256 b) internal pure returns (uint256) {\n // (a + b - 1) / b can overflow on addition, so we distribute.\n return a == 0 ? 0 : (a - 1) / b + 1;\n }\n\n /**\n * @notice Calculates floor(x * y / denominator) with full precision. Throws if result overflows a uint256 or denominator == 0\n * @dev Original credit to Remco Bloemen under MIT license (https://xn--2-umb.com/21/muldiv)\n * with further edits by Uniswap Labs also under MIT license.\n */\n function mulDiv(uint256 x, uint256 y, uint256 denominator) internal pure returns (uint256 result) {\n unchecked {\n // 512-bit multiply [prod1 prod0] = x * y. Compute the product mod 2^256 and mod 2^256 - 1, then use\n // use the Chinese Remainder Theorem to reconstruct the 512 bit result. The result is stored in two 256\n // variables such that product = prod1 * 2^256 + prod0.\n uint256 prod0; // Least significant 256 bits of the product\n uint256 prod1; // Most significant 256 bits of the product\n assembly {\n let mm := mulmod(x, y, not(0))\n prod0 := mul(x, y)\n prod1 := sub(sub(mm, prod0), lt(mm, prod0))\n }\n\n // Handle non-overflow cases, 256 by 256 division.\n if (prod1 == 0) {\n // Solidity will revert if denominator == 0, unlike the div opcode on its own.\n // The surrounding unchecked block does not change this fact.\n // See https://docs.soliditylang.org/en/latest/control-structures.html#checked-or-unchecked-arithmetic.\n return prod0 / denominator;\n }\n\n // Make sure the result is less than 2^256. Also prevents denominator == 0.\n require(denominator \u003e prod1, \"Math: mulDiv overflow\");\n\n ///////////////////////////////////////////////\n // 512 by 256 division.\n ///////////////////////////////////////////////\n\n // Make division exact by subtracting the remainder from [prod1 prod0].\n uint256 remainder;\n assembly {\n // Compute remainder using mulmod.\n remainder := mulmod(x, y, denominator)\n\n // Subtract 256 bit number from 512 bit number.\n prod1 := sub(prod1, gt(remainder, prod0))\n prod0 := sub(prod0, remainder)\n }\n\n // Factor powers of two out of denominator and compute largest power of two divisor of denominator. Always \u003e= 1.\n // See https://cs.stackexchange.com/q/138556/92363.\n\n // Does not overflow because the denominator cannot be zero at this stage in the function.\n uint256 twos = denominator \u0026 (~denominator + 1);\n assembly {\n // Divide denominator by twos.\n denominator := div(denominator, twos)\n\n // Divide [prod1 prod0] by twos.\n prod0 := div(prod0, twos)\n\n // Flip twos such that it is 2^256 / twos. If twos is zero, then it becomes one.\n twos := add(div(sub(0, twos), twos), 1)\n }\n\n // Shift in bits from prod1 into prod0.\n prod0 |= prod1 * twos;\n\n // Invert denominator mod 2^256. Now that denominator is an odd number, it has an inverse modulo 2^256 such\n // that denominator * inv = 1 mod 2^256. Compute the inverse by starting with a seed that is correct for\n // four bits. That is, denominator * inv = 1 mod 2^4.\n uint256 inverse = (3 * denominator) ^ 2;\n\n // Use the Newton-Raphson iteration to improve the precision. Thanks to Hensel's lifting lemma, this also works\n // in modular arithmetic, doubling the correct bits in each step.\n inverse *= 2 - denominator * inverse; // inverse mod 2^8\n inverse *= 2 - denominator * inverse; // inverse mod 2^16\n inverse *= 2 - denominator * inverse; // inverse mod 2^32\n inverse *= 2 - denominator * inverse; // inverse mod 2^64\n inverse *= 2 - denominator * inverse; // inverse mod 2^128\n inverse *= 2 - denominator * inverse; // inverse mod 2^256\n\n // Because the division is now exact we can divide by multiplying with the modular inverse of denominator.\n // This will give us the correct result modulo 2^256. Since the preconditions guarantee that the outcome is\n // less than 2^256, this is the final result. We don't need to compute the high bits of the result and prod1\n // is no longer required.\n result = prod0 * inverse;\n return result;\n }\n }\n\n /**\n * @notice Calculates x * y / denominator with full precision, following the selected rounding direction.\n */\n function mulDiv(uint256 x, uint256 y, uint256 denominator, Rounding rounding) internal pure returns (uint256) {\n uint256 result = mulDiv(x, y, denominator);\n if (rounding == Rounding.Up \u0026\u0026 mulmod(x, y, denominator) \u003e 0) {\n result += 1;\n }\n return result;\n }\n\n /**\n * @dev Returns the square root of a number. If the number is not a perfect square, the value is rounded down.\n *\n * Inspired by Henry S. Warren, Jr.'s \"Hacker's Delight\" (Chapter 11).\n */\n function sqrt(uint256 a) internal pure returns (uint256) {\n if (a == 0) {\n return 0;\n }\n\n // For our first guess, we get the biggest power of 2 which is smaller than the square root of the target.\n //\n // We know that the \"msb\" (most significant bit) of our target number `a` is a power of 2 such that we have\n // `msb(a) \u003c= a \u003c 2*msb(a)`. This value can be written `msb(a)=2**k` with `k=log2(a)`.\n //\n // This can be rewritten `2**log2(a) \u003c= a \u003c 2**(log2(a) + 1)`\n // → `sqrt(2**k) \u003c= sqrt(a) \u003c sqrt(2**(k+1))`\n // → `2**(k/2) \u003c= sqrt(a) \u003c 2**((k+1)/2) \u003c= 2**(k/2 + 1)`\n //\n // Consequently, `2**(log2(a) / 2)` is a good first approximation of `sqrt(a)` with at least 1 correct bit.\n uint256 result = 1 \u003c\u003c (log2(a) \u003e\u003e 1);\n\n // At this point `result` is an estimation with one bit of precision. We know the true value is a uint128,\n // since it is the square root of a uint256. Newton's method converges quadratically (precision doubles at\n // every iteration). We thus need at most 7 iteration to turn our partial result with one bit of precision\n // into the expected uint128 result.\n unchecked {\n result = (result + a / result) \u003e\u003e 1;\n result = (result + a / result) \u003e\u003e 1;\n result = (result + a / result) \u003e\u003e 1;\n result = (result + a / result) \u003e\u003e 1;\n result = (result + a / result) \u003e\u003e 1;\n result = (result + a / result) \u003e\u003e 1;\n result = (result + a / result) \u003e\u003e 1;\n return min(result, a / result);\n }\n }\n\n /**\n * @notice Calculates sqrt(a), following the selected rounding direction.\n */\n function sqrt(uint256 a, Rounding rounding) internal pure returns (uint256) {\n unchecked {\n uint256 result = sqrt(a);\n return result + (rounding == Rounding.Up \u0026\u0026 result * result \u003c a ? 1 : 0);\n }\n }\n\n /**\n * @dev Return the log in base 2, rounded down, of a positive value.\n * Returns 0 if given 0.\n */\n function log2(uint256 value) internal pure returns (uint256) {\n uint256 result = 0;\n unchecked {\n if (value \u003e\u003e 128 \u003e 0) {\n value \u003e\u003e= 128;\n result += 128;\n }\n if (value \u003e\u003e 64 \u003e 0) {\n value \u003e\u003e= 64;\n result += 64;\n }\n if (value \u003e\u003e 32 \u003e 0) {\n value \u003e\u003e= 32;\n result += 32;\n }\n if (value \u003e\u003e 16 \u003e 0) {\n value \u003e\u003e= 16;\n result += 16;\n }\n if (value \u003e\u003e 8 \u003e 0) {\n value \u003e\u003e= 8;\n result += 8;\n }\n if (value \u003e\u003e 4 \u003e 0) {\n value \u003e\u003e= 4;\n result += 4;\n }\n if (value \u003e\u003e 2 \u003e 0) {\n value \u003e\u003e= 2;\n result += 2;\n }\n if (value \u003e\u003e 1 \u003e 0) {\n result += 1;\n }\n }\n return result;\n }\n\n /**\n * @dev Return the log in base 2, following the selected rounding direction, of a positive value.\n * Returns 0 if given 0.\n */\n function log2(uint256 value, Rounding rounding) internal pure returns (uint256) {\n unchecked {\n uint256 result = log2(value);\n return result + (rounding == Rounding.Up \u0026\u0026 1 \u003c\u003c result \u003c value ? 1 : 0);\n }\n }\n\n /**\n * @dev Return the log in base 10, rounded down, of a positive value.\n * Returns 0 if given 0.\n */\n function log10(uint256 value) internal pure returns (uint256) {\n uint256 result = 0;\n unchecked {\n if (value \u003e= 10 ** 64) {\n value /= 10 ** 64;\n result += 64;\n }\n if (value \u003e= 10 ** 32) {\n value /= 10 ** 32;\n result += 32;\n }\n if (value \u003e= 10 ** 16) {\n value /= 10 ** 16;\n result += 16;\n }\n if (value \u003e= 10 ** 8) {\n value /= 10 ** 8;\n result += 8;\n }\n if (value \u003e= 10 ** 4) {\n value /= 10 ** 4;\n result += 4;\n }\n if (value \u003e= 10 ** 2) {\n value /= 10 ** 2;\n result += 2;\n }\n if (value \u003e= 10 ** 1) {\n result += 1;\n }\n }\n return result;\n }\n\n /**\n * @dev Return the log in base 10, following the selected rounding direction, of a positive value.\n * Returns 0 if given 0.\n */\n function log10(uint256 value, Rounding rounding) internal pure returns (uint256) {\n unchecked {\n uint256 result = log10(value);\n return result + (rounding == Rounding.Up \u0026\u0026 10 ** result \u003c value ? 1 : 0);\n }\n }\n\n /**\n * @dev Return the log in base 256, rounded down, of a positive value.\n * Returns 0 if given 0.\n *\n * Adding one to the result gives the number of pairs of hex symbols needed to represent `value` as a hex string.\n */\n function log256(uint256 value) internal pure returns (uint256) {\n uint256 result = 0;\n unchecked {\n if (value \u003e\u003e 128 \u003e 0) {\n value \u003e\u003e= 128;\n result += 16;\n }\n if (value \u003e\u003e 64 \u003e 0) {\n value \u003e\u003e= 64;\n result += 8;\n }\n if (value \u003e\u003e 32 \u003e 0) {\n value \u003e\u003e= 32;\n result += 4;\n }\n if (value \u003e\u003e 16 \u003e 0) {\n value \u003e\u003e= 16;\n result += 2;\n }\n if (value \u003e\u003e 8 \u003e 0) {\n result += 1;\n }\n }\n return result;\n }\n\n /**\n * @dev Return the log in base 256, following the selected rounding direction, of a positive value.\n * Returns 0 if given 0.\n */\n function log256(uint256 value, Rounding rounding) internal pure returns (uint256) {\n unchecked {\n uint256 result = log256(value);\n return result + (rounding == Rounding.Up \u0026\u0026 1 \u003c\u003c (result \u003c\u003c 3) \u003c value ? 1 : 0);\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/utils/math/SignedMath.sol\n\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/math/SignedMath.sol)\n\n/**\n * @dev Standard signed math utilities missing in the Solidity language.\n */\nlibrary SignedMath {\n /**\n * @dev Returns the largest of two signed numbers.\n */\n function max(int256 a, int256 b) internal pure returns (int256) {\n return a \u003e b ? a : b;\n }\n\n /**\n * @dev Returns the smallest of two signed numbers.\n */\n function min(int256 a, int256 b) internal pure returns (int256) {\n return a \u003c b ? a : b;\n }\n\n /**\n * @dev Returns the average of two signed numbers without overflow.\n * The result is rounded towards zero.\n */\n function average(int256 a, int256 b) internal pure returns (int256) {\n // Formula from the book \"Hacker's Delight\"\n int256 x = (a \u0026 b) + ((a ^ b) \u003e\u003e 1);\n return x + (int256(uint256(x) \u003e\u003e 255) \u0026 (a ^ b));\n }\n\n /**\n * @dev Returns the absolute unsigned value of a signed value.\n */\n function abs(int256 n) internal pure returns (uint256) {\n unchecked {\n // must be unchecked in order to support `n = type(int256).min`\n return uint256(n \u003e= 0 ? n : -n);\n }\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// 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/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/InterfaceSummit.sol\n\ninterface InterfaceSummit {\n // ══════════════════════════════════════════ ACCEPT AGENT STATEMENTS ══════════════════════════════════════════════\n\n /**\n * @notice Accepts a receipt, which local `AgentManager` verified to have been signed by an active Notary.\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 * - Notary who signed the receipt is referenced as the \"Receipt Notary\".\n * - Notary who signed the attestation on destination chain is referenced as the \"Attestation Notary\".\n * \u003e Will revert if any of these is true:\n * \u003e - Called by anyone other than local `AgentManager`.\n * \u003e - Receipt body payload is not properly formatted.\n * \u003e - Receipt signer is in Dispute.\n * \u003e - Receipt's snapshot root is unknown.\n * @param rcptNotaryIndex Index of Receipt Notary in Agent Merkle Tree\n * @param attNotaryIndex Index of Attestation Notary in Agent Merkle Tree\n * @param sigIndex Index of stored Notary signature\n * @param attNonce Nonce of the attestation used for proving the executed message\n * @param paddedTips Padded encoded paid tips information\n * @param rcptPayload Raw payload with message execution receipt\n * @return wasAccepted Whether the receipt was accepted\n */\n function acceptReceipt(\n uint32 rcptNotaryIndex,\n uint32 attNotaryIndex,\n uint256 sigIndex,\n uint32 attNonce,\n uint256 paddedTips,\n bytes memory rcptPayload\n ) external returns (bool wasAccepted);\n\n /**\n * @notice Accepts a snapshot, which local `AgentManager` verified to have been signed by an active Guard.\n * \u003e Snapshot is a list of states for a set of Origin contracts residing on any of the chains.\n * All the states in the Guard-signed snapshot become available for Notary signing.\n * \u003e Will revert if any of these is true:\n * \u003e - Called by anyone other than local `AgentManager`.\n * \u003e - Snapshot payload is not properly formatted.\n * \u003e - Snapshot contains a state older then the Guard has previously submitted.\n * @param guardIndex Index of Guard in Agent Merkle Tree\n * @param sigIndex Index of stored Agent signature\n * @param snapPayload Raw payload with snapshot data\n */\n function acceptGuardSnapshot(uint32 guardIndex, uint256 sigIndex, bytes memory snapPayload) external;\n\n /**\n * @notice Accepts a snapshot, which local `AgentManager` verified to have been signed by an active Notary.\n * \u003e Snapshot is a list of states for a set of Origin contracts residing on any of the chains.\n * Snapshot Merkle Root is calculated and saved for valid snapshots, i.e.\n * snapshots which are only using states previously submitted by any of the Guards.\n * - Notary could use states singed by the same of different Guards 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 - Called by anyone other than local `AgentManager`.\n * \u003e - Snapshot payload is not properly formatted.\n * \u003e - Snapshot contains a state older then the Notary has previously submitted.\n * \u003e - Snapshot contains a state that no Guard has previously submitted.\n * @param notaryIndex Index of Notary in Agent Merkle Tree\n * @param sigIndex Index of stored Agent signature\n * @param agentRoot Current root of the Agent Merkle Tree\n * @param snapPayload Raw payload with snapshot data\n * @return attPayload Raw payload with data for attestation derived from Notary snapshot.\n */\n function acceptNotarySnapshot(uint32 notaryIndex, uint256 sigIndex, bytes32 agentRoot, bytes memory snapPayload)\n external\n returns (bytes memory attPayload);\n\n // ════════════════════════════════════════════════ TIPS LOGIC ═════════════════════════════════════════════════════\n\n /**\n * @notice Distributes tips using the first Receipt from the \"receipt quarantine queue\".\n * Possible scenarios:\n * - Receipt queue is empty =\u003e does nothing\n * - Receipt optimistic period is not over =\u003e does nothing\n * - Either of Notaries present in Receipt was slashed =\u003e receipt is deleted from the queue\n * - Either of Notaries present in Receipt in Dispute =\u003e receipt is moved to the end of queue\n * - None of the above =\u003e receipt tips are distributed\n * @dev Returned value makes it possible to do the following: `while (distributeTips()) {}`\n * @return queuePopped Whether the first element was popped from the queue\n */\n function distributeTips() external returns (bool queuePopped);\n\n /**\n * @notice Withdraws locked base message tips from requested domain Origin to the recipient.\n * This is done by a call to a local Origin contract, or by a manager message to the remote chain.\n * @dev This will revert, if the pending balance of origin tips (earned-claimed) is lower than requested.\n * @param origin Domain of chain to withdraw tips on\n * @param amount Amount of tips to withdraw\n */\n function withdrawTips(uint32 origin, uint256 amount) external;\n\n // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════\n\n /**\n * @notice Returns earned and claimed tips for the actor.\n * Note: Tips for address(0) belong to the Treasury.\n * @param actor Address of the actor\n * @param origin Domain where the tips were initially paid\n * @return earned Total amount of origin tips the actor has earned so far\n * @return claimed Total amount of origin tips the actor has claimed so far\n */\n function actorTips(address actor, uint32 origin) external view returns (uint128 earned, uint128 claimed);\n\n /**\n * @notice Returns the amount of receipts in the \"Receipt Quarantine Queue\".\n */\n function receiptQueueLength() external view returns (uint256);\n\n /**\n * @notice Returns the state with the highest known nonce\n * submitted by any of the currently active Guards.\n * @param origin Domain of origin chain\n * @return statePayload Raw payload with latest active Guard state for origin\n */\n function getLatestState(uint32 origin) external view returns (bytes memory statePayload);\n}\n\n// node_modules/@openzeppelin/contracts/utils/Strings.sol\n\n// OpenZeppelin Contracts (last updated v4.9.0) (utils/Strings.sol)\n\n/**\n * @dev String operations.\n */\nlibrary Strings {\n bytes16 private constant _SYMBOLS = \"0123456789abcdef\";\n uint8 private constant _ADDRESS_LENGTH = 20;\n\n /**\n * @dev Converts a `uint256` to its ASCII `string` decimal representation.\n */\n function toString(uint256 value) internal pure returns (string memory) {\n unchecked {\n uint256 length = Math.log10(value) + 1;\n string memory buffer = new string(length);\n uint256 ptr;\n /// @solidity memory-safe-assembly\n assembly {\n ptr := add(buffer, add(32, length))\n }\n while (true) {\n ptr--;\n /// @solidity memory-safe-assembly\n assembly {\n mstore8(ptr, byte(mod(value, 10), _SYMBOLS))\n }\n value /= 10;\n if (value == 0) break;\n }\n return buffer;\n }\n }\n\n /**\n * @dev Converts a `int256` to its ASCII `string` decimal representation.\n */\n function toString(int256 value) internal pure returns (string memory) {\n return string(abi.encodePacked(value \u003c 0 ? \"-\" : \"\", toString(SignedMath.abs(value))));\n }\n\n /**\n * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation.\n */\n function toHexString(uint256 value) internal pure returns (string memory) {\n unchecked {\n return toHexString(value, Math.log256(value) + 1);\n }\n }\n\n /**\n * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length.\n */\n function toHexString(uint256 value, uint256 length) internal pure returns (string memory) {\n bytes memory buffer = new bytes(2 * length + 2);\n buffer[0] = \"0\";\n buffer[1] = \"x\";\n for (uint256 i = 2 * length + 1; i \u003e 1; --i) {\n buffer[i] = _SYMBOLS[value \u0026 0xf];\n value \u003e\u003e= 4;\n }\n require(value == 0, \"Strings: hex length insufficient\");\n return string(buffer);\n }\n\n /**\n * @dev Converts an `address` with fixed length of 20 bytes to its not checksummed ASCII `string` hexadecimal representation.\n */\n function toHexString(address addr) internal pure returns (string memory) {\n return toHexString(uint256(uint160(addr)), _ADDRESS_LENGTH);\n }\n\n /**\n * @dev Returns true if the two strings are equal.\n */\n function equal(string memory a, string memory b) internal pure returns (bool) {\n return keccak256(bytes(a)) == keccak256(bytes(b));\n }\n}\n\n// node_modules/@openzeppelin/contracts-upgradeable/utils/ContextUpgradeable.sol\n\n// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)\n\n/**\n * @dev Provides information about the current execution context, including the\n * sender of the transaction and its data. While these are generally available\n * via msg.sender and msg.data, they should not be accessed in such a direct\n * manner, since when dealing with meta-transactions the account sending and\n * paying for execution may not be the actual sender (as far as an application\n * is concerned).\n *\n * This contract is only required for intermediate, library-like contracts.\n */\nabstract contract ContextUpgradeable is Initializable {\n function __Context_init() internal onlyInitializing {\n }\n\n function __Context_init_unchained() internal onlyInitializing {\n }\n function _msgSender() internal view virtual returns (address) {\n return msg.sender;\n }\n\n function _msgData() internal view virtual returns (bytes calldata) {\n return msg.data;\n }\n\n /**\n * @dev This empty reserved space is put in place to allow future versions to add new\n * variables without shifting down storage in the inheritance chain.\n * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\n */\n uint256[50] private __gap;\n}\n\n// contracts/libs/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/utils/cryptography/ECDSA.sol\n\n// OpenZeppelin Contracts (last updated v4.9.0) (utils/cryptography/ECDSA.sol)\n\n/**\n * @dev Elliptic Curve Digital Signature Algorithm (ECDSA) operations.\n *\n * These functions can be used to verify that a message was signed by the holder\n * of the private keys of a given address.\n */\nlibrary ECDSA {\n enum RecoverError {\n NoError,\n InvalidSignature,\n InvalidSignatureLength,\n InvalidSignatureS,\n InvalidSignatureV // Deprecated in v4.8\n }\n\n function _throwError(RecoverError error) private pure {\n if (error == RecoverError.NoError) {\n return; // no error: do nothing\n } else if (error == RecoverError.InvalidSignature) {\n revert(\"ECDSA: invalid signature\");\n } else if (error == RecoverError.InvalidSignatureLength) {\n revert(\"ECDSA: invalid signature length\");\n } else if (error == RecoverError.InvalidSignatureS) {\n revert(\"ECDSA: invalid signature 's' value\");\n }\n }\n\n /**\n * @dev Returns the address that signed a hashed message (`hash`) with\n * `signature` or error string. This address can then be used for verification purposes.\n *\n * The `ecrecover` EVM opcode allows for malleable (non-unique) signatures:\n * this function rejects them by requiring the `s` value to be in the lower\n * half order, and the `v` value to be either 27 or 28.\n *\n * IMPORTANT: `hash` _must_ be the result of a hash operation for the\n * verification to be secure: it is possible to craft signatures that\n * recover to arbitrary addresses for non-hashed data. A safe way to ensure\n * this is by receiving a hash of the original message (which may otherwise\n * be too long), and then calling {toEthSignedMessageHash} on it.\n *\n * Documentation for signature generation:\n * - with https://web3js.readthedocs.io/en/v1.3.4/web3-eth-accounts.html#sign[Web3.js]\n * - with https://docs.ethers.io/v5/api/signer/#Signer-signMessage[ethers]\n *\n * _Available since v4.3._\n */\n function tryRecover(bytes32 hash, bytes memory signature) internal pure returns (address, RecoverError) {\n if (signature.length == 65) {\n bytes32 r;\n bytes32 s;\n uint8 v;\n // ecrecover takes the signature parameters, and the only way to get them\n // currently is to use assembly.\n /// @solidity memory-safe-assembly\n assembly {\n r := mload(add(signature, 0x20))\n s := mload(add(signature, 0x40))\n v := byte(0, mload(add(signature, 0x60)))\n }\n return tryRecover(hash, v, r, s);\n } else {\n return (address(0), RecoverError.InvalidSignatureLength);\n }\n }\n\n /**\n * @dev Returns the address that signed a hashed message (`hash`) with\n * `signature`. This address can then be used for verification purposes.\n *\n * The `ecrecover` EVM opcode allows for malleable (non-unique) signatures:\n * this function rejects them by requiring the `s` value to be in the lower\n * half order, and the `v` value to be either 27 or 28.\n *\n * IMPORTANT: `hash` _must_ be the result of a hash operation for the\n * verification to be secure: it is possible to craft signatures that\n * recover to arbitrary addresses for non-hashed data. A safe way to ensure\n * this is by receiving a hash of the original message (which may otherwise\n * be too long), and then calling {toEthSignedMessageHash} on it.\n */\n function recover(bytes32 hash, bytes memory signature) internal pure returns (address) {\n (address recovered, RecoverError error) = tryRecover(hash, signature);\n _throwError(error);\n return recovered;\n }\n\n /**\n * @dev Overload of {ECDSA-tryRecover} that receives the `r` and `vs` short-signature fields separately.\n *\n * See https://eips.ethereum.org/EIPS/eip-2098[EIP-2098 short signatures]\n *\n * _Available since v4.3._\n */\n function tryRecover(bytes32 hash, bytes32 r, bytes32 vs) internal pure returns (address, RecoverError) {\n bytes32 s = vs \u0026 bytes32(0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff);\n uint8 v = uint8((uint256(vs) \u003e\u003e 255) + 27);\n return tryRecover(hash, v, r, s);\n }\n\n /**\n * @dev Overload of {ECDSA-recover} that receives the `r and `vs` short-signature fields separately.\n *\n * _Available since v4.2._\n */\n function recover(bytes32 hash, bytes32 r, bytes32 vs) internal pure returns (address) {\n (address recovered, RecoverError error) = tryRecover(hash, r, vs);\n _throwError(error);\n return recovered;\n }\n\n /**\n * @dev Overload of {ECDSA-tryRecover} that receives the `v`,\n * `r` and `s` signature fields separately.\n *\n * _Available since v4.3._\n */\n function tryRecover(bytes32 hash, uint8 v, bytes32 r, bytes32 s) internal pure returns (address, RecoverError) {\n // EIP-2 still allows signature malleability for ecrecover(). Remove this possibility and make the signature\n // unique. Appendix F in the Ethereum Yellow paper (https://ethereum.github.io/yellowpaper/paper.pdf), defines\n // the valid range for s in (301): 0 \u003c s \u003c secp256k1n ÷ 2 + 1, and for v in (302): v ∈ {27, 28}. Most\n // signatures from current libraries generate a unique signature with an s-value in the lower half order.\n //\n // If your library generates malleable signatures, such as s-values in the upper range, calculate a new s-value\n // with 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141 - s1 and flip v from 27 to 28 or\n // vice versa. If your library also generates signatures with 0/1 for v instead 27/28, add 27 to v to accept\n // these malleable signatures as well.\n if (uint256(s) \u003e 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0) {\n return (address(0), RecoverError.InvalidSignatureS);\n }\n\n // If the signature is valid (and not malleable), return the signer address\n address signer = ecrecover(hash, v, r, s);\n if (signer == address(0)) {\n return (address(0), RecoverError.InvalidSignature);\n }\n\n return (signer, RecoverError.NoError);\n }\n\n /**\n * @dev Overload of {ECDSA-recover} that receives the `v`,\n * `r` and `s` signature fields separately.\n */\n function recover(bytes32 hash, uint8 v, bytes32 r, bytes32 s) internal pure returns (address) {\n (address recovered, RecoverError error) = tryRecover(hash, v, r, s);\n _throwError(error);\n return recovered;\n }\n\n /**\n * @dev Returns an Ethereum Signed Message, created from a `hash`. This\n * produces hash corresponding to the one signed with the\n * https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`]\n * JSON-RPC method as part of EIP-191.\n *\n * See {recover}.\n */\n function toEthSignedMessageHash(bytes32 hash) internal pure returns (bytes32 message) {\n // 32 is the length in bytes of hash,\n // enforced by the type signature above\n /// @solidity memory-safe-assembly\n assembly {\n mstore(0x00, \"\\x19Ethereum Signed Message:\\n32\")\n mstore(0x1c, hash)\n message := keccak256(0x00, 0x3c)\n }\n }\n\n /**\n * @dev Returns an Ethereum Signed Message, created from `s`. This\n * produces hash corresponding to the one signed with the\n * https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`]\n * JSON-RPC method as part of EIP-191.\n *\n * See {recover}.\n */\n function toEthSignedMessageHash(bytes memory s) internal pure returns (bytes32) {\n return keccak256(abi.encodePacked(\"\\x19Ethereum Signed Message:\\n\", Strings.toString(s.length), s));\n }\n\n /**\n * @dev Returns an Ethereum Signed Typed Data, created from a\n * `domainSeparator` and a `structHash`. This produces hash corresponding\n * to the one signed with the\n * https://eips.ethereum.org/EIPS/eip-712[`eth_signTypedData`]\n * JSON-RPC method as part of EIP-712.\n *\n * See {recover}.\n */\n function toTypedDataHash(bytes32 domainSeparator, bytes32 structHash) internal pure returns (bytes32 data) {\n /// @solidity memory-safe-assembly\n assembly {\n let ptr := mload(0x40)\n mstore(ptr, \"\\x19\\x01\")\n mstore(add(ptr, 0x02), domainSeparator)\n mstore(add(ptr, 0x22), structHash)\n data := keccak256(ptr, 0x42)\n }\n }\n\n /**\n * @dev Returns an Ethereum Signed Data with intended validator, created from a\n * `validator` and `data` according to the version 0 of EIP-191.\n *\n * See {recover}.\n */\n function toDataWithIntendedValidatorHash(address validator, bytes memory data) internal pure returns (bytes32) {\n return keccak256(abi.encodePacked(\"\\x19\\x00\", validator, data));\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/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/inbox/StatementInbox.sol\n\n// ══════════════════════════════ LIBRARY IMPORTS ══════════════════════════════\n\n// ═════════════════════════════ INTERNAL IMPORTS ══════════════════════════════\n\n// ═════════════════════════════ EXTERNAL IMPORTS ══════════════════════════════\n\n/// @notice `StatementInbox` is the entry point for all agent-signed statements. It verifies the\n/// agent signatures, and passes the unsigned statements to the contract to consume it via `acceptX` functions. Is is\n/// also used to verify the agent-signed statements and initiate the agent slashing, should the statement be invalid.\n/// `StatementInbox` is responsible for the following:\n/// - Accepting State and Receipt Reports to initiate a dispute between Guard and Notary.\n/// - Storing all the Guard Reports with the Guard signature leading to a dispute.\n/// - Verifying State/State Reports referencing the local chain and slashing the signer if statement is invalid.\n/// - Verifying Receipt/Receipt Reports referencing the local chain and slashing the signer if statement is invalid.\nabstract contract StatementInbox is MessagingBase, StatementInboxEvents, IStatementInbox {\n using AttestationLib for bytes;\n using ReceiptLib for bytes;\n using StateLib for bytes;\n using SnapshotLib for bytes;\n\n struct StoredReport {\n uint256 sigIndex;\n bytes statementPayload;\n }\n\n // ══════════════════════════════════════════════════ STORAGE ══════════════════════════════════════════════════════\n\n address public agentManager;\n address public origin;\n address public destination;\n\n // TODO: optimize this\n bytes[] internal _storedSignatures;\n StoredReport[] internal _storedReports;\n\n /// @dev gap for upgrade safety\n uint256[45] private __GAP; // solhint-disable-line var-name-mixedcase\n\n // ════════════════════════════════════════════════ INITIALIZER ════════════════════════════════════════════════════\n\n /// @dev Initializes the contract:\n /// - Sets up `msg.sender` as the owner of the contract.\n /// - Sets up `agentManager`, `origin`, and `destination`.\n // solhint-disable-next-line func-name-mixedcase\n function __StatementInbox_init(address agentManager_, address origin_, address destination_)\n internal\n onlyInitializing\n {\n agentManager = agentManager_;\n origin = origin_;\n destination = destination_;\n __Ownable2Step_init();\n }\n\n // ══════════════════════════════════════════ SUBMIT AGENT STATEMENTS ══════════════════════════════════════════════\n\n /// @inheritdoc IStatementInbox\n // solhint-disable-next-line ordering\n function submitStateReportWithSnapshot(\n uint8 stateIndex,\n bytes memory srSignature,\n bytes memory snapPayload,\n bytes memory snapSignature\n ) external returns (bool wasAccepted) {\n // This will revert if payload is not a snapshot\n Snapshot snapshot = snapPayload.castToSnapshot();\n // This will revert if the snapshot signer is not a known Notary\n (AgentStatus memory notaryStatus,) =\n _verifySnapshot({snapshot: snapshot, snapSignature: snapSignature, verifyNotary: true});\n // Notary needs to be Active/Unstaking\n notaryStatus.verifyActiveUnstaking();\n // Check if Notary is active on this chain\n _verifyNotaryDomain(notaryStatus.domain);\n // This will revert if state index is out of range\n State state = snapshot.state(stateIndex);\n // This will revert if the report signer is not an known Guard\n (AgentStatus memory guardStatus,) = _verifyStateReport(state, srSignature);\n // Check that Guard is active\n guardStatus.verifyActive();\n _saveReport(state.unwrap().clone(), srSignature);\n // This will revert if either actor is already in dispute\n IAgentManager(agentManager).openDispute(guardStatus.index, notaryStatus.index);\n return true;\n }\n\n /// @inheritdoc IStatementInbox\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 // This will revert if payload is not a snapshot\n Snapshot snapshot = snapPayload.castToSnapshot();\n // This will revert if state index is out of range\n State state = snapshot.state(stateIndex);\n // This will revert if the report signer is not an known Guard\n (AgentStatus memory guardStatus,) = _verifyStateReport(state, srSignature);\n // Check that Guard is active\n guardStatus.verifyActive();\n // This will revert if payload is not an attestation\n Attestation att = attPayload.castToAttestation();\n // This will revert if signer is not an known Notary\n (AgentStatus memory notaryStatus,) = _verifyAttestation(att, attSignature);\n // Notary needs to be Active/Unstaking\n notaryStatus.verifyActiveUnstaking();\n // Check if Notary is active on this chain\n _verifyNotaryDomain(notaryStatus.domain);\n if (snapshot.calculateRoot() != att.snapRoot()) revert IncorrectSnapshotRoot();\n _saveReport(state.unwrap().clone(), srSignature);\n // This will revert if either actor is already in dispute\n IAgentManager(agentManager).openDispute(guardStatus.index, notaryStatus.index);\n return true;\n }\n\n /// @inheritdoc IStatementInbox\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 // This will revert if payload is not a state\n State state = statePayload.castToState();\n // This will revert if the report signer is not an known Guard\n (AgentStatus memory guardStatus,) = _verifyStateReport(state, srSignature);\n // Check that Guard is active\n guardStatus.verifyActive();\n // This will revert if payload is not an attestation\n Attestation att = attPayload.castToAttestation();\n // This will revert if signer is not a known Notary\n (AgentStatus memory notaryStatus,) = _verifyAttestation(att, attSignature);\n // Notary needs to be Active/Unstaking\n notaryStatus.verifyActiveUnstaking();\n // Check if Notary is active on this chain\n _verifyNotaryDomain(notaryStatus.domain);\n // This will revert if any of these is true:\n // - Attestation root is not equal to Merkle Root derived from State and Snapshot Proof.\n // - Snapshot Proof's first element does not match the State metadata.\n // - Snapshot Proof length exceeds Snapshot tree Height.\n // - State index is out of range.\n _verifySnapshotMerkle(att, stateIndex, state, snapProof);\n _saveReport(statePayload, srSignature);\n // This will revert if either actor is already in dispute\n IAgentManager(agentManager).openDispute(guardStatus.index, notaryStatus.index);\n return true;\n }\n\n // ══════════════════════════════════════════ VERIFY AGENT STATEMENTS ══════════════════════════════════════════════\n\n /// @inheritdoc IStatementInbox\n function verifyReceipt(bytes memory rcptPayload, bytes memory rcptSignature)\n external\n returns (bool isValidReceipt)\n {\n // This will revert if payload is not a receipt\n Receipt rcpt = rcptPayload.castToReceipt();\n // This will revert if the attestation signer is not a known Notary\n (AgentStatus memory status, address notary) = _verifyReceipt(rcpt, rcptSignature);\n // Notary needs to be Active/Unstaking\n status.verifyActiveUnstaking();\n isValidReceipt = IExecutionHub(destination).isValidReceipt(rcptPayload);\n if (!isValidReceipt) {\n emit InvalidReceipt(rcptPayload, rcptSignature);\n IAgentManager(agentManager).slashAgent(status.domain, notary, msg.sender);\n }\n }\n\n /// @inheritdoc IStatementInbox\n function verifyReceiptReport(bytes memory rcptPayload, bytes memory rrSignature)\n external\n returns (bool isValidReport)\n {\n // This will revert if payload is not a receipt\n Receipt rcpt = rcptPayload.castToReceipt();\n // This will revert if the report signer is not a known Guard\n (AgentStatus memory status, address guard) = _verifyReceiptReport(rcpt, rrSignature);\n // Guard needs to be Active/Unstaking\n status.verifyActiveUnstaking();\n // Report is valid IF AND ONLY IF the reported receipt in invalid\n isValidReport = !IExecutionHub(destination).isValidReceipt(rcptPayload);\n if (!isValidReport) {\n emit InvalidReceiptReport(rcptPayload, rrSignature);\n IAgentManager(agentManager).slashAgent(status.domain, guard, msg.sender);\n }\n }\n\n /// @inheritdoc IStatementInbox\n function verifyStateWithAttestation(\n uint8 stateIndex,\n bytes memory snapPayload,\n bytes memory attPayload,\n bytes memory attSignature\n ) external returns (bool isValidState) {\n // This will revert if payload is not an attestation\n Attestation att = attPayload.castToAttestation();\n // This will revert if the attestation signer is not a known Notary\n (AgentStatus memory status, address notary) = _verifyAttestation(att, attSignature);\n // Notary needs to be Active/Unstaking\n status.verifyActiveUnstaking();\n // This will revert if payload is not a snapshot\n Snapshot snapshot = snapPayload.castToSnapshot();\n if (snapshot.calculateRoot() != att.snapRoot()) revert IncorrectSnapshotRoot();\n // This will revert if state does not refer to this chain\n bytes memory statePayload = snapshot.state(stateIndex).unwrap().clone();\n isValidState = IStateHub(origin).isValidState(statePayload);\n if (!isValidState) {\n emit InvalidStateWithAttestation(stateIndex, statePayload, attPayload, attSignature);\n IAgentManager(agentManager).slashAgent(status.domain, notary, msg.sender);\n }\n }\n\n /// @inheritdoc IStatementInbox\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 // This will revert if payload is not an attestation\n Attestation att = attPayload.castToAttestation();\n // This will revert if the attestation signer is not a known Notary\n (AgentStatus memory status, address notary) = _verifyAttestation(att, attSignature);\n // Notary needs to be Active/Unstaking\n status.verifyActiveUnstaking();\n // This will revert if payload is not a state\n State state = statePayload.castToState();\n // This will revert if any of these is true:\n // - Attestation root is not equal to Merkle Root derived from State and Snapshot Proof.\n // - Snapshot Proof's first element does not match the State metadata.\n // - Snapshot Proof length exceeds Snapshot tree Height.\n // - State index is out of range.\n _verifySnapshotMerkle(att, stateIndex, state, snapProof);\n // This will revert if state does not refer to this chain\n isValidState = IStateHub(origin).isValidState(statePayload);\n if (!isValidState) {\n emit InvalidStateWithAttestation(stateIndex, statePayload, attPayload, attSignature);\n IAgentManager(agentManager).slashAgent(status.domain, notary, msg.sender);\n }\n }\n\n /// @inheritdoc IStatementInbox\n function verifyStateWithSnapshot(uint8 stateIndex, bytes memory snapPayload, bytes memory snapSignature)\n external\n returns (bool isValidState)\n {\n // This will revert if payload is not a snapshot\n Snapshot snapshot = snapPayload.castToSnapshot();\n // This will revert if the snapshot signer is not a known Guard/Notary\n (AgentStatus memory status, address agent) =\n _verifySnapshot({snapshot: snapshot, snapSignature: snapSignature, verifyNotary: false});\n // Agent needs to be Active/Unstaking\n status.verifyActiveUnstaking();\n // This will revert if state does not refer to this chain\n isValidState = IStateHub(origin).isValidState(snapshot.state(stateIndex).unwrap().clone());\n if (!isValidState) {\n emit InvalidStateWithSnapshot(stateIndex, snapPayload, snapSignature);\n IAgentManager(agentManager).slashAgent(status.domain, agent, msg.sender);\n }\n }\n\n /// @inheritdoc IStatementInbox\n function verifyStateReport(bytes memory statePayload, bytes memory srSignature)\n external\n returns (bool isValidReport)\n {\n // This will revert if payload is not a state\n State state = statePayload.castToState();\n // This will revert if the report signer is not a known Guard\n (AgentStatus memory status, address guard) = _verifyStateReport(state, srSignature);\n // Guard needs to be Active/Unstaking\n status.verifyActiveUnstaking();\n // Report is valid IF AND ONLY IF the reported state in invalid\n // This will revert if the reported state does not refer to this chain\n isValidReport = !IStateHub(origin).isValidState(statePayload);\n if (!isValidReport) {\n emit InvalidStateReport(statePayload, srSignature);\n IAgentManager(agentManager).slashAgent(status.domain, guard, msg.sender);\n }\n }\n\n // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════\n\n /// @inheritdoc IStatementInbox\n function getReportsAmount() external view returns (uint256) {\n return _storedReports.length;\n }\n\n /// @inheritdoc IStatementInbox\n function getGuardReport(uint256 index)\n external\n view\n returns (bytes memory statementPayload, bytes memory reportSignature)\n {\n if (index \u003e= _storedReports.length) revert IndexOutOfRange();\n StoredReport memory storedReport = _storedReports[index];\n statementPayload = storedReport.statementPayload;\n reportSignature = _storedSignatures[storedReport.sigIndex];\n }\n\n /// @inheritdoc IStatementInbox\n function getStoredSignature(uint256 index) external view returns (bytes memory) {\n return _storedSignatures[index];\n }\n\n // ══════════════════════════════════════════════ INTERNAL LOGIC ═══════════════════════════════════════════════════\n\n /// @dev Saves the statement reported by Guard as invalid and the Guard Report signature.\n function _saveReport(bytes memory statementPayload, bytes memory reportSignature) internal {\n uint256 sigIndex = _saveSignature(reportSignature);\n _storedReports.push(StoredReport(sigIndex, statementPayload));\n }\n\n /// @dev Saves the signature and returns its index.\n function _saveSignature(bytes memory signature) internal returns (uint256 sigIndex) {\n sigIndex = _storedSignatures.length;\n _storedSignatures.push(signature);\n }\n\n // ═══════════════════════════════════════════════ AGENT CHECKS ════════════════════════════════════════════════════\n\n /**\n * @dev Recovers a signer from a hashed message, and a EIP-191 signature for it.\n * Will revert, if the signer is not a known agent.\n * @dev Agent flag could be any of these: Active/Unstaking/Resting/Fraudulent/Slashed\n * Further checks need to be performed in a caller function.\n * @param hashedStatement Hash of the statement that was signed by an Agent\n * @param signature Agent signature for the hashed statement\n * @return status Struct representing agent status:\n * - flag Unknown/Active/Unstaking/Resting/Fraudulent/Slashed\n * - domain Domain where agent is/was active\n * - index Index of agent in the Agent Merkle Tree\n * @return agent Agent that signed the statement\n */\n function _recoverAgent(bytes32 hashedStatement, bytes memory signature)\n internal\n view\n returns (AgentStatus memory status, address agent)\n {\n bytes32 ethSignedMsg = ECDSA.toEthSignedMessageHash(hashedStatement);\n agent = ECDSA.recover(ethSignedMsg, signature);\n status = IAgentManager(agentManager).agentStatus(agent);\n // Discard signature of unknown agents.\n // Further flag checks are supposed to be performed in a caller function.\n status.verifyKnown();\n }\n\n /// @dev Verifies that Notary signature is active on local domain.\n function _verifyNotaryDomain(uint32 notaryDomain) internal view {\n // Notary needs to be from the local domain (if contract is not deployed on Synapse Chain).\n // Or Notary could be from any domain (if contract is deployed on Synapse Chain).\n if (notaryDomain != localDomain \u0026\u0026 localDomain != synapseDomain) revert IncorrectAgentDomain();\n }\n\n // ════════════════════════════════════════ ATTESTATION RELATED CHECKS ═════════════════════════════════════════════\n\n /**\n * @dev Internal function to verify the signed attestation payload.\n * Reverts if any of these is true:\n * - Attestation signer is not a known Notary.\n * @param att Typed memory view over attestation payload\n * @param attSignature Notary signature for the attestation\n * @return status Struct representing agent status, see {_recoverAgent}\n * @return notary Notary that signed the snapshot\n */\n function _verifyAttestation(Attestation att, bytes memory attSignature)\n internal\n view\n returns (AgentStatus memory status, address notary)\n {\n // This will revert if signer is not a known agent\n (status, notary) = _recoverAgent(att.hashValid(), attSignature);\n // Attestation signer needs to be a Notary, not a Guard\n if (status.domain == 0) revert AgentNotNotary();\n }\n\n /**\n * @dev Internal function to verify the signed attestation report payload.\n * Reverts if any of these is true:\n * - Report signer is not a known Guard.\n * @param att Typed memory view over attestation payload that Guard reports as invalid\n * @param arSignature Guard signature for the \"invalid attestation\" report\n * @return status Struct representing guard status, see {_recoverAgent}\n * @return guard Guard that signed the report\n */\n function _verifyAttestationReport(Attestation att, bytes memory arSignature)\n internal\n view\n returns (AgentStatus memory status, address guard)\n {\n // This will revert if signer is not a known agent\n (status, guard) = _recoverAgent(att.hashInvalid(), arSignature);\n // Report signer needs to be a Guard, not a Notary\n if (status.domain != 0) revert AgentNotGuard();\n }\n\n // ══════════════════════════════════════════ RECEIPT RELATED CHECKS ═══════════════════════════════════════════════\n\n /**\n * @dev Internal function to verify the signed receipt payload.\n * Reverts if any of these is true:\n * - Receipt signer is not a known Notary.\n * @param rcpt Typed memory view over receipt payload\n * @param rcptSignature Notary signature for the receipt\n * @return status Struct representing agent status, see {_recoverAgent}\n * @return notary Notary that signed the snapshot\n */\n function _verifyReceipt(Receipt rcpt, bytes memory rcptSignature)\n internal\n view\n returns (AgentStatus memory status, address notary)\n {\n // This will revert if signer is not a known agent\n (status, notary) = _recoverAgent(rcpt.hashValid(), rcptSignature);\n // Receipt signer needs to be a Notary, not a Guard\n if (status.domain == 0) revert AgentNotNotary();\n }\n\n /**\n * @dev Internal function to verify the signed receipt report payload.\n * Reverts if any of these is true:\n * - Report signer is not a known Guard.\n * @param rcpt Typed memory view over receipt payload that Guard reports as invalid\n * @param rrSignature Guard signature for the \"invalid receipt\" report\n * @return status Struct representing guard status, see {_recoverAgent}\n * @return guard Guard that signed the report\n */\n function _verifyReceiptReport(Receipt rcpt, bytes memory rrSignature)\n internal\n view\n returns (AgentStatus memory status, address guard)\n {\n // This will revert if signer is not a known agent\n (status, guard) = _recoverAgent(rcpt.hashInvalid(), rrSignature);\n // Report signer needs to be a Guard, not a Notary\n if (status.domain != 0) revert AgentNotGuard();\n }\n\n // ═══════════════════════════════════════ STATE/SNAPSHOT RELATED CHECKS ═══════════════════════════════════════════\n\n /**\n * @dev Internal function to verify the signed snapshot report payload.\n * Reverts if any of these is true:\n * - Report signer is not a known Guard.\n * @param state Typed memory view over state payload that Guard reports as invalid\n * @param srSignature Guard signature for the report\n * @return status Struct representing guard status, see {_recoverAgent}\n * @return guard Guard that signed the report\n */\n function _verifyStateReport(State state, bytes memory srSignature)\n internal\n view\n returns (AgentStatus memory status, address guard)\n {\n // This will revert if signer is not a known agent\n (status, guard) = _recoverAgent(state.hashInvalid(), srSignature);\n // Report signer needs to be a Guard, not a Notary\n if (status.domain != 0) revert AgentNotGuard();\n }\n\n /**\n * @dev Internal function to verify the signed snapshot payload.\n * Reverts if any of these is true:\n * - Snapshot signer is not a known Agent.\n * - Snapshot signer is not a Notary (if verifyNotary is true).\n * @param snapshot Typed memory view over snapshot payload\n * @param snapSignature Agent signature for the snapshot\n * @param verifyNotary If true, snapshot signer needs to be a Notary, not a Guard\n * @return status Struct representing agent status, see {_recoverAgent}\n * @return agent Agent that signed the snapshot\n */\n function _verifySnapshot(Snapshot snapshot, bytes memory snapSignature, bool verifyNotary)\n internal\n view\n returns (AgentStatus memory status, address agent)\n {\n // This will revert if signer is not a known agent\n (status, agent) = _recoverAgent(snapshot.hashValid(), snapSignature);\n // If requested, snapshot signer needs to be a Notary, not a Guard\n if (verifyNotary \u0026\u0026 status.domain == 0) revert AgentNotNotary();\n }\n\n // ═══════════════════════════════════════════ MERKLE RELATED CHECKS ═══════════════════════════════════════════════\n\n /**\n * @dev Internal function to verify that snapshot roots match.\n * Reverts if any of these is true:\n * - Attestation root is not equal to Merkle Root derived from State and Snapshot Proof.\n * - Snapshot Proof's first element does not match the State metadata.\n * - Snapshot Proof length exceeds Snapshot tree Height.\n * - State index is out of range.\n * @param att Typed memory view over Attestation\n * @param stateIndex Index of state in the snapshot\n * @param state Typed memory view over the provided state payload\n * @param snapProof Raw payload with snapshot data\n */\n function _verifySnapshotMerkle(Attestation att, uint8 stateIndex, State state, bytes32[] memory snapProof)\n internal\n pure\n {\n // Snapshot proof first element should match State metadata (aka \"right sub-leaf\")\n (, bytes32 rightSubLeaf) = state.subLeafs();\n if (snapProof[0] != rightSubLeaf) revert IncorrectSnapshotProof();\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(state.root(), state.origin(), snapProof, stateIndex);\n // Snapshot root should match the attestation root\n if (att.snapRoot() != snapshotRoot) revert IncorrectSnapshotRoot();\n }\n}\n\n// contracts/inbox/Inbox.sol\n\n// ══════════════════════════════ LIBRARY IMPORTS ══════════════════════════════\n\n// ═════════════════════════════ INTERNAL IMPORTS ══════════════════════════════\n\n/// @notice `Inbox` is the child of `StatementInbox` contract, that is used on Synapse Chain.\n/// In addition to the functionality of `StatementInbox`, it also:\n/// - Accepts Guard and Notary Snapshots and passes them to `Summit` contract.\n/// - Accepts Notary-signed Receipts and passes them to `Summit` contract.\n/// - Accepts Receipt Reports to initiate a dispute between Guard and Notary.\n/// - Verifies Attestations and Attestation Reports, and slashes the signer if they are invalid.\ncontract Inbox is StatementInbox, InboxEvents, InterfaceInbox {\n using AttestationLib for bytes;\n using ReceiptLib for bytes;\n using SnapshotLib for bytes;\n\n // Struct to get around stack too deep error. TODO: revisit this\n struct ReceiptInfo {\n AgentStatus rcptNotaryStatus;\n address notary;\n uint32 attNonce;\n AgentStatus attNotaryStatus;\n }\n\n // ══════════════════════════════════════════════════ STORAGE ══════════════════════════════════════════════════════\n\n // The address of the Summit contract.\n address public summit;\n\n // ═════════════════════════════════════════ CONSTRUCTOR \u0026 INITIALIZER ═════════════════════════════════════════════\n\n constructor(uint32 synapseDomain_) MessagingBase(\"0.0.3\", synapseDomain_) {\n if (localDomain != synapseDomain) revert MustBeSynapseDomain();\n }\n\n /// @notice Initializes `Inbox` contract:\n /// - Sets `msg.sender` as the owner of the contract\n /// - Sets `agentManager`, `origin`, `destination` and `summit` addresses\n function initialize(address agentManager_, address origin_, address destination_, address summit_)\n external\n initializer\n {\n __StatementInbox_init(agentManager_, origin_, destination_);\n summit = summit_;\n }\n\n // ══════════════════════════════════════════ SUBMIT AGENT STATEMENTS ══════════════════════════════════════════════\n\n /// @inheritdoc InterfaceInbox\n function submitSnapshot(bytes memory snapPayload, bytes memory snapSignature)\n external\n returns (bytes memory attPayload, bytes32 agentRoot_, uint256[] memory snapGas)\n {\n // This will revert if payload is not a snapshot\n Snapshot snapshot = snapPayload.castToSnapshot();\n // This will revert if the signer is not a known Guard/Notary\n (AgentStatus memory status, address agent) =\n _verifySnapshot({snapshot: snapshot, snapSignature: snapSignature, verifyNotary: false});\n // Check that Agent is active\n status.verifyActive();\n // Store Agent signature for the Snapshot\n uint256 sigIndex = _saveSignature(snapSignature);\n if (status.domain == 0) {\n // Guard that is in Dispute could still submit new snapshots, so we don't check that\n InterfaceSummit(summit).acceptGuardSnapshot({\n guardIndex: status.index,\n sigIndex: sigIndex,\n snapPayload: snapPayload\n });\n } else {\n // Get current agentRoot from AgentManager\n agentRoot_ = IAgentManager(agentManager).agentRoot();\n // This will revert if Notary is in Dispute\n attPayload = InterfaceSummit(summit).acceptNotarySnapshot({\n notaryIndex: status.index,\n sigIndex: sigIndex,\n agentRoot: agentRoot_,\n snapPayload: snapPayload\n });\n ChainGas[] memory snapGas_ = snapshot.snapGas();\n // Pass created attestation to Destination to enable executing messages coming to Synapse Chain\n InterfaceDestination(destination).acceptAttestation(\n status.index, type(uint256).max, attPayload, agentRoot_, snapGas_\n );\n // Use assembly to cast ChainGas[] to uint256[] without copying. Highest bits are left zeroed.\n // solhint-disable-next-line no-inline-assembly\n assembly {\n snapGas := snapGas_\n }\n }\n emit SnapshotAccepted(status.domain, agent, snapPayload, snapSignature);\n }\n\n /// @inheritdoc InterfaceInbox\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 // Struct to get around stack too deep error.\n ReceiptInfo memory info;\n // This will revert if payload is not a receipt\n Receipt rcpt = rcptPayload.castToReceipt();\n // This will revert if the receipt signer is not a known Notary\n (info.rcptNotaryStatus, info.notary) = _verifyReceipt(rcpt, rcptSignature);\n // Receipt Notary needs to be Active\n info.rcptNotaryStatus.verifyActive();\n info.attNonce = IExecutionHub(destination).getAttestationNonce(rcpt.snapshotRoot());\n if (info.attNonce == 0) revert IncorrectSnapshotRoot();\n // Attestation Notary domain needs to match the destination domain\n info.attNotaryStatus = IAgentManager(agentManager).agentStatus(rcpt.attNotary());\n if (info.attNotaryStatus.domain != rcpt.destination()) revert IncorrectAgentDomain();\n // Check that the correct tip values for the message were provided\n _verifyReceiptTips(rcpt.messageHash(), paddedTips, headerHash, bodyHash);\n // Store Notary signature for the Receipt\n uint256 sigIndex = _saveSignature(rcptSignature);\n // This will revert if Receipt Notary is in Dispute\n wasAccepted = InterfaceSummit(summit).acceptReceipt({\n rcptNotaryIndex: info.rcptNotaryStatus.index,\n attNotaryIndex: info.attNotaryStatus.index,\n sigIndex: sigIndex,\n attNonce: info.attNonce,\n paddedTips: paddedTips,\n rcptPayload: rcptPayload\n });\n if (wasAccepted) {\n emit ReceiptAccepted(info.rcptNotaryStatus.domain, info.notary, rcptPayload, rcptSignature);\n }\n }\n\n /// @inheritdoc InterfaceInbox\n function submitReceiptReport(bytes memory rcptPayload, bytes memory rcptSignature, bytes memory rrSignature)\n external\n returns (bool wasAccepted)\n {\n // This will revert if payload is not a receipt\n Receipt rcpt = rcptPayload.castToReceipt();\n // This will revert if the receipt signer is not a known Guard\n (AgentStatus memory guardStatus,) = _verifyReceiptReport(rcpt, rrSignature);\n // Guard needs to be Active\n guardStatus.verifyActive();\n // This will revert if report signer is not a known Notary\n (AgentStatus memory notaryStatus,) = _verifyReceipt(rcpt, rcptSignature);\n // Notary needs to be Active/Unstaking\n notaryStatus.verifyActiveUnstaking();\n _saveReport(rcptPayload, rrSignature);\n // This will revert if either actor is already in dispute\n IAgentManager(agentManager).openDispute(guardStatus.index, notaryStatus.index);\n return true;\n }\n\n /// @inheritdoc InterfaceInbox\n function passReceipt(uint32 attNotaryIndex, uint32 attNonce, uint256 paddedTips, bytes memory rcptPayload)\n external\n returns (bool wasAccepted)\n {\n // Only Destination can pass receipts\n if (msg.sender != destination) revert CallerNotDestination();\n return InterfaceSummit(summit).acceptReceipt({\n rcptNotaryIndex: attNotaryIndex,\n attNotaryIndex: attNotaryIndex,\n sigIndex: type(uint256).max,\n attNonce: attNonce,\n paddedTips: paddedTips,\n rcptPayload: rcptPayload\n });\n }\n\n // ══════════════════════════════════════════ VERIFY AGENT STATEMENTS ══════════════════════════════════════════════\n\n /// @inheritdoc InterfaceInbox\n function verifyAttestation(bytes memory attPayload, bytes memory attSignature)\n external\n returns (bool isValidAttestation)\n {\n // This will revert if payload is not an attestation\n Attestation att = attPayload.castToAttestation();\n // This will revert if the attestation signer is not a known Notary\n (AgentStatus memory status, address notary) = _verifyAttestation(att, attSignature);\n // Notary needs to be Active/Unstaking\n status.verifyActiveUnstaking();\n isValidAttestation = ISnapshotHub(summit).isValidAttestation(attPayload);\n if (!isValidAttestation) {\n emit InvalidAttestation(attPayload, attSignature);\n IAgentManager(agentManager).slashAgent(status.domain, notary, msg.sender);\n }\n }\n\n /// @inheritdoc InterfaceInbox\n function verifyAttestationReport(bytes memory attPayload, bytes memory arSignature)\n external\n returns (bool isValidReport)\n {\n // This will revert if payload is not an attestation\n Attestation att = attPayload.castToAttestation();\n // This will revert if the report signer is not a known Guard\n (AgentStatus memory status, address guard) = _verifyAttestationReport(att, arSignature);\n // Guard needs to be Active/Unstaking\n status.verifyActiveUnstaking();\n // Report is valid IF AND ONLY IF the reported attestation in invalid\n isValidReport = !ISnapshotHub(summit).isValidAttestation(attPayload);\n if (!isValidReport) {\n emit InvalidAttestationReport(attPayload, arSignature);\n IAgentManager(agentManager).slashAgent(status.domain, guard, msg.sender);\n }\n }\n\n // ══════════════════════════════════════════════ INTERNAL VIEWS ═══════════════════════════════════════════════════\n\n /// @dev Verifies that tips proof matches the message hash.\n function _verifyReceiptTips(bytes32 msgHash, uint256 paddedTips, bytes32 headerHash, bytes32 bodyHash)\n internal\n pure\n {\n Tips tips = TipsLib.wrapPadded(paddedTips);\n // full message leaf is (header, baseMessage), while base message leaf is (tips, remainingBody).\n if (MerkleMath.getParent(headerHash, MerkleMath.getParent(tips.leaf(), bodyHash)) != msgHash) {\n revert IncorrectTipsProof();\n }\n }\n}\n","language":"Solidity","languageVersion":"0.8.17","compilerVersion":"0.8.17","compilerOptions":"--combined-json bin,bin-runtime,srcmap,srcmap-runtime,abi,userdoc,devdoc,metadata,hashes --optimize --optimize-runs 10000 --allow-paths ., ./, ../","srcMap":"","srcMapRuntime":"","abiDefinition":[{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint32","name":"domain","type":"uint32"},{"indexed":false,"internalType":"address","name":"notary","type":"address"},{"indexed":false,"internalType":"bytes","name":"attPayload","type":"bytes"},{"indexed":false,"internalType":"bytes","name":"attSignature","type":"bytes"}],"name":"AttestationAccepted","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"bytes","name":"rcptPayload","type":"bytes"},{"indexed":false,"internalType":"bytes","name":"rcptSignature","type":"bytes"}],"name":"InvalidReceipt","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"bytes","name":"rrPayload","type":"bytes"},{"indexed":false,"internalType":"bytes","name":"rrSignature","type":"bytes"}],"name":"InvalidReceiptReport","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"bytes","name":"srPayload","type":"bytes"},{"indexed":false,"internalType":"bytes","name":"srSignature","type":"bytes"}],"name":"InvalidStateReport","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint8","name":"stateIndex","type":"uint8"},{"indexed":false,"internalType":"bytes","name":"statePayload","type":"bytes"},{"indexed":false,"internalType":"bytes","name":"attPayload","type":"bytes"},{"indexed":false,"internalType":"bytes","name":"attSignature","type":"bytes"}],"name":"InvalidStateWithAttestation","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint8","name":"stateIndex","type":"uint8"},{"indexed":false,"internalType":"bytes","name":"snapPayload","type":"bytes"},{"indexed":false,"internalType":"bytes","name":"snapSignature","type":"bytes"}],"name":"InvalidStateWithSnapshot","type":"event"}],"userDoc":{"events":{"AttestationAccepted(uint32,address,bytes,bytes)":{"notice":"Emitted when a snapshot is accepted by the Destination contract."},"InvalidReceipt(bytes,bytes)":{"notice":"Emitted when a proof of invalid receipt statement is submitted."},"InvalidReceiptReport(bytes,bytes)":{"notice":"Emitted when a proof of invalid receipt report is submitted."},"InvalidStateReport(bytes,bytes)":{"notice":"Emitted when a proof of invalid state report is submitted."},"InvalidStateWithAttestation(uint8,bytes,bytes,bytes)":{"notice":"Emitted when a proof of invalid state in the signed attestation is submitted."},"InvalidStateWithSnapshot(uint8,bytes,bytes)":{"notice":"Emitted when a proof of invalid state in the signed snapshot is submitted."}},"kind":"user","methods":{},"version":1},"developerDoc":{"events":{"AttestationAccepted(uint32,address,bytes,bytes)":{"params":{"attPayload":"Raw payload with attestation data","attSignature":"Notary signature for the attestation","domain":"Domain where the signed Notary is active","notary":"Notary who signed the attestation"}},"InvalidReceipt(bytes,bytes)":{"params":{"rcptPayload":"Raw payload with the receipt statement","rcptSignature":"Notary signature for the receipt statement"}},"InvalidReceiptReport(bytes,bytes)":{"params":{"rrPayload":"Raw payload with report data","rrSignature":"Guard signature for the report"}},"InvalidStateReport(bytes,bytes)":{"params":{"srPayload":"Raw payload with report data","srSignature":"Guard signature for the report"}},"InvalidStateWithAttestation(uint8,bytes,bytes,bytes)":{"params":{"attPayload":"Raw payload with Attestation data for snapshot","attSignature":"Notary signature for the attestation","stateIndex":"Index of invalid state in the snapshot","statePayload":"Raw payload with state data"}},"InvalidStateWithSnapshot(uint8,bytes,bytes)":{"params":{"snapPayload":"Raw payload with snapshot data","snapSignature":"Agent signature for the snapshot","stateIndex":"Index of invalid state in the snapshot"}}},"kind":"dev","methods":{},"version":1},"metadata":"{\"compiler\":{\"version\":\"0.8.17+commit.8df45f5f\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint32\",\"name\":\"domain\",\"type\":\"uint32\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"notary\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"attPayload\",\"type\":\"bytes\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"attSignature\",\"type\":\"bytes\"}],\"name\":\"AttestationAccepted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"rcptPayload\",\"type\":\"bytes\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"rcptSignature\",\"type\":\"bytes\"}],\"name\":\"InvalidReceipt\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"rrPayload\",\"type\":\"bytes\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"rrSignature\",\"type\":\"bytes\"}],\"name\":\"InvalidReceiptReport\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"srPayload\",\"type\":\"bytes\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"srSignature\",\"type\":\"bytes\"}],\"name\":\"InvalidStateReport\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint8\",\"name\":\"stateIndex\",\"type\":\"uint8\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"statePayload\",\"type\":\"bytes\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"attPayload\",\"type\":\"bytes\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"attSignature\",\"type\":\"bytes\"}],\"name\":\"InvalidStateWithAttestation\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint8\",\"name\":\"stateIndex\",\"type\":\"uint8\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"snapPayload\",\"type\":\"bytes\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"snapSignature\",\"type\":\"bytes\"}],\"name\":\"InvalidStateWithSnapshot\",\"type\":\"event\"}],\"devdoc\":{\"events\":{\"AttestationAccepted(uint32,address,bytes,bytes)\":{\"params\":{\"attPayload\":\"Raw payload with attestation data\",\"attSignature\":\"Notary signature for the attestation\",\"domain\":\"Domain where the signed Notary is active\",\"notary\":\"Notary who signed the attestation\"}},\"InvalidReceipt(bytes,bytes)\":{\"params\":{\"rcptPayload\":\"Raw payload with the receipt statement\",\"rcptSignature\":\"Notary signature for the receipt statement\"}},\"InvalidReceiptReport(bytes,bytes)\":{\"params\":{\"rrPayload\":\"Raw payload with report data\",\"rrSignature\":\"Guard signature for the report\"}},\"InvalidStateReport(bytes,bytes)\":{\"params\":{\"srPayload\":\"Raw payload with report data\",\"srSignature\":\"Guard signature for the report\"}},\"InvalidStateWithAttestation(uint8,bytes,bytes,bytes)\":{\"params\":{\"attPayload\":\"Raw payload with Attestation data for snapshot\",\"attSignature\":\"Notary signature for the attestation\",\"stateIndex\":\"Index of invalid state in the snapshot\",\"statePayload\":\"Raw payload with state data\"}},\"InvalidStateWithSnapshot(uint8,bytes,bytes)\":{\"params\":{\"snapPayload\":\"Raw payload with snapshot data\",\"snapSignature\":\"Agent signature for the snapshot\",\"stateIndex\":\"Index of invalid state in the snapshot\"}}},\"kind\":\"dev\",\"methods\":{},\"version\":1},\"userdoc\":{\"events\":{\"AttestationAccepted(uint32,address,bytes,bytes)\":{\"notice\":\"Emitted when a snapshot is accepted by the Destination contract.\"},\"InvalidReceipt(bytes,bytes)\":{\"notice\":\"Emitted when a proof of invalid receipt statement is submitted.\"},\"InvalidReceiptReport(bytes,bytes)\":{\"notice\":\"Emitted when a proof of invalid receipt report is submitted.\"},\"InvalidStateReport(bytes,bytes)\":{\"notice\":\"Emitted when a proof of invalid state report is submitted.\"},\"InvalidStateWithAttestation(uint8,bytes,bytes,bytes)\":{\"notice\":\"Emitted when a proof of invalid state in the signed attestation is submitted.\"},\"InvalidStateWithSnapshot(uint8,bytes,bytes)\":{\"notice\":\"Emitted when a proof of invalid state in the signed snapshot is submitted.\"}},\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"solidity/Inbox.sol\":\"StatementInboxEvents\"},\"evmVersion\":\"london\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\"},\"optimizer\":{\"enabled\":true,\"runs\":10000},\"remappings\":[]},\"sources\":{\"solidity/Inbox.sol\":{\"keccak256\":\"0x9b516081a036814c0169e20e484d4a5499066b7a6f48fada952b5e844a1ca3e5\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://32bde393b3f24ef4307d9626d4143f337b3c0bd34e17bb969fd5a15221d96987\",\"dweb:/ipfs/QmTkt2XZRtgsbSpmsVQUM3c4ebETQoDVYbmEV9yheBghnr\"]}},\"version\":1}"},"hashes":{}},"solidity/Inbox.sol:Strings":{"code":"0x60566037600b82828239805160001a607314602a57634e487b7160e01b600052600060045260246000fd5b30600052607381538281f3fe73000000000000000000000000000000000000000030146080604052600080fdfea2646970667358221220e47e63d0f3a5edc36a3ba53b3deb8da19f5b14d1e4fa361663b5f045d915fe2864736f6c63430008110033","runtime-code":"0x73000000000000000000000000000000000000000030146080604052600080fdfea2646970667358221220e47e63d0f3a5edc36a3ba53b3deb8da19f5b14d1e4fa361663b5f045d915fe2864736f6c63430008110033","info":{"source":"// SPDX-License-Identifier: MIT\npragma solidity =0.8.17 ^0.8.0 ^0.8.1 ^0.8.2;\n\n// contracts/events/InboxEvents.sol\n\nabstract contract InboxEvents {\n /**\n * @notice Emitted when a snapshot is accepted by the Summit contract.\n * @param domain Domain where the signed Agent is active (ZERO for Guards)\n * @param agent Agent who signed the snapshot\n * @param snapPayload Raw payload with snapshot data\n * @param snapSignature Agent signature for the snapshot\n */\n event SnapshotAccepted(uint32 indexed domain, address indexed agent, bytes snapPayload, bytes snapSignature);\n\n /**\n * @notice Emitted when a snapshot is accepted by the Summit contract.\n * @param domain Domain where the signed Notary is active\n * @param notary Notary who signed the attestation\n * @param rcptPayload Raw payload with receipt data\n * @param rcptSignature Notary signature for the receipt\n */\n event ReceiptAccepted(uint32 domain, address notary, bytes rcptPayload, bytes rcptSignature);\n\n /**\n * @notice Emitted when a proof of invalid attestation is submitted.\n * @param attPayload Raw payload with Attestation data\n * @param attSignature Notary signature for the attestation\n */\n event InvalidAttestation(bytes attPayload, bytes attSignature);\n\n /**\n * @notice Emitted when a proof of invalid attestation report is submitted.\n * @param arPayload Raw payload with report data\n * @param arSignature Guard signature for the report\n */\n event InvalidAttestationReport(bytes arPayload, bytes arSignature);\n}\n\n// contracts/events/StatementInboxEvents.sol\n\nabstract contract StatementInboxEvents {\n // ════════════════════════════════════════════ STATEMENT ACCEPTED ═════════════════════════════════════════════════\n\n /**\n * @notice Emitted when a snapshot is accepted by the Destination contract.\n * @param domain Domain where the signed Notary is active\n * @param notary Notary who signed the attestation\n * @param attPayload Raw payload with attestation data\n * @param attSignature Notary signature for the attestation\n */\n event AttestationAccepted(uint32 domain, address notary, bytes attPayload, bytes attSignature);\n\n // ═════════════════════════════════════════ INVALID STATEMENT PROVED ══════════════════════════════════════════════\n\n /**\n * @notice Emitted when a proof of invalid receipt statement is submitted.\n * @param rcptPayload Raw payload with the receipt statement\n * @param rcptSignature Notary signature for the receipt statement\n */\n event InvalidReceipt(bytes rcptPayload, bytes rcptSignature);\n\n /**\n * @notice Emitted when a proof of invalid receipt report is submitted.\n * @param rrPayload Raw payload with report data\n * @param rrSignature Guard signature for the report\n */\n event InvalidReceiptReport(bytes rrPayload, bytes rrSignature);\n\n /**\n * @notice Emitted when a proof of invalid state in the signed attestation is submitted.\n * @param stateIndex Index of invalid state in the snapshot\n * @param statePayload Raw payload with state data\n * @param attPayload Raw payload with Attestation data for snapshot\n * @param attSignature Notary signature for the attestation\n */\n event InvalidStateWithAttestation(uint8 stateIndex, bytes statePayload, bytes attPayload, bytes attSignature);\n\n /**\n * @notice Emitted when a proof of invalid state in the signed snapshot is submitted.\n * @param stateIndex Index of invalid state in the snapshot\n * @param snapPayload Raw payload with snapshot data\n * @param snapSignature Agent signature for the snapshot\n */\n event InvalidStateWithSnapshot(uint8 stateIndex, bytes snapPayload, bytes snapSignature);\n\n /**\n * @notice Emitted when a proof of invalid state report is submitted.\n * @param srPayload Raw payload with report data\n * @param srSignature Guard signature for the report\n */\n event InvalidStateReport(bytes srPayload, bytes srSignature);\n}\n\n// contracts/interfaces/ISnapshotHub.sol\n\ninterface ISnapshotHub {\n /**\n * @notice Check that a given attestation is valid: matches the historical attestation\n * derived from an accepted Notary snapshot.\n * @dev Will revert if any of these is true:\n * - Attestation payload is not properly formatted.\n * @param attPayload Raw payload with attestation data\n * @return isValid Whether the provided attestation is valid\n */\n function isValidAttestation(bytes memory attPayload) external view returns (bool isValid);\n\n /**\n * @notice Returns saved attestation with the given nonce.\n * @dev Reverts if attestation with given nonce hasn't been created yet.\n * @param attNonce Nonce for the attestation\n * @return attPayload Raw payload with formatted Attestation data\n * @return agentRoot Agent root hash used for the attestation\n * @return snapGas Snapshot gas data used for the attestation\n */\n function getAttestation(uint32 attNonce)\n external\n view\n returns (bytes memory attPayload, bytes32 agentRoot, uint256[] memory snapGas);\n\n /**\n * @notice Returns the state with the highest known nonce submitted by a given Agent.\n * @param origin Domain of origin chain\n * @param agent Agent address\n * @return statePayload Raw payload with agent's latest state for origin\n */\n function getLatestAgentState(uint32 origin, address agent) external view returns (bytes memory statePayload);\n\n /**\n * @notice Returns latest saved attestation for a Notary.\n * @param notary Notary address\n * @return attPayload Raw payload with formatted Attestation data\n * @return agentRoot Agent root hash used for the attestation\n * @return snapGas Snapshot gas data used for the attestation\n */\n function getLatestNotaryAttestation(address notary)\n external\n view\n returns (bytes memory attPayload, bytes32 agentRoot, uint256[] memory snapGas);\n\n /**\n * @notice Returns Guard snapshot from the list of all accepted Guard snapshots.\n * @dev Reverts if snapshot with given index hasn't been accepted yet.\n * @param index Snapshot index in the list of all Guard snapshots\n * @return snapPayload Raw payload with Guard snapshot\n * @return snapSignature Raw payload with Guard signature for snapshot\n */\n function getGuardSnapshot(uint256 index)\n external\n view\n returns (bytes memory snapPayload, bytes memory snapSignature);\n\n /**\n * @notice Returns Notary snapshot from the list of all accepted Guard snapshots.\n * @dev Reverts if snapshot with given index hasn't been accepted yet.\n * @param index Snapshot index in the list of all Notary snapshots\n * @return snapPayload Raw payload with Notary snapshot\n * @return snapSignature Raw payload with Notary signature for snapshot\n */\n function getNotarySnapshot(uint256 index)\n external\n view\n returns (bytes memory snapPayload, bytes memory snapSignature);\n\n /**\n * @notice Returns Notary snapshot that was used for creating a given attestation.\n * @dev Reverts if any of these is true:\n * - Attestation payload is not properly formatted.\n * - Attestation is invalid (doesn't have a matching Notary snapshot).\n * @param attPayload Raw payload with attestation data\n * @return snapPayload Raw payload with Notary snapshot\n * @return snapSignature Raw payload with Notary signature for snapshot\n */\n function getNotarySnapshot(bytes memory attPayload)\n external\n view\n returns (bytes memory snapPayload, bytes memory snapSignature);\n\n /**\n * @notice Returns proof of inclusion of (root, origin) fields of a given snapshot's state\n * into the Snapshot Merkle Tree for a given attestation.\n * @dev Reverts if any of these is true:\n * - Attestation with given nonce hasn't been created yet.\n * - State index is out of range of snapshot list.\n * @param attNonce Nonce for the attestation\n * @param stateIndex Index of state in the attestation'