synapsecns/sanguine

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

Summary

Maintainability
Test Coverage
{"solidity/BaseMessageHarness.t.sol:BaseMessageHarness":{"code":"0x608060405234801561001057600080fd5b50610aa2806100206000396000f3fe608060405234801561001057600080fd5b50600436106100be5760003560e01c80636dc3c4f711610076578063985a5c311161005b578063985a5c3114610178578063b94207d31461018b578063d7a7a72c146101c757600080fd5b80636dc3c4f714610152578063949b7cee1461016557600080fd5b806327f8d97f116100a757806327f8d97f14610109578063311bc6c81461012c5780635013fc9f1461013f57600080fd5b8063045c6c0b146100c357806307755381146100e9575b600080fd5b6100d66100d136600461089e565b6101da565b6040519081526020015b60405180910390f35b6100fc6100f736600461089e565b6101f3565b6040516100e091906108f7565b61011c61011736600461089e565b61020e565b60405190151581526020016100e0565b6100fc61013a366004610948565b610221565b6100fc61014d36600461089e565b61023a565b6100d661016036600461089e565b610259565b6100d661017336600461089e565b61026c565b6100d661018636600461089e565b61027f565b61019e61019936600461089e565b610292565b60405177ffffffffffffffffffffffffffffffffffffffffffffffff90911681526020016100e0565b6100d66101d536600461089e565b6102a5565b60006101ed6101e8836102b8565b6102cb565b92915050565b60606101ed610209610204846102b8565b6102e2565b610307565b60006101ed61021c83610364565b61037f565b606061023086868686866103b4565b9695505050505050565b60606000610247836102b8565b905061025281610307565b9392505050565b60006101ed610267836102b8565b6103e9565b60006101ed61027a836102b8565b6103fa565b60006101ed61028d836102b8565b61040f565b60006101ed6102a0836102b8565b61041e565b60006101ed6102b3836102b8565b61043a565b60006101ed6102c683610364565b610465565b60006101ed6102df826020855b91906104aa565b90565b60006101ed60186102f5602060406109d2565b6102ff91906109d2565b835b906104cb565b604051806103188360208301610531565b506fffffffffffffffffffffffffffffffff83166000601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0168301602001604052509052919050565b80516000906020830161037781836105e0565b949350505050565b6000601861038f602060406109d2565b61039991906109d2565b6fffffffffffffffffffffffffffffffff8316101592915050565b606085858585856040516020016103cf959493929190610a0c565b604051602081830303815290604052905095945050505050565b60006101ed602080845b9190610643565b60006101ed61040a602084610301565b61074d565b60006101ed60406020846103f3565b60006101ed6102df610432602060406109d2565b6018856102d8565b60006101ed61045761044b846102cb565b60009081526020902090565b610460846103fa565b610778565b60006104708261037f565b6104a6576040517f35c196ef00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5090565b6000806104b8858585610643565b602084900360031b1c9150509392505050565b60006fffffffffffffffffffffffffffffffff83168083111561051a576040517fa3b99ded00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610377836105288660801c90565b018483036105e0565b6040516000906fffffffffffffffffffffffffffffffff841690608085901c908085101561058b576040517f4b2a158c00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008386858560045afa9050806105ce576040517f7c7d772f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b608086901b8417979650505050505050565b6000806105ed83856109d2565b90506040518111156105fd575060005b80600003610637576040517f10bef38600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b608084901b8317610377565b60008160000361065557506000610252565b6020821115610690576040517f31d784a800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6fffffffffffffffffffffffffffffffff84166106ad83856109d2565b11156106e5576040517fa3b99ded00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600382901b60006106f68660801c90565b909401517f80000000000000000000000000000000000000000000000000000000000000007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff929092019190911d16949350505050565b60008061075a8360801c90565b6fffffffffffffffffffffffffffffffff9390931690922092915050565b600082158015610786575081155b15610793575060006101ed565b60408051602081018590529081018390526060016040516020818303038152906040528051906020012090506101ed565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b600082601f83011261080457600080fd5b813567ffffffffffffffff8082111561081f5761081f6107c4565b604051601f83017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f01168101908282118183101715610865576108656107c4565b8160405283815286602085880101111561087e57600080fd5b836020870160208301376000602085830101528094505050505092915050565b6000602082840312156108b057600080fd5b813567ffffffffffffffff8111156108c757600080fd5b610377848285016107f3565b60005b838110156108ee5781810151838201526020016108d6565b50506000910152565b60208152600082518060208401526109168160408501602087016108d3565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169190910160400192915050565b600080600080600060a0868803121561096057600080fd5b853594506020860135935060408601359250606086013577ffffffffffffffffffffffffffffffffffffffffffffffff8116811461099d57600080fd5b9150608086013567ffffffffffffffff8111156109b957600080fd5b6109c5888289016107f3565b9150509295509295909350565b808201808211156101ed577f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b8581528460208201528360408201527fffffffffffffffffffffffffffffffffffffffffffffffff00000000000000008360401b16606082015260008251610a5b8160788501602087016108d3565b91909101607801969550505050505056fea2646970667358221220eca41bb3f4c48da3bd0b509394a95e456a9a29d8736f327b6683663bbfd4e6a364736f6c63430008110033","runtime-code":"0x608060405234801561001057600080fd5b50600436106100be5760003560e01c80636dc3c4f711610076578063985a5c311161005b578063985a5c3114610178578063b94207d31461018b578063d7a7a72c146101c757600080fd5b80636dc3c4f714610152578063949b7cee1461016557600080fd5b806327f8d97f116100a757806327f8d97f14610109578063311bc6c81461012c5780635013fc9f1461013f57600080fd5b8063045c6c0b146100c357806307755381146100e9575b600080fd5b6100d66100d136600461089e565b6101da565b6040519081526020015b60405180910390f35b6100fc6100f736600461089e565b6101f3565b6040516100e091906108f7565b61011c61011736600461089e565b61020e565b60405190151581526020016100e0565b6100fc61013a366004610948565b610221565b6100fc61014d36600461089e565b61023a565b6100d661016036600461089e565b610259565b6100d661017336600461089e565b61026c565b6100d661018636600461089e565b61027f565b61019e61019936600461089e565b610292565b60405177ffffffffffffffffffffffffffffffffffffffffffffffff90911681526020016100e0565b6100d66101d536600461089e565b6102a5565b60006101ed6101e8836102b8565b6102cb565b92915050565b60606101ed610209610204846102b8565b6102e2565b610307565b60006101ed61021c83610364565b61037f565b606061023086868686866103b4565b9695505050505050565b60606000610247836102b8565b905061025281610307565b9392505050565b60006101ed610267836102b8565b6103e9565b60006101ed61027a836102b8565b6103fa565b60006101ed61028d836102b8565b61040f565b60006101ed6102a0836102b8565b61041e565b60006101ed6102b3836102b8565b61043a565b60006101ed6102c683610364565b610465565b60006101ed6102df826020855b91906104aa565b90565b60006101ed60186102f5602060406109d2565b6102ff91906109d2565b835b906104cb565b604051806103188360208301610531565b506fffffffffffffffffffffffffffffffff83166000601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0168301602001604052509052919050565b80516000906020830161037781836105e0565b949350505050565b6000601861038f602060406109d2565b61039991906109d2565b6fffffffffffffffffffffffffffffffff8316101592915050565b606085858585856040516020016103cf959493929190610a0c565b604051602081830303815290604052905095945050505050565b60006101ed602080845b9190610643565b60006101ed61040a602084610301565b61074d565b60006101ed60406020846103f3565b60006101ed6102df610432602060406109d2565b6018856102d8565b60006101ed61045761044b846102cb565b60009081526020902090565b610460846103fa565b610778565b60006104708261037f565b6104a6576040517f35c196ef00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5090565b6000806104b8858585610643565b602084900360031b1c9150509392505050565b60006fffffffffffffffffffffffffffffffff83168083111561051a576040517fa3b99ded00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610377836105288660801c90565b018483036105e0565b6040516000906fffffffffffffffffffffffffffffffff841690608085901c908085101561058b576040517f4b2a158c00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008386858560045afa9050806105ce576040517f7c7d772f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b608086901b8417979650505050505050565b6000806105ed83856109d2565b90506040518111156105fd575060005b80600003610637576040517f10bef38600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b608084901b8317610377565b60008160000361065557506000610252565b6020821115610690576040517f31d784a800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6fffffffffffffffffffffffffffffffff84166106ad83856109d2565b11156106e5576040517fa3b99ded00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600382901b60006106f68660801c90565b909401517f80000000000000000000000000000000000000000000000000000000000000007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff929092019190911d16949350505050565b60008061075a8360801c90565b6fffffffffffffffffffffffffffffffff9390931690922092915050565b600082158015610786575081155b15610793575060006101ed565b60408051602081018590529081018390526060016040516020818303038152906040528051906020012090506101ed565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b600082601f83011261080457600080fd5b813567ffffffffffffffff8082111561081f5761081f6107c4565b604051601f83017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f01168101908282118183101715610865576108656107c4565b8160405283815286602085880101111561087e57600080fd5b836020870160208301376000602085830101528094505050505092915050565b6000602082840312156108b057600080fd5b813567ffffffffffffffff8111156108c757600080fd5b610377848285016107f3565b60005b838110156108ee5781810151838201526020016108d6565b50506000910152565b60208152600082518060208401526109168160408501602087016108d3565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169190910160400192915050565b600080600080600060a0868803121561096057600080fd5b853594506020860135935060408601359250606086013577ffffffffffffffffffffffffffffffffffffffffffffffff8116811461099d57600080fd5b9150608086013567ffffffffffffffff8111156109b957600080fd5b6109c5888289016107f3565b9150509295509295909350565b808201808211156101ed577f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b8581528460208201528360408201527fffffffffffffffffffffffffffffffffffffffffffffffff00000000000000008360401b16606082015260008251610a5b8160788501602087016108d3565b91909101607801969550505050505056fea2646970667358221220eca41bb3f4c48da3bd0b509394a95e456a9a29d8736f327b6683663bbfd4e6a364736f6c63430008110033","info":{"source":"// SPDX-License-Identifier: MIT\npragma solidity =0.8.17 ^0.8.0;\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/Request.sol\n\n/// Request is encoded data with \"message execution request\".\ntype Request is uint192;\n\nusing RequestLib for Request global;\n\n/// Library for formatting _the request part_ of _the base messages_.\n/// - Request represents a message sender requirements for the message execution on the destination chain.\n/// - Request occupies a single storage word, and thus is stored on stack instead of being stored in memory.\n/// \u003e gasDrop field is included for future compatibility and is ignored at the moment.\n///\n/// # Request stack layout (from highest bits to lowest)\n///\n/// | Position   | Field    | Type   | Bytes | Description                                          |\n/// | ---------- | -------- | ------ | ----- | ---------------------------------------------------- |\n/// | (024..012] | gasDrop  | uint96 | 12    | Minimum amount of gas token to drop to the recipient |\n/// | (012..004] | gasLimit | uint64 | 8     | Minimum amount of gas units to supply for execution  |\n/// | (004..000] | version  | uint32 | 4     | Base message version to pass to the recipient        |\n\nlibrary RequestLib {\n    /// @dev Amount of bits to shift to gasDrop field\n    uint192 private constant SHIFT_GAS_DROP = 12 * 8;\n    /// @dev Amount of bits to shift to gasLimit field\n    uint192 private constant SHIFT_GAS_LIMIT = 4 * 8;\n\n    /// @notice Returns an encoded request with the given fields\n    /// @param gasDrop_     Minimum amount of gas token to drop to the recipient (ignored at the moment)\n    /// @param gasLimit_    Minimum amount of gas units to supply for execution\n    /// @param version_     Base message version to pass to the recipient\n    function encodeRequest(uint96 gasDrop_, uint64 gasLimit_, uint32 version_) internal pure returns (Request) {\n        // Casts below are upcasts, so they are safe\n        return Request.wrap(uint192(gasDrop_) \u003c\u003c SHIFT_GAS_DROP | uint192(gasLimit_) \u003c\u003c SHIFT_GAS_LIMIT | version_);\n    }\n\n    /// @notice Wraps the padded encoded request into a Request-typed value.\n    /// @dev The \"padded\" request is simply an encoded request casted to uint256 (highest bits are set to zero).\n    /// Casting to uint256 is done automatically in Solidity, so no extra actions from consumers are needed.\n    /// The highest bits are discarded, so that the contracts dealing with encoded requests\n    /// don't need to be updated, if a new field is added.\n    function wrapPadded(uint256 paddedRequest) internal pure returns (Request) {\n        // Casting to uint192 will truncate the highest bits, which is the behavior we want\n        return Request.wrap(uint192(paddedRequest));\n    }\n\n    /// @notice Returns the requested of gas token to drop to the recipient.\n    function gasDrop(Request request) internal pure returns (uint96) {\n        // Casting to uint96 will truncate the highest bits, which is the behavior we want\n        return uint96(Request.unwrap(request) \u003e\u003e SHIFT_GAS_DROP);\n    }\n\n    /// @notice Returns the requested minimum amount of gas units to supply for execution.\n    function gasLimit(Request request) internal pure returns (uint64) {\n        // Casting to uint64 will truncate the highest bits, which is the behavior we want\n        return uint64(Request.unwrap(request) \u003e\u003e SHIFT_GAS_LIMIT);\n    }\n\n    /// @notice Returns the requested base message version to pass to the recipient.\n    function version(Request request) internal pure returns (uint32) {\n        // Casting to uint32 will truncate the highest bits, which is the behavior we want\n        return uint32(Request.unwrap(request));\n    }\n}\n\n// node_modules/@openzeppelin/contracts/utils/math/SafeCast.sol\n\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/math/SafeCast.sol)\n// This file was procedurally generated from scripts/generate/templates/SafeCast.js.\n\n/**\n * @dev Wrappers over Solidity's uintXX/intXX casting operators with added overflow\n * checks.\n *\n * Downcasting from uint256/int256 in Solidity does not revert on overflow. This can\n * easily result in undesired exploitation or bugs, since developers usually\n * assume that overflows raise errors. `SafeCast` restores this intuition by\n * reverting the transaction when such an operation overflows.\n *\n * Using this library instead of the unchecked operations eliminates an entire\n * class of bugs, so it's recommended to use it always.\n *\n * Can be combined with {SafeMath} and {SignedSafeMath} to extend it to smaller types, by performing\n * all math on `uint256` and `int256` and then downcasting.\n */\nlibrary SafeCast {\n    /**\n     * @dev Returns the downcasted uint248 from uint256, reverting on\n     * overflow (when the input is greater than largest uint248).\n     *\n     * Counterpart to Solidity's `uint248` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 248 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint248(uint256 value) internal pure returns (uint248) {\n        require(value \u003c= type(uint248).max, \"SafeCast: value doesn't fit in 248 bits\");\n        return uint248(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint240 from uint256, reverting on\n     * overflow (when the input is greater than largest uint240).\n     *\n     * Counterpart to Solidity's `uint240` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 240 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint240(uint256 value) internal pure returns (uint240) {\n        require(value \u003c= type(uint240).max, \"SafeCast: value doesn't fit in 240 bits\");\n        return uint240(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint232 from uint256, reverting on\n     * overflow (when the input is greater than largest uint232).\n     *\n     * Counterpart to Solidity's `uint232` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 232 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint232(uint256 value) internal pure returns (uint232) {\n        require(value \u003c= type(uint232).max, \"SafeCast: value doesn't fit in 232 bits\");\n        return uint232(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint224 from uint256, reverting on\n     * overflow (when the input is greater than largest uint224).\n     *\n     * Counterpart to Solidity's `uint224` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 224 bits\n     *\n     * _Available since v4.2._\n     */\n    function toUint224(uint256 value) internal pure returns (uint224) {\n        require(value \u003c= type(uint224).max, \"SafeCast: value doesn't fit in 224 bits\");\n        return uint224(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint216 from uint256, reverting on\n     * overflow (when the input is greater than largest uint216).\n     *\n     * Counterpart to Solidity's `uint216` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 216 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint216(uint256 value) internal pure returns (uint216) {\n        require(value \u003c= type(uint216).max, \"SafeCast: value doesn't fit in 216 bits\");\n        return uint216(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint208 from uint256, reverting on\n     * overflow (when the input is greater than largest uint208).\n     *\n     * Counterpart to Solidity's `uint208` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 208 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint208(uint256 value) internal pure returns (uint208) {\n        require(value \u003c= type(uint208).max, \"SafeCast: value doesn't fit in 208 bits\");\n        return uint208(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint200 from uint256, reverting on\n     * overflow (when the input is greater than largest uint200).\n     *\n     * Counterpart to Solidity's `uint200` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 200 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint200(uint256 value) internal pure returns (uint200) {\n        require(value \u003c= type(uint200).max, \"SafeCast: value doesn't fit in 200 bits\");\n        return uint200(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint192 from uint256, reverting on\n     * overflow (when the input is greater than largest uint192).\n     *\n     * Counterpart to Solidity's `uint192` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 192 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint192(uint256 value) internal pure returns (uint192) {\n        require(value \u003c= type(uint192).max, \"SafeCast: value doesn't fit in 192 bits\");\n        return uint192(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint184 from uint256, reverting on\n     * overflow (when the input is greater than largest uint184).\n     *\n     * Counterpart to Solidity's `uint184` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 184 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint184(uint256 value) internal pure returns (uint184) {\n        require(value \u003c= type(uint184).max, \"SafeCast: value doesn't fit in 184 bits\");\n        return uint184(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint176 from uint256, reverting on\n     * overflow (when the input is greater than largest uint176).\n     *\n     * Counterpart to Solidity's `uint176` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 176 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint176(uint256 value) internal pure returns (uint176) {\n        require(value \u003c= type(uint176).max, \"SafeCast: value doesn't fit in 176 bits\");\n        return uint176(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint168 from uint256, reverting on\n     * overflow (when the input is greater than largest uint168).\n     *\n     * Counterpart to Solidity's `uint168` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 168 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint168(uint256 value) internal pure returns (uint168) {\n        require(value \u003c= type(uint168).max, \"SafeCast: value doesn't fit in 168 bits\");\n        return uint168(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint160 from uint256, reverting on\n     * overflow (when the input is greater than largest uint160).\n     *\n     * Counterpart to Solidity's `uint160` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 160 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint160(uint256 value) internal pure returns (uint160) {\n        require(value \u003c= type(uint160).max, \"SafeCast: value doesn't fit in 160 bits\");\n        return uint160(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint152 from uint256, reverting on\n     * overflow (when the input is greater than largest uint152).\n     *\n     * Counterpart to Solidity's `uint152` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 152 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint152(uint256 value) internal pure returns (uint152) {\n        require(value \u003c= type(uint152).max, \"SafeCast: value doesn't fit in 152 bits\");\n        return uint152(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint144 from uint256, reverting on\n     * overflow (when the input is greater than largest uint144).\n     *\n     * Counterpart to Solidity's `uint144` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 144 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint144(uint256 value) internal pure returns (uint144) {\n        require(value \u003c= type(uint144).max, \"SafeCast: value doesn't fit in 144 bits\");\n        return uint144(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint136 from uint256, reverting on\n     * overflow (when the input is greater than largest uint136).\n     *\n     * Counterpart to Solidity's `uint136` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 136 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint136(uint256 value) internal pure returns (uint136) {\n        require(value \u003c= type(uint136).max, \"SafeCast: value doesn't fit in 136 bits\");\n        return uint136(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint128 from uint256, reverting on\n     * overflow (when the input is greater than largest uint128).\n     *\n     * Counterpart to Solidity's `uint128` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 128 bits\n     *\n     * _Available since v2.5._\n     */\n    function toUint128(uint256 value) internal pure returns (uint128) {\n        require(value \u003c= type(uint128).max, \"SafeCast: value doesn't fit in 128 bits\");\n        return uint128(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint120 from uint256, reverting on\n     * overflow (when the input is greater than largest uint120).\n     *\n     * Counterpart to Solidity's `uint120` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 120 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint120(uint256 value) internal pure returns (uint120) {\n        require(value \u003c= type(uint120).max, \"SafeCast: value doesn't fit in 120 bits\");\n        return uint120(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint112 from uint256, reverting on\n     * overflow (when the input is greater than largest uint112).\n     *\n     * Counterpart to Solidity's `uint112` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 112 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint112(uint256 value) internal pure returns (uint112) {\n        require(value \u003c= type(uint112).max, \"SafeCast: value doesn't fit in 112 bits\");\n        return uint112(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint104 from uint256, reverting on\n     * overflow (when the input is greater than largest uint104).\n     *\n     * Counterpart to Solidity's `uint104` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 104 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint104(uint256 value) internal pure returns (uint104) {\n        require(value \u003c= type(uint104).max, \"SafeCast: value doesn't fit in 104 bits\");\n        return uint104(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint96 from uint256, reverting on\n     * overflow (when the input is greater than largest uint96).\n     *\n     * Counterpart to Solidity's `uint96` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 96 bits\n     *\n     * _Available since v4.2._\n     */\n    function toUint96(uint256 value) internal pure returns (uint96) {\n        require(value \u003c= type(uint96).max, \"SafeCast: value doesn't fit in 96 bits\");\n        return uint96(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint88 from uint256, reverting on\n     * overflow (when the input is greater than largest uint88).\n     *\n     * Counterpart to Solidity's `uint88` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 88 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint88(uint256 value) internal pure returns (uint88) {\n        require(value \u003c= type(uint88).max, \"SafeCast: value doesn't fit in 88 bits\");\n        return uint88(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint80 from uint256, reverting on\n     * overflow (when the input is greater than largest uint80).\n     *\n     * Counterpart to Solidity's `uint80` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 80 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint80(uint256 value) internal pure returns (uint80) {\n        require(value \u003c= type(uint80).max, \"SafeCast: value doesn't fit in 80 bits\");\n        return uint80(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint72 from uint256, reverting on\n     * overflow (when the input is greater than largest uint72).\n     *\n     * Counterpart to Solidity's `uint72` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 72 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint72(uint256 value) internal pure returns (uint72) {\n        require(value \u003c= type(uint72).max, \"SafeCast: value doesn't fit in 72 bits\");\n        return uint72(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint64 from uint256, reverting on\n     * overflow (when the input is greater than largest uint64).\n     *\n     * Counterpart to Solidity's `uint64` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 64 bits\n     *\n     * _Available since v2.5._\n     */\n    function toUint64(uint256 value) internal pure returns (uint64) {\n        require(value \u003c= type(uint64).max, \"SafeCast: value doesn't fit in 64 bits\");\n        return uint64(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint56 from uint256, reverting on\n     * overflow (when the input is greater than largest uint56).\n     *\n     * Counterpart to Solidity's `uint56` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 56 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint56(uint256 value) internal pure returns (uint56) {\n        require(value \u003c= type(uint56).max, \"SafeCast: value doesn't fit in 56 bits\");\n        return uint56(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint48 from uint256, reverting on\n     * overflow (when the input is greater than largest uint48).\n     *\n     * Counterpart to Solidity's `uint48` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 48 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint48(uint256 value) internal pure returns (uint48) {\n        require(value \u003c= type(uint48).max, \"SafeCast: value doesn't fit in 48 bits\");\n        return uint48(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint40 from uint256, reverting on\n     * overflow (when the input is greater than largest uint40).\n     *\n     * Counterpart to Solidity's `uint40` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 40 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint40(uint256 value) internal pure returns (uint40) {\n        require(value \u003c= type(uint40).max, \"SafeCast: value doesn't fit in 40 bits\");\n        return uint40(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint32 from uint256, reverting on\n     * overflow (when the input is greater than largest uint32).\n     *\n     * Counterpart to Solidity's `uint32` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 32 bits\n     *\n     * _Available since v2.5._\n     */\n    function toUint32(uint256 value) internal pure returns (uint32) {\n        require(value \u003c= type(uint32).max, \"SafeCast: value doesn't fit in 32 bits\");\n        return uint32(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint24 from uint256, reverting on\n     * overflow (when the input is greater than largest uint24).\n     *\n     * Counterpart to Solidity's `uint24` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 24 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint24(uint256 value) internal pure returns (uint24) {\n        require(value \u003c= type(uint24).max, \"SafeCast: value doesn't fit in 24 bits\");\n        return uint24(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint16 from uint256, reverting on\n     * overflow (when the input is greater than largest uint16).\n     *\n     * Counterpart to Solidity's `uint16` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 16 bits\n     *\n     * _Available since v2.5._\n     */\n    function toUint16(uint256 value) internal pure returns (uint16) {\n        require(value \u003c= type(uint16).max, \"SafeCast: value doesn't fit in 16 bits\");\n        return uint16(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint8 from uint256, reverting on\n     * overflow (when the input is greater than largest uint8).\n     *\n     * Counterpart to Solidity's `uint8` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 8 bits\n     *\n     * _Available since v2.5._\n     */\n    function toUint8(uint256 value) internal pure returns (uint8) {\n        require(value \u003c= type(uint8).max, \"SafeCast: value doesn't fit in 8 bits\");\n        return uint8(value);\n    }\n\n    /**\n     * @dev Converts a signed int256 into an unsigned uint256.\n     *\n     * Requirements:\n     *\n     * - input must be greater than or equal to 0.\n     *\n     * _Available since v3.0._\n     */\n    function toUint256(int256 value) internal pure returns (uint256) {\n        require(value \u003e= 0, \"SafeCast: value must be positive\");\n        return uint256(value);\n    }\n\n    /**\n     * @dev Returns the downcasted int248 from int256, reverting on\n     * overflow (when the input is less than smallest int248 or\n     * greater than largest int248).\n     *\n     * Counterpart to Solidity's `int248` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 248 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt248(int256 value) internal pure returns (int248 downcasted) {\n        downcasted = int248(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 248 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int240 from int256, reverting on\n     * overflow (when the input is less than smallest int240 or\n     * greater than largest int240).\n     *\n     * Counterpart to Solidity's `int240` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 240 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt240(int256 value) internal pure returns (int240 downcasted) {\n        downcasted = int240(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 240 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int232 from int256, reverting on\n     * overflow (when the input is less than smallest int232 or\n     * greater than largest int232).\n     *\n     * Counterpart to Solidity's `int232` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 232 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt232(int256 value) internal pure returns (int232 downcasted) {\n        downcasted = int232(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 232 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int224 from int256, reverting on\n     * overflow (when the input is less than smallest int224 or\n     * greater than largest int224).\n     *\n     * Counterpart to Solidity's `int224` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 224 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt224(int256 value) internal pure returns (int224 downcasted) {\n        downcasted = int224(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 224 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int216 from int256, reverting on\n     * overflow (when the input is less than smallest int216 or\n     * greater than largest int216).\n     *\n     * Counterpart to Solidity's `int216` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 216 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt216(int256 value) internal pure returns (int216 downcasted) {\n        downcasted = int216(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 216 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int208 from int256, reverting on\n     * overflow (when the input is less than smallest int208 or\n     * greater than largest int208).\n     *\n     * Counterpart to Solidity's `int208` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 208 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt208(int256 value) internal pure returns (int208 downcasted) {\n        downcasted = int208(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 208 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int200 from int256, reverting on\n     * overflow (when the input is less than smallest int200 or\n     * greater than largest int200).\n     *\n     * Counterpart to Solidity's `int200` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 200 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt200(int256 value) internal pure returns (int200 downcasted) {\n        downcasted = int200(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 200 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int192 from int256, reverting on\n     * overflow (when the input is less than smallest int192 or\n     * greater than largest int192).\n     *\n     * Counterpart to Solidity's `int192` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 192 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt192(int256 value) internal pure returns (int192 downcasted) {\n        downcasted = int192(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 192 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int184 from int256, reverting on\n     * overflow (when the input is less than smallest int184 or\n     * greater than largest int184).\n     *\n     * Counterpart to Solidity's `int184` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 184 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt184(int256 value) internal pure returns (int184 downcasted) {\n        downcasted = int184(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 184 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int176 from int256, reverting on\n     * overflow (when the input is less than smallest int176 or\n     * greater than largest int176).\n     *\n     * Counterpart to Solidity's `int176` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 176 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt176(int256 value) internal pure returns (int176 downcasted) {\n        downcasted = int176(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 176 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int168 from int256, reverting on\n     * overflow (when the input is less than smallest int168 or\n     * greater than largest int168).\n     *\n     * Counterpart to Solidity's `int168` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 168 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt168(int256 value) internal pure returns (int168 downcasted) {\n        downcasted = int168(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 168 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int160 from int256, reverting on\n     * overflow (when the input is less than smallest int160 or\n     * greater than largest int160).\n     *\n     * Counterpart to Solidity's `int160` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 160 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt160(int256 value) internal pure returns (int160 downcasted) {\n        downcasted = int160(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 160 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int152 from int256, reverting on\n     * overflow (when the input is less than smallest int152 or\n     * greater than largest int152).\n     *\n     * Counterpart to Solidity's `int152` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 152 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt152(int256 value) internal pure returns (int152 downcasted) {\n        downcasted = int152(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 152 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int144 from int256, reverting on\n     * overflow (when the input is less than smallest int144 or\n     * greater than largest int144).\n     *\n     * Counterpart to Solidity's `int144` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 144 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt144(int256 value) internal pure returns (int144 downcasted) {\n        downcasted = int144(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 144 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int136 from int256, reverting on\n     * overflow (when the input is less than smallest int136 or\n     * greater than largest int136).\n     *\n     * Counterpart to Solidity's `int136` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 136 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt136(int256 value) internal pure returns (int136 downcasted) {\n        downcasted = int136(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 136 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int128 from int256, reverting on\n     * overflow (when the input is less than smallest int128 or\n     * greater than largest int128).\n     *\n     * Counterpart to Solidity's `int128` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 128 bits\n     *\n     * _Available since v3.1._\n     */\n    function toInt128(int256 value) internal pure returns (int128 downcasted) {\n        downcasted = int128(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 128 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int120 from int256, reverting on\n     * overflow (when the input is less than smallest int120 or\n     * greater than largest int120).\n     *\n     * Counterpart to Solidity's `int120` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 120 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt120(int256 value) internal pure returns (int120 downcasted) {\n        downcasted = int120(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 120 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int112 from int256, reverting on\n     * overflow (when the input is less than smallest int112 or\n     * greater than largest int112).\n     *\n     * Counterpart to Solidity's `int112` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 112 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt112(int256 value) internal pure returns (int112 downcasted) {\n        downcasted = int112(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 112 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int104 from int256, reverting on\n     * overflow (when the input is less than smallest int104 or\n     * greater than largest int104).\n     *\n     * Counterpart to Solidity's `int104` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 104 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt104(int256 value) internal pure returns (int104 downcasted) {\n        downcasted = int104(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 104 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int96 from int256, reverting on\n     * overflow (when the input is less than smallest int96 or\n     * greater than largest int96).\n     *\n     * Counterpart to Solidity's `int96` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 96 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt96(int256 value) internal pure returns (int96 downcasted) {\n        downcasted = int96(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 96 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int88 from int256, reverting on\n     * overflow (when the input is less than smallest int88 or\n     * greater than largest int88).\n     *\n     * Counterpart to Solidity's `int88` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 88 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt88(int256 value) internal pure returns (int88 downcasted) {\n        downcasted = int88(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 88 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int80 from int256, reverting on\n     * overflow (when the input is less than smallest int80 or\n     * greater than largest int80).\n     *\n     * Counterpart to Solidity's `int80` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 80 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt80(int256 value) internal pure returns (int80 downcasted) {\n        downcasted = int80(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 80 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int72 from int256, reverting on\n     * overflow (when the input is less than smallest int72 or\n     * greater than largest int72).\n     *\n     * Counterpart to Solidity's `int72` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 72 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt72(int256 value) internal pure returns (int72 downcasted) {\n        downcasted = int72(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 72 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int64 from int256, reverting on\n     * overflow (when the input is less than smallest int64 or\n     * greater than largest int64).\n     *\n     * Counterpart to Solidity's `int64` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 64 bits\n     *\n     * _Available since v3.1._\n     */\n    function toInt64(int256 value) internal pure returns (int64 downcasted) {\n        downcasted = int64(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 64 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int56 from int256, reverting on\n     * overflow (when the input is less than smallest int56 or\n     * greater than largest int56).\n     *\n     * Counterpart to Solidity's `int56` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 56 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt56(int256 value) internal pure returns (int56 downcasted) {\n        downcasted = int56(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 56 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int48 from int256, reverting on\n     * overflow (when the input is less than smallest int48 or\n     * greater than largest int48).\n     *\n     * Counterpart to Solidity's `int48` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 48 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt48(int256 value) internal pure returns (int48 downcasted) {\n        downcasted = int48(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 48 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int40 from int256, reverting on\n     * overflow (when the input is less than smallest int40 or\n     * greater than largest int40).\n     *\n     * Counterpart to Solidity's `int40` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 40 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt40(int256 value) internal pure returns (int40 downcasted) {\n        downcasted = int40(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 40 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int32 from int256, reverting on\n     * overflow (when the input is less than smallest int32 or\n     * greater than largest int32).\n     *\n     * Counterpart to Solidity's `int32` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 32 bits\n     *\n     * _Available since v3.1._\n     */\n    function toInt32(int256 value) internal pure returns (int32 downcasted) {\n        downcasted = int32(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 32 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int24 from int256, reverting on\n     * overflow (when the input is less than smallest int24 or\n     * greater than largest int24).\n     *\n     * Counterpart to Solidity's `int24` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 24 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt24(int256 value) internal pure returns (int24 downcasted) {\n        downcasted = int24(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 24 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int16 from int256, reverting on\n     * overflow (when the input is less than smallest int16 or\n     * greater than largest int16).\n     *\n     * Counterpart to Solidity's `int16` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 16 bits\n     *\n     * _Available since v3.1._\n     */\n    function toInt16(int256 value) internal pure returns (int16 downcasted) {\n        downcasted = int16(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 16 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int8 from int256, reverting on\n     * overflow (when the input is less than smallest int8 or\n     * greater than largest int8).\n     *\n     * Counterpart to Solidity's `int8` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 8 bits\n     *\n     * _Available since v3.1._\n     */\n    function toInt8(int256 value) internal pure returns (int8 downcasted) {\n        downcasted = int8(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 8 bits\");\n    }\n\n    /**\n     * @dev Converts an unsigned uint256 into a signed int256.\n     *\n     * Requirements:\n     *\n     * - input must be less than or equal to maxInt256.\n     *\n     * _Available since v3.0._\n     */\n    function toInt256(uint256 value) internal pure returns (int256) {\n        // Note: Unsafe cast below is okay because `type(int256).max` is guaranteed to be positive\n        require(value \u003c= uint256(type(int256).max), \"SafeCast: value doesn't fit in an int256\");\n        return int256(value);\n    }\n}\n\n// 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/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// contracts/libs/memory/BaseMessage.sol\n\n/// BaseMessage is a memory view over the base message supported by Origin-Destination\ntype BaseMessage is uint256;\n\nusing BaseMessageLib for BaseMessage global;\n\n/// BaseMessage structure represents a base message sent via the Origin-Destination contracts.\n/// - It only contains data relevant to the base message, the rest of data is encoded in the message header.\n/// - `sender` and `recipient` for EVM chains are EVM addresses casted to bytes32, while preserving left-alignment.\n/// - `tips` and `request` parameters are specified by a message sender\n/// \u003e Origin will calculate minimum tips for given request and content length, and will reject messages with tips\n/// lower than that.\n///\n/// # Memory layout of BaseMessage fields\n///\n/// | Position   | Field     | Type    | Bytes | Description                            |\n/// | ---------- | --------- | ------- | ----- | -------------------------------------- |\n/// | [000..032) | tips      | uint256 | 32    | Encoded tips paid on origin chain      |\n/// | [032..064) | sender    | bytes32 | 32    | Sender address on origin chain         |\n/// | [064..096) | recipient | bytes32 | 32    | Recipient address on destination chain |\n/// | [096..116) | request   | uint160 | 20    | Encoded request for message execution  |\n/// | [104..AAA) | content   | bytes   | ??    | Content to be passed to recipient      |\nlibrary BaseMessageLib {\n    using MemViewLib for bytes;\n\n    /// @dev The variables below are not supposed to be used outside of the library directly.\n    uint256 private constant OFFSET_TIPS = 0;\n    uint256 private constant OFFSET_SENDER = 32;\n    uint256 private constant OFFSET_RECIPIENT = 64;\n    uint256 private constant OFFSET_REQUEST = OFFSET_RECIPIENT + TIPS_LENGTH;\n    uint256 private constant OFFSET_CONTENT = OFFSET_REQUEST + REQUEST_LENGTH;\n\n    // ═══════════════════════════════════════════════ BASE MESSAGE ════════════════════════════════════════════════════\n\n    /**\n     * @notice Returns a formatted BaseMessage payload with provided fields.\n     * @param tips_         Encoded tips information\n     * @param sender_       Sender address on origin chain\n     * @param recipient_    Recipient address on destination chain\n     * @param request_      Encoded request for message execution\n     * @param content_      Raw content to be passed to recipient on destination chain\n     * @return Formatted base message\n     */\n    function formatBaseMessage(Tips tips_, bytes32 sender_, bytes32 recipient_, Request request_, bytes memory content_)\n        internal\n        pure\n        returns (bytes memory)\n    {\n        return abi.encodePacked(tips_, sender_, recipient_, request_, content_);\n    }\n\n    /**\n     * @notice Returns a BaseMessage view over the given payload.\n     * @dev Will revert if the payload is not a base message.\n     */\n    function castToBaseMessage(bytes memory payload) internal pure returns (BaseMessage) {\n        return castToBaseMessage(payload.ref());\n    }\n\n    /**\n     * @notice Casts a memory view to a BaseMessage view.\n     * @dev Will revert if the memory view is not over a base message payload.\n     */\n    function castToBaseMessage(MemView memView) internal pure returns (BaseMessage) {\n        if (!isBaseMessage(memView)) revert UnformattedBaseMessage();\n        return BaseMessage.wrap(MemView.unwrap(memView));\n    }\n\n    /// @notice Checks that a payload is a formatted BaseMessage.\n    function isBaseMessage(MemView memView) internal pure returns (bool) {\n        // Check if sender, recipient, tips fields exist\n        return (memView.len() \u003e= OFFSET_CONTENT);\n        // Content could be empty, so we don't check that\n    }\n\n    /// @notice Convenience shortcut for unwrapping a view.\n    function unwrap(BaseMessage baseMessage) internal pure returns (MemView) {\n        return MemView.wrap(BaseMessage.unwrap(baseMessage));\n    }\n\n    /// @notice Returns baseMessage's hash: a leaf to be inserted in the \"Message mini-Merkle tree\".\n    function leaf(BaseMessage baseMessage) internal pure returns (bytes32) {\n        // We hash \"tips\" and \"everything but tips\" to make tips proofs easier to verify\n        return MerkleMath.getParent(baseMessage.tips().leaf(), baseMessage.bodyLeaf());\n    }\n\n    /// @notice Returns hash for the \"everything but tips\" part of the base message.\n    function bodyLeaf(BaseMessage baseMessage) internal pure returns (bytes32) {\n        return baseMessage.unwrap().sliceFrom({index_: OFFSET_SENDER}).keccak();\n    }\n\n    // ═══════════════════════════════════════════ BASE MESSAGE SLICING ════════════════════════════════════════════════\n\n    /// @notice Returns encoded tips paid on origin chain.\n    function tips(BaseMessage baseMessage) internal pure returns (Tips) {\n        return TipsLib.wrapPadded((baseMessage.unwrap().indexUint({index_: OFFSET_TIPS, bytes_: TIPS_LENGTH})));\n    }\n\n    /// @notice Returns sender address on origin chain.\n    function sender(BaseMessage baseMessage) internal pure returns (bytes32) {\n        return baseMessage.unwrap().index({index_: OFFSET_SENDER, bytes_: 32});\n    }\n\n    /// @notice Returns recipient address on destination chain.\n    function recipient(BaseMessage baseMessage) internal pure returns (bytes32) {\n        return baseMessage.unwrap().index({index_: OFFSET_RECIPIENT, bytes_: 32});\n    }\n\n    /// @notice Returns an encoded request for message execution on destination chain.\n    function request(BaseMessage baseMessage) internal pure returns (Request) {\n        return RequestLib.wrapPadded((baseMessage.unwrap().indexUint({index_: OFFSET_REQUEST, bytes_: REQUEST_LENGTH})));\n    }\n\n    /// @notice Returns an untyped memory view over the content to be passed to recipient.\n    function content(BaseMessage baseMessage) internal pure returns (MemView) {\n        return baseMessage.unwrap().sliceFrom({index_: OFFSET_CONTENT});\n    }\n}\n\n// test/harnesses/libs/memory/BaseMessageHarness.t.sol\n\n// solhint-disable ordering\n/**\n * @notice Exposes BaseMessage methods for testing against golang.\n */\ncontract BaseMessageHarness {\n    using BaseMessageLib for bytes;\n    using BaseMessageLib for MemView;\n    using MemViewLib for bytes;\n\n    // Note: we don't add an empty test() function here, as it currently leads\n    // to zero coverage on the corresponding library.\n\n    // ══════════════════════════════════════════════════ GETTERS ══════════════════════════════════════════════════════\n\n    function castToBaseMessage(bytes memory payload) public view returns (bytes memory) {\n        // Walkaround to get the forge coverage working on libraries, see\n        // https://github.com/foundry-rs/foundry/pull/3128#issuecomment-1241245086\n        BaseMessage baseMessage = BaseMessageLib.castToBaseMessage(payload);\n        return baseMessage.unwrap().clone();\n    }\n\n    /// @notice Returns baseMessage's sender field\n    function sender(bytes memory payload) public pure returns (bytes32) {\n        return payload.castToBaseMessage().sender();\n    }\n\n    /// @notice Returns baseMessage's recipient field as bytes32\n    function recipient(bytes memory payload) public pure returns (bytes32) {\n        return payload.castToBaseMessage().recipient();\n    }\n\n    /// @notice Returns baseMessage's tips field\n    function tips(bytes memory payload) public pure returns (uint256) {\n        return Tips.unwrap(payload.castToBaseMessage().tips());\n    }\n\n    /// @notice Returns baseMessage's request field\n    function request(bytes memory payload) public pure returns (uint192) {\n        return Request.unwrap(payload.castToBaseMessage().request());\n    }\n\n    /// @notice Returns baseMessage's content field\n    function content(bytes memory payload) public view returns (bytes memory) {\n        return payload.castToBaseMessage().content().clone();\n    }\n\n    function isBaseMessage(bytes memory payload) public pure returns (bool) {\n        return payload.ref().isBaseMessage();\n    }\n\n    // ════════════════════════════════════════════════ FORMATTERS ═════════════════════════════════════════════════════\n\n    function formatBaseMessage(Tips tips_, bytes32 sender_, bytes32 recipient_, Request request_, bytes memory content_)\n        public\n        pure\n        returns (bytes memory)\n    {\n        return BaseMessageLib.formatBaseMessage(tips_, sender_, recipient_, request_, content_);\n    }\n\n    function leaf(bytes memory payload) public pure returns (bytes32) {\n        return payload.castToBaseMessage().leaf();\n    }\n\n    function bodyLeaf(bytes memory payload) public pure returns (bytes32) {\n        return payload.castToBaseMessage().bodyLeaf();\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":"93500:2977:0:-:0;;;;;;;;;;;;;;;;;;;","srcMapRuntime":"93500:2977:0:-:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;94920:137;;;;;;:::i;:::-;;:::i;:::-;;;1456:25:1;;;1444:2;1429:18;94920:137:0;;;;;;;;95319:143;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;95468:125::-;;;;;;:::i;:::-;;:::i;:::-;;;2370:14:1;;2363:22;2345:41;;2333:2;2318:18;95468:125:0;2205:187:1;95923:284:0;;;;;;:::i;:::-;;:::i;94105:370::-;;;;;;:::i;:::-;;:::i;94532:128::-;;;;;;:::i;:::-;;:::i;96343:132::-;;;;;;:::i;:::-;;:::i;94731:134::-;;;;;;:::i;:::-;;:::i;95115:146::-;;;;;;:::i;:::-;;:::i;:::-;;;3543:50:1;3531:63;;;3513:82;;3501:2;3486:18;95115:146:0;3367:234:1;96213:124:0;;;;;;:::i;:::-;;:::i;94920:137::-;94977:7;95015:34;:27;:7;:25;:27::i;:::-;:32;:34::i;:::-;94996:54;94920:137;-1:-1:-1;;94920:137:0:o;95319:143::-;95379:12;95410:45;:37;:27;:7;:25;:27::i;:::-;:35;:37::i;:::-;:43;:45::i;95468:125::-;95534:4;95557:29;:13;:7;:11;:13::i;:::-;:27;:29::i;95923:284::-;96085:12;96120:80;96153:5;96160:7;96169:10;96181:8;96191;96120:32;:80::i;:::-;96113:87;95923:284;-1:-1:-1;;;;;;95923:284:0:o;94105:370::-;94175:12;94356:23;94382:41;94415:7;94382:32;:41::i;:::-;94356:67;-1:-1:-1;94440:28:0;94356:67;95410:43;:45::i;94440:28::-;94433:35;94105:370;-1:-1:-1;;;94105:370:0:o;94532:128::-;94591:7;94617:36;:27;:7;:25;:27::i;:::-;:34;:36::i;96343:132::-;96404:7;96430:38;:27;:7;:25;:27::i;:::-;:36;:38::i;94731:134::-;94793:7;94819:39;:27;:7;:25;:27::i;:::-;:37;:39::i;95115:146::-;95175:7;95216:37;:27;:7;:25;:27::i;:::-;:35;:37::i;96213:124::-;96270:7;96296:34;:27;:7;:25;:27::i;:::-;:32;:34::i;90123:141::-;90195:11;90225:32;90243:13;:7;:11;:13::i;:::-;90225:17;:32::i;92144:188::-;92206:4;92229:96;92249:74;92206:4;2134:2;92249:11;:20;:30;:74;:30;:74::i;:::-;91139:11;91017:142;93183:154;93248:7;93274:56;2037:2;88804:30;2134:2;88754;88804:30;:::i;:::-;88882:31;;;;:::i;:::-;93274:11;:20;:30;;:56::i;51557:1041::-;51803:4;51797:11;;51933:34;51947:7;51962:4;51956:10;;51933:13;:34::i;:::-;-1:-1:-1;54743:17:0;54717:43;;52179:12;55575:2;55559:18;;55943:20;;52475;;52497:4;52471:31;52465:4;52458:45;-1:-1:-1;52565:17:0;;51557:1041;;-1:-1:-1;51557:1041:0:o;50450:569::-;50538:10;;50504:7;;50964:4;50955:14;;50995:17;50955:14;50538:10;50995:5;:17::i;:::-;50988:24;50450:569;-1:-1:-1;;;;50450:569:0:o;90710:241::-;90773:4;2037:2;88804:30;2134:2;88754;88804:30;:::i;:::-;88882:31;;;;:::i;:::-;54743:17;54717:43;;90854:31;;;90710:241;-1:-1:-1;;90710:241:0:o;89703:270::-;89867:12;89919:5;89926:7;89935:10;89947:8;89957;89902:64;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;89895:71;;89703:270;;;;;;;:::o;92394:160::-;92458:7;92484:63;88702:2;;92484:11;:20;:26;:63;:26;:63::i;91612:163::-;91678:7;91704:64;:55;88702:2;91704:11;:20;91017:142;91704:55;:62;:64::i;92624:166::-;92691:7;92717:66;88754:2;92779;92717:11;:20;91017:142;92883:203;92948:7;92974:105;92997:80;88804:30;2134:2;88754;88804:30;:::i;:::-;2037:2;92997:11;:20;91017:142;91266:255;91328:7;91443:71;91464:25;:18;:11;:16;:18::i;:::-;83686;83838:15;;;83948:2;83935:16;;;83638:329;91464:25;91491:22;:11;:20;:22::i;:::-;91443:20;:71::i;90423:215::-;90490:11;90518:22;90532:7;90518:13;:22::i;:::-;90513:60;;90549:24;;;;;;;;;;;;;;90513:60;-1:-1:-1;90622:7:0;90423:215::o;63030:538::-;63121:7;;63163:29;:7;63177:6;63185;63163:13;:29::i;:::-;63533:2;:11;;;63549:1;63532:18;63506:45;;-1:-1:-1;;63030:538:0;;;;;:::o;58604:529::-;58679:7;54743:17;54717:43;;58786:13;;;58782:64;;;58822:13;;;;;;;;;;;;;;58782:64;59058:58;59087:6;59071:13;:7;54376:3;54349:30;;54190:196;59071:13;:22;59108:6;59101:4;:13;59058:5;:58::i;65491:842::-;65830:4;65824:11;65569:7;;54743:17;54717:43;;;54376:3;54349:30;;;;65912:12;;;65908:66;;;65947:16;;;;;;;;;;;;;;65908:66;65983:8;66199:4;66191:6;66185:4;66177:6;66171:4;66164:5;66153:51;66146:58;;66228:3;66223:37;;66240:20;;;;;;;;;;;;;;66223:37;64840:3;64832:11;;;64831:20;;66270:56;65491:842;-1:-1:-1;;;;;;;65491:842:0:o;49570:540::-;49636:7;;49670:11;49677:4;49670;:11;:::i;:::-;49655:26;;49949:4;49943:11;49937:4;49934:21;49931:38;;;-1:-1:-1;49966:1:0;49931:38;49992:4;50000:1;49992:9;49988:66;;50024:19;;;;;;;;;;;;;;49988:66;64840:3;64832:11;;;64831:20;;50070:33;64507:352;61338:1334;61425:14;61455:6;61465:1;61455:11;61451:59;;-1:-1:-1;61497:1:0;61482:17;;61451:59;61596:2;61587:6;:11;61583:65;;;61621:16;;;;;;;;;;;;;;61583:65;54743:17;54717:43;;61727:15;61736:6;61727;:15;:::i;:::-;:31;61723:82;;;61781:13;;;;;;;;;;;;;;61723:82;61844:1;61834:11;;;61814:17;61884:13;:7;54376:3;54349:30;;54190:196;61884:13;62631:17;;;62625:24;62342:66;62323:17;;;;;62319:90;;;;62621:35;;61338:1334;-1:-1:-1;;;;61338:1334:0:o;56481:292::-;56537:14;56563:12;56578:13;:7;54376:3;54349:30;;54190:196;56578:13;54743:17;54717:43;;;;56736:21;;;;;-1:-1:-1;;56481:292:0:o;70925:287::-;71006:14;71036:23;;:51;;;;-1:-1:-1;71063:24:0;;71036:51;71032:174;;;-1:-1:-1;71110:1:0;71103:8;;71032:174;71159:35;;;;;;4742:19:1;;;4777:12;;;4770:28;;;4814:12;;71159:35:0;;;;;;;;;;;;71149:46;;;;;;71142:53;;;;14:184:1;66:77;63:1;56:88;163:4;160:1;153:15;187:4;184:1;177:15;203:777;245:5;298:3;291:4;283:6;279:17;275:27;265:55;;316:1;313;306:12;265:55;352:6;339:20;378:18;415:2;411;408:10;405:36;;;421:18;;:::i;:::-;555:2;549:9;617:4;609:13;;460:66;605:22;;;629:2;601:31;597:40;585:53;;;653:18;;;673:22;;;650:46;647:72;;;699:18;;:::i;:::-;739:10;735:2;728:22;774:2;766:6;759:18;820:3;813:4;808:2;800:6;796:15;792:26;789:35;786:55;;;837:1;834;827:12;786:55;901:2;894:4;886:6;882:17;875:4;867:6;863:17;850:54;948:1;941:4;936:2;928:6;924:15;920:26;913:37;968:6;959:15;;;;;;203:777;;;;:::o;985:320::-;1053:6;1106:2;1094:9;1085:7;1081:23;1077:32;1074:52;;;1122:1;1119;1112:12;1074:52;1162:9;1149:23;1195:18;1187:6;1184:30;1181:50;;;1227:1;1224;1217:12;1181:50;1250:49;1291:7;1282:6;1271:9;1267:22;1250:49;:::i;1492:250::-;1577:1;1587:113;1601:6;1598:1;1595:13;1587:113;;;1677:11;;;1671:18;1658:11;;;1651:39;1623:2;1616:10;1587:113;;;-1:-1:-1;;1734:1:1;1716:16;;1709:27;1492:250::o;1747:453::-;1894:2;1883:9;1876:21;1857:4;1926:6;1920:13;1969:6;1964:2;1953:9;1949:18;1942:34;1985:79;2057:6;2052:2;2041:9;2037:18;2032:2;2024:6;2020:15;1985:79;:::i;:::-;2116:2;2104:15;2121:66;2100:88;2085:104;;;;2191:2;2081:113;;1747:453;-1:-1:-1;;1747:453:1:o;2397:783::-;2553:6;2561;2569;2577;2585;2638:3;2626:9;2617:7;2613:23;2609:33;2606:53;;;2655:1;2652;2645:12;2606:53;2691:9;2678:23;2668:33;;2748:2;2737:9;2733:18;2720:32;2710:42;;2799:2;2788:9;2784:18;2771:32;2761:42;;2853:2;2842:9;2838:18;2825:32;2897:50;2890:5;2886:62;2879:5;2876:73;2866:101;;2963:1;2960;2953:12;2866:101;2986:5;-1:-1:-1;3042:3:1;3027:19;;3014:33;3070:18;3059:30;;3056:50;;;3102:1;3099;3092:12;3056:50;3125:49;3166:7;3157:6;3146:9;3142:22;3125:49;:::i;:::-;3115:59;;;2397:783;;;;;;;;:::o;3606:279::-;3671:9;;;3692:10;;;3689:190;;;3735:77;3732:1;3725:88;3836:4;3833:1;3826:15;3864:4;3861:1;3854:15;3890:690;4213:6;4208:3;4201:19;4250:6;4245:2;4240:3;4236:12;4229:28;4287:6;4282:2;4277:3;4273:12;4266:28;4345:66;4336:6;4332:2;4328:15;4324:88;4319:2;4314:3;4310:12;4303:110;4183:3;4442:6;4436:13;4458:74;4525:6;4519:3;4514;4510:13;4505:2;4497:6;4493:15;4458:74;:::i;:::-;4552:16;;;;4570:3;4548:26;;3890:690;-1:-1:-1;;;;;;3890:690:1:o","abiDefinition":[{"inputs":[],"name":"IndexedTooMuch","type":"error"},{"inputs":[],"name":"OccupiedMemory","type":"error"},{"inputs":[],"name":"PrecompileOutOfGas","type":"error"},{"inputs":[],"name":"UnallocatedMemory","type":"error"},{"inputs":[],"name":"UnformattedBaseMessage","type":"error"},{"inputs":[],"name":"ViewOverrun","type":"error"},{"inputs":[{"internalType":"bytes","name":"payload","type":"bytes"}],"name":"bodyLeaf","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"bytes","name":"payload","type":"bytes"}],"name":"castToBaseMessage","outputs":[{"internalType":"bytes","name":"","type":"bytes"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes","name":"payload","type":"bytes"}],"name":"content","outputs":[{"internalType":"bytes","name":"","type":"bytes"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"Tips","name":"tips_","type":"uint256"},{"internalType":"bytes32","name":"sender_","type":"bytes32"},{"internalType":"bytes32","name":"recipient_","type":"bytes32"},{"internalType":"Request","name":"request_","type":"uint192"},{"internalType":"bytes","name":"content_","type":"bytes"}],"name":"formatBaseMessage","outputs":[{"internalType":"bytes","name":"","type":"bytes"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"bytes","name":"payload","type":"bytes"}],"name":"isBaseMessage","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"bytes","name":"payload","type":"bytes"}],"name":"leaf","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"bytes","name":"payload","type":"bytes"}],"name":"recipient","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"bytes","name":"payload","type":"bytes"}],"name":"request","outputs":[{"internalType":"uint192","name":"","type":"uint192"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"bytes","name":"payload","type":"bytes"}],"name":"sender","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"bytes","name":"payload","type":"bytes"}],"name":"tips","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"pure","type":"function"}],"userDoc":{"kind":"user","methods":{"content(bytes)":{"notice":"Returns baseMessage's content field"},"recipient(bytes)":{"notice":"Returns baseMessage's recipient field as bytes32"},"request(bytes)":{"notice":"Returns baseMessage's request field"},"sender(bytes)":{"notice":"Returns baseMessage's sender field"},"tips(bytes)":{"notice":"Returns baseMessage's tips field"}},"notice":"Exposes BaseMessage methods for testing against golang.","version":1},"developerDoc":{"kind":"dev","methods":{},"version":1},"metadata":"{\"compiler\":{\"version\":\"0.8.17+commit.8df45f5f\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[],\"name\":\"IndexedTooMuch\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OccupiedMemory\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"PrecompileOutOfGas\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"UnallocatedMemory\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"UnformattedBaseMessage\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ViewOverrun\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"payload\",\"type\":\"bytes\"}],\"name\":\"bodyLeaf\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"payload\",\"type\":\"bytes\"}],\"name\":\"castToBaseMessage\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"payload\",\"type\":\"bytes\"}],\"name\":\"content\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"Tips\",\"name\":\"tips_\",\"type\":\"uint256\"},{\"internalType\":\"bytes32\",\"name\":\"sender_\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"recipient_\",\"type\":\"bytes32\"},{\"internalType\":\"Request\",\"name\":\"request_\",\"type\":\"uint192\"},{\"internalType\":\"bytes\",\"name\":\"content_\",\"type\":\"bytes\"}],\"name\":\"formatBaseMessage\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"payload\",\"type\":\"bytes\"}],\"name\":\"isBaseMessage\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"payload\",\"type\":\"bytes\"}],\"name\":\"leaf\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"payload\",\"type\":\"bytes\"}],\"name\":\"recipient\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"payload\",\"type\":\"bytes\"}],\"name\":\"request\",\"outputs\":[{\"internalType\":\"uint192\",\"name\":\"\",\"type\":\"uint192\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"payload\",\"type\":\"bytes\"}],\"name\":\"sender\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"payload\",\"type\":\"bytes\"}],\"name\":\"tips\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"pure\",\"type\":\"function\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{\"content(bytes)\":{\"notice\":\"Returns baseMessage's content field\"},\"recipient(bytes)\":{\"notice\":\"Returns baseMessage's recipient field as bytes32\"},\"request(bytes)\":{\"notice\":\"Returns baseMessage's request field\"},\"sender(bytes)\":{\"notice\":\"Returns baseMessage's sender field\"},\"tips(bytes)\":{\"notice\":\"Returns baseMessage's tips field\"}},\"notice\":\"Exposes BaseMessage methods for testing against golang.\",\"version\":1}},\"settings\":{\"compilationTarget\":{\"solidity/BaseMessageHarness.t.sol\":\"BaseMessageHarness\"},\"evmVersion\":\"london\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\"},\"optimizer\":{\"enabled\":true,\"runs\":10000},\"remappings\":[]},\"sources\":{\"solidity/BaseMessageHarness.t.sol\":{\"keccak256\":\"0x0b644d75605ac5a83f42b70984b4f8c78046e7756cf276e43df1e1f8c1c57ce6\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://89e64be85f0b7caad7e5d5fe0d77b92bb4c97bf9542651212fb3563a019d5bac\",\"dweb:/ipfs/QmVsD4QYYzmJVCjC85GjGjbY2Jooz9rZHSJmvp4hkWxxbR\"]}},\"version\":1}"},"hashes":{"bodyLeaf(bytes)":"949b7cee","castToBaseMessage(bytes)":"5013fc9f","content(bytes)":"07755381","formatBaseMessage(uint256,bytes32,bytes32,uint192,bytes)":"311bc6c8","isBaseMessage(bytes)":"27f8d97f","leaf(bytes)":"d7a7a72c","recipient(bytes)":"985a5c31","request(bytes)":"b94207d3","sender(bytes)":"6dc3c4f7","tips(bytes)":"045c6c0b"}},"solidity/BaseMessageHarness.t.sol:BaseMessageLib":{"code":"0x60566037600b82828239805160001a607314602a57634e487b7160e01b600052600060045260246000fd5b30600052607381538281f3fe73000000000000000000000000000000000000000030146080604052600080fdfea2646970667358221220048a89d9489d2ccdb78b132f06266841a7161a73b009ec37d5fb12d082e8926364736f6c63430008110033","runtime-code":"0x73000000000000000000000000000000000000000030146080604052600080fdfea2646970667358221220048a89d9489d2ccdb78b132f06266841a7161a73b009ec37d5fb12d082e8926364736f6c63430008110033","info":{"source":"// SPDX-License-Identifier: MIT\npragma solidity =0.8.17 ^0.8.0;\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/Request.sol\n\n/// Request is encoded data with \"message execution request\".\ntype Request is uint192;\n\nusing RequestLib for Request global;\n\n/// Library for formatting _the request part_ of _the base messages_.\n/// - Request represents a message sender requirements for the message execution on the destination chain.\n/// - Request occupies a single storage word, and thus is stored on stack instead of being stored in memory.\n/// \u003e gasDrop field is included for future compatibility and is ignored at the moment.\n///\n/// # Request stack layout (from highest bits to lowest)\n///\n/// | Position   | Field    | Type   | Bytes | Description                                          |\n/// | ---------- | -------- | ------ | ----- | ---------------------------------------------------- |\n/// | (024..012] | gasDrop  | uint96 | 12    | Minimum amount of gas token to drop to the recipient |\n/// | (012..004] | gasLimit | uint64 | 8     | Minimum amount of gas units to supply for execution  |\n/// | (004..000] | version  | uint32 | 4     | Base message version to pass to the recipient        |\n\nlibrary RequestLib {\n    /// @dev Amount of bits to shift to gasDrop field\n    uint192 private constant SHIFT_GAS_DROP = 12 * 8;\n    /// @dev Amount of bits to shift to gasLimit field\n    uint192 private constant SHIFT_GAS_LIMIT = 4 * 8;\n\n    /// @notice Returns an encoded request with the given fields\n    /// @param gasDrop_     Minimum amount of gas token to drop to the recipient (ignored at the moment)\n    /// @param gasLimit_    Minimum amount of gas units to supply for execution\n    /// @param version_     Base message version to pass to the recipient\n    function encodeRequest(uint96 gasDrop_, uint64 gasLimit_, uint32 version_) internal pure returns (Request) {\n        // Casts below are upcasts, so they are safe\n        return Request.wrap(uint192(gasDrop_) \u003c\u003c SHIFT_GAS_DROP | uint192(gasLimit_) \u003c\u003c SHIFT_GAS_LIMIT | version_);\n    }\n\n    /// @notice Wraps the padded encoded request into a Request-typed value.\n    /// @dev The \"padded\" request is simply an encoded request casted to uint256 (highest bits are set to zero).\n    /// Casting to uint256 is done automatically in Solidity, so no extra actions from consumers are needed.\n    /// The highest bits are discarded, so that the contracts dealing with encoded requests\n    /// don't need to be updated, if a new field is added.\n    function wrapPadded(uint256 paddedRequest) internal pure returns (Request) {\n        // Casting to uint192 will truncate the highest bits, which is the behavior we want\n        return Request.wrap(uint192(paddedRequest));\n    }\n\n    /// @notice Returns the requested of gas token to drop to the recipient.\n    function gasDrop(Request request) internal pure returns (uint96) {\n        // Casting to uint96 will truncate the highest bits, which is the behavior we want\n        return uint96(Request.unwrap(request) \u003e\u003e SHIFT_GAS_DROP);\n    }\n\n    /// @notice Returns the requested minimum amount of gas units to supply for execution.\n    function gasLimit(Request request) internal pure returns (uint64) {\n        // Casting to uint64 will truncate the highest bits, which is the behavior we want\n        return uint64(Request.unwrap(request) \u003e\u003e SHIFT_GAS_LIMIT);\n    }\n\n    /// @notice Returns the requested base message version to pass to the recipient.\n    function version(Request request) internal pure returns (uint32) {\n        // Casting to uint32 will truncate the highest bits, which is the behavior we want\n        return uint32(Request.unwrap(request));\n    }\n}\n\n// node_modules/@openzeppelin/contracts/utils/math/SafeCast.sol\n\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/math/SafeCast.sol)\n// This file was procedurally generated from scripts/generate/templates/SafeCast.js.\n\n/**\n * @dev Wrappers over Solidity's uintXX/intXX casting operators with added overflow\n * checks.\n *\n * Downcasting from uint256/int256 in Solidity does not revert on overflow. This can\n * easily result in undesired exploitation or bugs, since developers usually\n * assume that overflows raise errors. `SafeCast` restores this intuition by\n * reverting the transaction when such an operation overflows.\n *\n * Using this library instead of the unchecked operations eliminates an entire\n * class of bugs, so it's recommended to use it always.\n *\n * Can be combined with {SafeMath} and {SignedSafeMath} to extend it to smaller types, by performing\n * all math on `uint256` and `int256` and then downcasting.\n */\nlibrary SafeCast {\n    /**\n     * @dev Returns the downcasted uint248 from uint256, reverting on\n     * overflow (when the input is greater than largest uint248).\n     *\n     * Counterpart to Solidity's `uint248` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 248 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint248(uint256 value) internal pure returns (uint248) {\n        require(value \u003c= type(uint248).max, \"SafeCast: value doesn't fit in 248 bits\");\n        return uint248(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint240 from uint256, reverting on\n     * overflow (when the input is greater than largest uint240).\n     *\n     * Counterpart to Solidity's `uint240` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 240 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint240(uint256 value) internal pure returns (uint240) {\n        require(value \u003c= type(uint240).max, \"SafeCast: value doesn't fit in 240 bits\");\n        return uint240(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint232 from uint256, reverting on\n     * overflow (when the input is greater than largest uint232).\n     *\n     * Counterpart to Solidity's `uint232` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 232 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint232(uint256 value) internal pure returns (uint232) {\n        require(value \u003c= type(uint232).max, \"SafeCast: value doesn't fit in 232 bits\");\n        return uint232(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint224 from uint256, reverting on\n     * overflow (when the input is greater than largest uint224).\n     *\n     * Counterpart to Solidity's `uint224` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 224 bits\n     *\n     * _Available since v4.2._\n     */\n    function toUint224(uint256 value) internal pure returns (uint224) {\n        require(value \u003c= type(uint224).max, \"SafeCast: value doesn't fit in 224 bits\");\n        return uint224(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint216 from uint256, reverting on\n     * overflow (when the input is greater than largest uint216).\n     *\n     * Counterpart to Solidity's `uint216` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 216 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint216(uint256 value) internal pure returns (uint216) {\n        require(value \u003c= type(uint216).max, \"SafeCast: value doesn't fit in 216 bits\");\n        return uint216(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint208 from uint256, reverting on\n     * overflow (when the input is greater than largest uint208).\n     *\n     * Counterpart to Solidity's `uint208` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 208 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint208(uint256 value) internal pure returns (uint208) {\n        require(value \u003c= type(uint208).max, \"SafeCast: value doesn't fit in 208 bits\");\n        return uint208(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint200 from uint256, reverting on\n     * overflow (when the input is greater than largest uint200).\n     *\n     * Counterpart to Solidity's `uint200` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 200 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint200(uint256 value) internal pure returns (uint200) {\n        require(value \u003c= type(uint200).max, \"SafeCast: value doesn't fit in 200 bits\");\n        return uint200(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint192 from uint256, reverting on\n     * overflow (when the input is greater than largest uint192).\n     *\n     * Counterpart to Solidity's `uint192` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 192 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint192(uint256 value) internal pure returns (uint192) {\n        require(value \u003c= type(uint192).max, \"SafeCast: value doesn't fit in 192 bits\");\n        return uint192(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint184 from uint256, reverting on\n     * overflow (when the input is greater than largest uint184).\n     *\n     * Counterpart to Solidity's `uint184` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 184 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint184(uint256 value) internal pure returns (uint184) {\n        require(value \u003c= type(uint184).max, \"SafeCast: value doesn't fit in 184 bits\");\n        return uint184(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint176 from uint256, reverting on\n     * overflow (when the input is greater than largest uint176).\n     *\n     * Counterpart to Solidity's `uint176` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 176 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint176(uint256 value) internal pure returns (uint176) {\n        require(value \u003c= type(uint176).max, \"SafeCast: value doesn't fit in 176 bits\");\n        return uint176(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint168 from uint256, reverting on\n     * overflow (when the input is greater than largest uint168).\n     *\n     * Counterpart to Solidity's `uint168` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 168 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint168(uint256 value) internal pure returns (uint168) {\n        require(value \u003c= type(uint168).max, \"SafeCast: value doesn't fit in 168 bits\");\n        return uint168(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint160 from uint256, reverting on\n     * overflow (when the input is greater than largest uint160).\n     *\n     * Counterpart to Solidity's `uint160` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 160 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint160(uint256 value) internal pure returns (uint160) {\n        require(value \u003c= type(uint160).max, \"SafeCast: value doesn't fit in 160 bits\");\n        return uint160(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint152 from uint256, reverting on\n     * overflow (when the input is greater than largest uint152).\n     *\n     * Counterpart to Solidity's `uint152` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 152 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint152(uint256 value) internal pure returns (uint152) {\n        require(value \u003c= type(uint152).max, \"SafeCast: value doesn't fit in 152 bits\");\n        return uint152(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint144 from uint256, reverting on\n     * overflow (when the input is greater than largest uint144).\n     *\n     * Counterpart to Solidity's `uint144` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 144 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint144(uint256 value) internal pure returns (uint144) {\n        require(value \u003c= type(uint144).max, \"SafeCast: value doesn't fit in 144 bits\");\n        return uint144(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint136 from uint256, reverting on\n     * overflow (when the input is greater than largest uint136).\n     *\n     * Counterpart to Solidity's `uint136` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 136 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint136(uint256 value) internal pure returns (uint136) {\n        require(value \u003c= type(uint136).max, \"SafeCast: value doesn't fit in 136 bits\");\n        return uint136(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint128 from uint256, reverting on\n     * overflow (when the input is greater than largest uint128).\n     *\n     * Counterpart to Solidity's `uint128` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 128 bits\n     *\n     * _Available since v2.5._\n     */\n    function toUint128(uint256 value) internal pure returns (uint128) {\n        require(value \u003c= type(uint128).max, \"SafeCast: value doesn't fit in 128 bits\");\n        return uint128(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint120 from uint256, reverting on\n     * overflow (when the input is greater than largest uint120).\n     *\n     * Counterpart to Solidity's `uint120` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 120 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint120(uint256 value) internal pure returns (uint120) {\n        require(value \u003c= type(uint120).max, \"SafeCast: value doesn't fit in 120 bits\");\n        return uint120(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint112 from uint256, reverting on\n     * overflow (when the input is greater than largest uint112).\n     *\n     * Counterpart to Solidity's `uint112` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 112 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint112(uint256 value) internal pure returns (uint112) {\n        require(value \u003c= type(uint112).max, \"SafeCast: value doesn't fit in 112 bits\");\n        return uint112(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint104 from uint256, reverting on\n     * overflow (when the input is greater than largest uint104).\n     *\n     * Counterpart to Solidity's `uint104` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 104 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint104(uint256 value) internal pure returns (uint104) {\n        require(value \u003c= type(uint104).max, \"SafeCast: value doesn't fit in 104 bits\");\n        return uint104(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint96 from uint256, reverting on\n     * overflow (when the input is greater than largest uint96).\n     *\n     * Counterpart to Solidity's `uint96` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 96 bits\n     *\n     * _Available since v4.2._\n     */\n    function toUint96(uint256 value) internal pure returns (uint96) {\n        require(value \u003c= type(uint96).max, \"SafeCast: value doesn't fit in 96 bits\");\n        return uint96(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint88 from uint256, reverting on\n     * overflow (when the input is greater than largest uint88).\n     *\n     * Counterpart to Solidity's `uint88` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 88 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint88(uint256 value) internal pure returns (uint88) {\n        require(value \u003c= type(uint88).max, \"SafeCast: value doesn't fit in 88 bits\");\n        return uint88(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint80 from uint256, reverting on\n     * overflow (when the input is greater than largest uint80).\n     *\n     * Counterpart to Solidity's `uint80` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 80 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint80(uint256 value) internal pure returns (uint80) {\n        require(value \u003c= type(uint80).max, \"SafeCast: value doesn't fit in 80 bits\");\n        return uint80(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint72 from uint256, reverting on\n     * overflow (when the input is greater than largest uint72).\n     *\n     * Counterpart to Solidity's `uint72` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 72 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint72(uint256 value) internal pure returns (uint72) {\n        require(value \u003c= type(uint72).max, \"SafeCast: value doesn't fit in 72 bits\");\n        return uint72(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint64 from uint256, reverting on\n     * overflow (when the input is greater than largest uint64).\n     *\n     * Counterpart to Solidity's `uint64` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 64 bits\n     *\n     * _Available since v2.5._\n     */\n    function toUint64(uint256 value) internal pure returns (uint64) {\n        require(value \u003c= type(uint64).max, \"SafeCast: value doesn't fit in 64 bits\");\n        return uint64(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint56 from uint256, reverting on\n     * overflow (when the input is greater than largest uint56).\n     *\n     * Counterpart to Solidity's `uint56` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 56 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint56(uint256 value) internal pure returns (uint56) {\n        require(value \u003c= type(uint56).max, \"SafeCast: value doesn't fit in 56 bits\");\n        return uint56(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint48 from uint256, reverting on\n     * overflow (when the input is greater than largest uint48).\n     *\n     * Counterpart to Solidity's `uint48` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 48 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint48(uint256 value) internal pure returns (uint48) {\n        require(value \u003c= type(uint48).max, \"SafeCast: value doesn't fit in 48 bits\");\n        return uint48(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint40 from uint256, reverting on\n     * overflow (when the input is greater than largest uint40).\n     *\n     * Counterpart to Solidity's `uint40` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 40 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint40(uint256 value) internal pure returns (uint40) {\n        require(value \u003c= type(uint40).max, \"SafeCast: value doesn't fit in 40 bits\");\n        return uint40(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint32 from uint256, reverting on\n     * overflow (when the input is greater than largest uint32).\n     *\n     * Counterpart to Solidity's `uint32` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 32 bits\n     *\n     * _Available since v2.5._\n     */\n    function toUint32(uint256 value) internal pure returns (uint32) {\n        require(value \u003c= type(uint32).max, \"SafeCast: value doesn't fit in 32 bits\");\n        return uint32(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint24 from uint256, reverting on\n     * overflow (when the input is greater than largest uint24).\n     *\n     * Counterpart to Solidity's `uint24` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 24 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint24(uint256 value) internal pure returns (uint24) {\n        require(value \u003c= type(uint24).max, \"SafeCast: value doesn't fit in 24 bits\");\n        return uint24(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint16 from uint256, reverting on\n     * overflow (when the input is greater than largest uint16).\n     *\n     * Counterpart to Solidity's `uint16` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 16 bits\n     *\n     * _Available since v2.5._\n     */\n    function toUint16(uint256 value) internal pure returns (uint16) {\n        require(value \u003c= type(uint16).max, \"SafeCast: value doesn't fit in 16 bits\");\n        return uint16(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint8 from uint256, reverting on\n     * overflow (when the input is greater than largest uint8).\n     *\n     * Counterpart to Solidity's `uint8` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 8 bits\n     *\n     * _Available since v2.5._\n     */\n    function toUint8(uint256 value) internal pure returns (uint8) {\n        require(value \u003c= type(uint8).max, \"SafeCast: value doesn't fit in 8 bits\");\n        return uint8(value);\n    }\n\n    /**\n     * @dev Converts a signed int256 into an unsigned uint256.\n     *\n     * Requirements:\n     *\n     * - input must be greater than or equal to 0.\n     *\n     * _Available since v3.0._\n     */\n    function toUint256(int256 value) internal pure returns (uint256) {\n        require(value \u003e= 0, \"SafeCast: value must be positive\");\n        return uint256(value);\n    }\n\n    /**\n     * @dev Returns the downcasted int248 from int256, reverting on\n     * overflow (when the input is less than smallest int248 or\n     * greater than largest int248).\n     *\n     * Counterpart to Solidity's `int248` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 248 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt248(int256 value) internal pure returns (int248 downcasted) {\n        downcasted = int248(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 248 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int240 from int256, reverting on\n     * overflow (when the input is less than smallest int240 or\n     * greater than largest int240).\n     *\n     * Counterpart to Solidity's `int240` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 240 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt240(int256 value) internal pure returns (int240 downcasted) {\n        downcasted = int240(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 240 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int232 from int256, reverting on\n     * overflow (when the input is less than smallest int232 or\n     * greater than largest int232).\n     *\n     * Counterpart to Solidity's `int232` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 232 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt232(int256 value) internal pure returns (int232 downcasted) {\n        downcasted = int232(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 232 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int224 from int256, reverting on\n     * overflow (when the input is less than smallest int224 or\n     * greater than largest int224).\n     *\n     * Counterpart to Solidity's `int224` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 224 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt224(int256 value) internal pure returns (int224 downcasted) {\n        downcasted = int224(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 224 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int216 from int256, reverting on\n     * overflow (when the input is less than smallest int216 or\n     * greater than largest int216).\n     *\n     * Counterpart to Solidity's `int216` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 216 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt216(int256 value) internal pure returns (int216 downcasted) {\n        downcasted = int216(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 216 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int208 from int256, reverting on\n     * overflow (when the input is less than smallest int208 or\n     * greater than largest int208).\n     *\n     * Counterpart to Solidity's `int208` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 208 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt208(int256 value) internal pure returns (int208 downcasted) {\n        downcasted = int208(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 208 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int200 from int256, reverting on\n     * overflow (when the input is less than smallest int200 or\n     * greater than largest int200).\n     *\n     * Counterpart to Solidity's `int200` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 200 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt200(int256 value) internal pure returns (int200 downcasted) {\n        downcasted = int200(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 200 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int192 from int256, reverting on\n     * overflow (when the input is less than smallest int192 or\n     * greater than largest int192).\n     *\n     * Counterpart to Solidity's `int192` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 192 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt192(int256 value) internal pure returns (int192 downcasted) {\n        downcasted = int192(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 192 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int184 from int256, reverting on\n     * overflow (when the input is less than smallest int184 or\n     * greater than largest int184).\n     *\n     * Counterpart to Solidity's `int184` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 184 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt184(int256 value) internal pure returns (int184 downcasted) {\n        downcasted = int184(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 184 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int176 from int256, reverting on\n     * overflow (when the input is less than smallest int176 or\n     * greater than largest int176).\n     *\n     * Counterpart to Solidity's `int176` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 176 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt176(int256 value) internal pure returns (int176 downcasted) {\n        downcasted = int176(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 176 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int168 from int256, reverting on\n     * overflow (when the input is less than smallest int168 or\n     * greater than largest int168).\n     *\n     * Counterpart to Solidity's `int168` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 168 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt168(int256 value) internal pure returns (int168 downcasted) {\n        downcasted = int168(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 168 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int160 from int256, reverting on\n     * overflow (when the input is less than smallest int160 or\n     * greater than largest int160).\n     *\n     * Counterpart to Solidity's `int160` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 160 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt160(int256 value) internal pure returns (int160 downcasted) {\n        downcasted = int160(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 160 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int152 from int256, reverting on\n     * overflow (when the input is less than smallest int152 or\n     * greater than largest int152).\n     *\n     * Counterpart to Solidity's `int152` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 152 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt152(int256 value) internal pure returns (int152 downcasted) {\n        downcasted = int152(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 152 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int144 from int256, reverting on\n     * overflow (when the input is less than smallest int144 or\n     * greater than largest int144).\n     *\n     * Counterpart to Solidity's `int144` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 144 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt144(int256 value) internal pure returns (int144 downcasted) {\n        downcasted = int144(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 144 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int136 from int256, reverting on\n     * overflow (when the input is less than smallest int136 or\n     * greater than largest int136).\n     *\n     * Counterpart to Solidity's `int136` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 136 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt136(int256 value) internal pure returns (int136 downcasted) {\n        downcasted = int136(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 136 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int128 from int256, reverting on\n     * overflow (when the input is less than smallest int128 or\n     * greater than largest int128).\n     *\n     * Counterpart to Solidity's `int128` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 128 bits\n     *\n     * _Available since v3.1._\n     */\n    function toInt128(int256 value) internal pure returns (int128 downcasted) {\n        downcasted = int128(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 128 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int120 from int256, reverting on\n     * overflow (when the input is less than smallest int120 or\n     * greater than largest int120).\n     *\n     * Counterpart to Solidity's `int120` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 120 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt120(int256 value) internal pure returns (int120 downcasted) {\n        downcasted = int120(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 120 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int112 from int256, reverting on\n     * overflow (when the input is less than smallest int112 or\n     * greater than largest int112).\n     *\n     * Counterpart to Solidity's `int112` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 112 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt112(int256 value) internal pure returns (int112 downcasted) {\n        downcasted = int112(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 112 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int104 from int256, reverting on\n     * overflow (when the input is less than smallest int104 or\n     * greater than largest int104).\n     *\n     * Counterpart to Solidity's `int104` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 104 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt104(int256 value) internal pure returns (int104 downcasted) {\n        downcasted = int104(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 104 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int96 from int256, reverting on\n     * overflow (when the input is less than smallest int96 or\n     * greater than largest int96).\n     *\n     * Counterpart to Solidity's `int96` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 96 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt96(int256 value) internal pure returns (int96 downcasted) {\n        downcasted = int96(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 96 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int88 from int256, reverting on\n     * overflow (when the input is less than smallest int88 or\n     * greater than largest int88).\n     *\n     * Counterpart to Solidity's `int88` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 88 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt88(int256 value) internal pure returns (int88 downcasted) {\n        downcasted = int88(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 88 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int80 from int256, reverting on\n     * overflow (when the input is less than smallest int80 or\n     * greater than largest int80).\n     *\n     * Counterpart to Solidity's `int80` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 80 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt80(int256 value) internal pure returns (int80 downcasted) {\n        downcasted = int80(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 80 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int72 from int256, reverting on\n     * overflow (when the input is less than smallest int72 or\n     * greater than largest int72).\n     *\n     * Counterpart to Solidity's `int72` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 72 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt72(int256 value) internal pure returns (int72 downcasted) {\n        downcasted = int72(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 72 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int64 from int256, reverting on\n     * overflow (when the input is less than smallest int64 or\n     * greater than largest int64).\n     *\n     * Counterpart to Solidity's `int64` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 64 bits\n     *\n     * _Available since v3.1._\n     */\n    function toInt64(int256 value) internal pure returns (int64 downcasted) {\n        downcasted = int64(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 64 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int56 from int256, reverting on\n     * overflow (when the input is less than smallest int56 or\n     * greater than largest int56).\n     *\n     * Counterpart to Solidity's `int56` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 56 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt56(int256 value) internal pure returns (int56 downcasted) {\n        downcasted = int56(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 56 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int48 from int256, reverting on\n     * overflow (when the input is less than smallest int48 or\n     * greater than largest int48).\n     *\n     * Counterpart to Solidity's `int48` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 48 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt48(int256 value) internal pure returns (int48 downcasted) {\n        downcasted = int48(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 48 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int40 from int256, reverting on\n     * overflow (when the input is less than smallest int40 or\n     * greater than largest int40).\n     *\n     * Counterpart to Solidity's `int40` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 40 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt40(int256 value) internal pure returns (int40 downcasted) {\n        downcasted = int40(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 40 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int32 from int256, reverting on\n     * overflow (when the input is less than smallest int32 or\n     * greater than largest int32).\n     *\n     * Counterpart to Solidity's `int32` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 32 bits\n     *\n     * _Available since v3.1._\n     */\n    function toInt32(int256 value) internal pure returns (int32 downcasted) {\n        downcasted = int32(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 32 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int24 from int256, reverting on\n     * overflow (when the input is less than smallest int24 or\n     * greater than largest int24).\n     *\n     * Counterpart to Solidity's `int24` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 24 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt24(int256 value) internal pure returns (int24 downcasted) {\n        downcasted = int24(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 24 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int16 from int256, reverting on\n     * overflow (when the input is less than smallest int16 or\n     * greater than largest int16).\n     *\n     * Counterpart to Solidity's `int16` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 16 bits\n     *\n     * _Available since v3.1._\n     */\n    function toInt16(int256 value) internal pure returns (int16 downcasted) {\n        downcasted = int16(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 16 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int8 from int256, reverting on\n     * overflow (when the input is less than smallest int8 or\n     * greater than largest int8).\n     *\n     * Counterpart to Solidity's `int8` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 8 bits\n     *\n     * _Available since v3.1._\n     */\n    function toInt8(int256 value) internal pure returns (int8 downcasted) {\n        downcasted = int8(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 8 bits\");\n    }\n\n    /**\n     * @dev Converts an unsigned uint256 into a signed int256.\n     *\n     * Requirements:\n     *\n     * - input must be less than or equal to maxInt256.\n     *\n     * _Available since v3.0._\n     */\n    function toInt256(uint256 value) internal pure returns (int256) {\n        // Note: Unsafe cast below is okay because `type(int256).max` is guaranteed to be positive\n        require(value \u003c= uint256(type(int256).max), \"SafeCast: value doesn't fit in an int256\");\n        return int256(value);\n    }\n}\n\n// 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/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// contracts/libs/memory/BaseMessage.sol\n\n/// BaseMessage is a memory view over the base message supported by Origin-Destination\ntype BaseMessage is uint256;\n\nusing BaseMessageLib for BaseMessage global;\n\n/// BaseMessage structure represents a base message sent via the Origin-Destination contracts.\n/// - It only contains data relevant to the base message, the rest of data is encoded in the message header.\n/// - `sender` and `recipient` for EVM chains are EVM addresses casted to bytes32, while preserving left-alignment.\n/// - `tips` and `request` parameters are specified by a message sender\n/// \u003e Origin will calculate minimum tips for given request and content length, and will reject messages with tips\n/// lower than that.\n///\n/// # Memory layout of BaseMessage fields\n///\n/// | Position   | Field     | Type    | Bytes | Description                            |\n/// | ---------- | --------- | ------- | ----- | -------------------------------------- |\n/// | [000..032) | tips      | uint256 | 32    | Encoded tips paid on origin chain      |\n/// | [032..064) | sender    | bytes32 | 32    | Sender address on origin chain         |\n/// | [064..096) | recipient | bytes32 | 32    | Recipient address on destination chain |\n/// | [096..116) | request   | uint160 | 20    | Encoded request for message execution  |\n/// | [104..AAA) | content   | bytes   | ??    | Content to be passed to recipient      |\nlibrary BaseMessageLib {\n    using MemViewLib for bytes;\n\n    /// @dev The variables below are not supposed to be used outside of the library directly.\n    uint256 private constant OFFSET_TIPS = 0;\n    uint256 private constant OFFSET_SENDER = 32;\n    uint256 private constant OFFSET_RECIPIENT = 64;\n    uint256 private constant OFFSET_REQUEST = OFFSET_RECIPIENT + TIPS_LENGTH;\n    uint256 private constant OFFSET_CONTENT = OFFSET_REQUEST + REQUEST_LENGTH;\n\n    // ═══════════════════════════════════════════════ BASE MESSAGE ════════════════════════════════════════════════════\n\n    /**\n     * @notice Returns a formatted BaseMessage payload with provided fields.\n     * @param tips_         Encoded tips information\n     * @param sender_       Sender address on origin chain\n     * @param recipient_    Recipient address on destination chain\n     * @param request_      Encoded request for message execution\n     * @param content_      Raw content to be passed to recipient on destination chain\n     * @return Formatted base message\n     */\n    function formatBaseMessage(Tips tips_, bytes32 sender_, bytes32 recipient_, Request request_, bytes memory content_)\n        internal\n        pure\n        returns (bytes memory)\n    {\n        return abi.encodePacked(tips_, sender_, recipient_, request_, content_);\n    }\n\n    /**\n     * @notice Returns a BaseMessage view over the given payload.\n     * @dev Will revert if the payload is not a base message.\n     */\n    function castToBaseMessage(bytes memory payload) internal pure returns (BaseMessage) {\n        return castToBaseMessage(payload.ref());\n    }\n\n    /**\n     * @notice Casts a memory view to a BaseMessage view.\n     * @dev Will revert if the memory view is not over a base message payload.\n     */\n    function castToBaseMessage(MemView memView) internal pure returns (BaseMessage) {\n        if (!isBaseMessage(memView)) revert UnformattedBaseMessage();\n        return BaseMessage.wrap(MemView.unwrap(memView));\n    }\n\n    /// @notice Checks that a payload is a formatted BaseMessage.\n    function isBaseMessage(MemView memView) internal pure returns (bool) {\n        // Check if sender, recipient, tips fields exist\n        return (memView.len() \u003e= OFFSET_CONTENT);\n        // Content could be empty, so we don't check that\n    }\n\n    /// @notice Convenience shortcut for unwrapping a view.\n    function unwrap(BaseMessage baseMessage) internal pure returns (MemView) {\n        return MemView.wrap(BaseMessage.unwrap(baseMessage));\n    }\n\n    /// @notice Returns baseMessage's hash: a leaf to be inserted in the \"Message mini-Merkle tree\".\n    function leaf(BaseMessage baseMessage) internal pure returns (bytes32) {\n        // We hash \"tips\" and \"everything but tips\" to make tips proofs easier to verify\n        return MerkleMath.getParent(baseMessage.tips().leaf(), baseMessage.bodyLeaf());\n    }\n\n    /// @notice Returns hash for the \"everything but tips\" part of the base message.\n    function bodyLeaf(BaseMessage baseMessage) internal pure returns (bytes32) {\n        return baseMessage.unwrap().sliceFrom({index_: OFFSET_SENDER}).keccak();\n    }\n\n    // ═══════════════════════════════════════════ BASE MESSAGE SLICING ════════════════════════════════════════════════\n\n    /// @notice Returns encoded tips paid on origin chain.\n    function tips(BaseMessage baseMessage) internal pure returns (Tips) {\n        return TipsLib.wrapPadded((baseMessage.unwrap().indexUint({index_: OFFSET_TIPS, bytes_: TIPS_LENGTH})));\n    }\n\n    /// @notice Returns sender address on origin chain.\n    function sender(BaseMessage baseMessage) internal pure returns (bytes32) {\n        return baseMessage.unwrap().index({index_: OFFSET_SENDER, bytes_: 32});\n    }\n\n    /// @notice Returns recipient address on destination chain.\n    function recipient(BaseMessage baseMessage) internal pure returns (bytes32) {\n        return baseMessage.unwrap().index({index_: OFFSET_RECIPIENT, bytes_: 32});\n    }\n\n    /// @notice Returns an encoded request for message execution on destination chain.\n    function request(BaseMessage baseMessage) internal pure returns (Request) {\n        return RequestLib.wrapPadded((baseMessage.unwrap().indexUint({index_: OFFSET_REQUEST, bytes_: REQUEST_LENGTH})));\n    }\n\n    /// @notice Returns an untyped memory view over the content to be passed to recipient.\n    function content(BaseMessage baseMessage) internal pure returns (MemView) {\n        return baseMessage.unwrap().sliceFrom({index_: OFFSET_CONTENT});\n    }\n}\n\n// test/harnesses/libs/memory/BaseMessageHarness.t.sol\n\n// solhint-disable ordering\n/**\n * @notice Exposes BaseMessage methods for testing against golang.\n */\ncontract BaseMessageHarness {\n    using BaseMessageLib for bytes;\n    using BaseMessageLib for MemView;\n    using MemViewLib for bytes;\n\n    // Note: we don't add an empty test() function here, as it currently leads\n    // to zero coverage on the corresponding library.\n\n    // ══════════════════════════════════════════════════ GETTERS ══════════════════════════════════════════════════════\n\n    function castToBaseMessage(bytes memory payload) public view returns (bytes memory) {\n        // Walkaround to get the forge coverage working on libraries, see\n        // https://github.com/foundry-rs/foundry/pull/3128#issuecomment-1241245086\n        BaseMessage baseMessage = BaseMessageLib.castToBaseMessage(payload);\n        return baseMessage.unwrap().clone();\n    }\n\n    /// @notice Returns baseMessage's sender field\n    function sender(bytes memory payload) public pure returns (bytes32) {\n        return payload.castToBaseMessage().sender();\n    }\n\n    /// @notice Returns baseMessage's recipient field as bytes32\n    function recipient(bytes memory payload) public pure returns (bytes32) {\n        return payload.castToBaseMessage().recipient();\n    }\n\n    /// @notice Returns baseMessage's tips field\n    function tips(bytes memory payload) public pure returns (uint256) {\n        return Tips.unwrap(payload.castToBaseMessage().tips());\n    }\n\n    /// @notice Returns baseMessage's request field\n    function request(bytes memory payload) public pure returns (uint192) {\n        return Request.unwrap(payload.castToBaseMessage().request());\n    }\n\n    /// @notice Returns baseMessage's content field\n    function content(bytes memory payload) public view returns (bytes memory) {\n        return payload.castToBaseMessage().content().clone();\n    }\n\n    function isBaseMessage(bytes memory payload) public pure returns (bool) {\n        return payload.ref().isBaseMessage();\n    }\n\n    // ════════════════════════════════════════════════ FORMATTERS ═════════════════════════════════════════════════════\n\n    function formatBaseMessage(Tips tips_, bytes32 sender_, bytes32 recipient_, Request request_, bytes memory content_)\n        public\n        pure\n        returns (bytes memory)\n    {\n        return BaseMessageLib.formatBaseMessage(tips_, sender_, recipient_, request_, content_);\n    }\n\n    function leaf(bytes memory payload) public pure returns (bytes32) {\n        return payload.castToBaseMessage().leaf();\n    }\n\n    function bodyLeaf(bytes memory payload) public pure returns (bytes32) {\n        return payload.castToBaseMessage().bodyLeaf();\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":"88459:4880:0:-:0;;;;;;;;;;;;;;;-1:-1:-1;;;88459:4880:0;;;;;;;;;;;;;;;;;","srcMapRuntime":"88459:4880:0:-:0;;;;;;;;","abiDefinition":[],"userDoc":{"kind":"user","methods":{},"notice":"BaseMessage structure represents a base message sent via the Origin-Destination contracts. - It only contains data relevant to the base message, the rest of data is encoded in the message header. - `sender` and `recipient` for EVM chains are EVM addresses casted to bytes32, while preserving left-alignment. - `tips` and `request` parameters are specified by a message sender \u003e Origin will calculate minimum tips for given request and content length, and will reject messages with tips lower than that. # Memory layout of BaseMessage fields | Position   | Field     | Type    | Bytes | Description                            | | ---------- | --------- | ------- | ----- | -------------------------------------- | | [000..032) | tips      | uint256 | 32    | Encoded tips paid on origin chain      | | [032..064) | sender    | bytes32 | 32    | Sender address on origin chain         | | [064..096) | recipient | bytes32 | 32    | Recipient address on destination chain | | [096..116) | request   | uint160 | 20    | Encoded request for message execution  | | [104..AAA) | content   | bytes   | ??    | Content to be passed to recipient      |","version":1},"developerDoc":{"kind":"dev","methods":{},"stateVariables":{"OFFSET_TIPS":{"details":"The variables below are not supposed to be used outside of the library directly."}},"version":1},"metadata":"{\"compiler\":{\"version\":\"0.8.17+commit.8df45f5f\"},\"language\":\"Solidity\",\"output\":{\"abi\":[],\"devdoc\":{\"kind\":\"dev\",\"methods\":{},\"stateVariables\":{\"OFFSET_TIPS\":{\"details\":\"The variables below are not supposed to be used outside of the library directly.\"}},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"notice\":\"BaseMessage structure represents a base message sent via the Origin-Destination contracts. - It only contains data relevant to the base message, the rest of data is encoded in the message header. - `sender` and `recipient` for EVM chains are EVM addresses casted to bytes32, while preserving left-alignment. - `tips` and `request` parameters are specified by a message sender \u003e Origin will calculate minimum tips for given request and content length, and will reject messages with tips lower than that. # Memory layout of BaseMessage fields | Position   | Field     | Type    | Bytes | Description                            | | ---------- | --------- | ------- | ----- | -------------------------------------- | | [000..032) | tips      | uint256 | 32    | Encoded tips paid on origin chain      | | [032..064) | sender    | bytes32 | 32    | Sender address on origin chain         | | [064..096) | recipient | bytes32 | 32    | Recipient address on destination chain | | [096..116) | request   | uint160 | 20    | Encoded request for message execution  | | [104..AAA) | content   | bytes   | ??    | Content to be passed to recipient      |\",\"version\":1}},\"settings\":{\"compilationTarget\":{\"solidity/BaseMessageHarness.t.sol\":\"BaseMessageLib\"},\"evmVersion\":\"london\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\"},\"optimizer\":{\"enabled\":true,\"runs\":10000},\"remappings\":[]},\"sources\":{\"solidity/BaseMessageHarness.t.sol\":{\"keccak256\":\"0x0b644d75605ac5a83f42b70984b4f8c78046e7756cf276e43df1e1f8c1c57ce6\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://89e64be85f0b7caad7e5d5fe0d77b92bb4c97bf9542651212fb3563a019d5bac\",\"dweb:/ipfs/QmVsD4QYYzmJVCjC85GjGjbY2Jooz9rZHSJmvp4hkWxxbR\"]}},\"version\":1}"},"hashes":{}},"solidity/BaseMessageHarness.t.sol:MemViewLib":{"code":"0x60566037600b82828239805160001a607314602a57634e487b7160e01b600052600060045260246000fd5b30600052607381538281f3fe73000000000000000000000000000000000000000030146080604052600080fdfea2646970667358221220c76a4e73fb006e88a0be3f04b107d774f1bc6354ca2c214205b4dbb6b0cc5d6564736f6c63430008110033","runtime-code":"0x73000000000000000000000000000000000000000030146080604052600080fdfea2646970667358221220c76a4e73fb006e88a0be3f04b107d774f1bc6354ca2c214205b4dbb6b0cc5d6564736f6c63430008110033","info":{"source":"// SPDX-License-Identifier: MIT\npragma solidity =0.8.17 ^0.8.0;\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/Request.sol\n\n/// Request is encoded data with \"message execution request\".\ntype Request is uint192;\n\nusing RequestLib for Request global;\n\n/// Library for formatting _the request part_ of _the base messages_.\n/// - Request represents a message sender requirements for the message execution on the destination chain.\n/// - Request occupies a single storage word, and thus is stored on stack instead of being stored in memory.\n/// \u003e gasDrop field is included for future compatibility and is ignored at the moment.\n///\n/// # Request stack layout (from highest bits to lowest)\n///\n/// | Position   | Field    | Type   | Bytes | Description                                          |\n/// | ---------- | -------- | ------ | ----- | ---------------------------------------------------- |\n/// | (024..012] | gasDrop  | uint96 | 12    | Minimum amount of gas token to drop to the recipient |\n/// | (012..004] | gasLimit | uint64 | 8     | Minimum amount of gas units to supply for execution  |\n/// | (004..000] | version  | uint32 | 4     | Base message version to pass to the recipient        |\n\nlibrary RequestLib {\n    /// @dev Amount of bits to shift to gasDrop field\n    uint192 private constant SHIFT_GAS_DROP = 12 * 8;\n    /// @dev Amount of bits to shift to gasLimit field\n    uint192 private constant SHIFT_GAS_LIMIT = 4 * 8;\n\n    /// @notice Returns an encoded request with the given fields\n    /// @param gasDrop_     Minimum amount of gas token to drop to the recipient (ignored at the moment)\n    /// @param gasLimit_    Minimum amount of gas units to supply for execution\n    /// @param version_     Base message version to pass to the recipient\n    function encodeRequest(uint96 gasDrop_, uint64 gasLimit_, uint32 version_) internal pure returns (Request) {\n        // Casts below are upcasts, so they are safe\n        return Request.wrap(uint192(gasDrop_) \u003c\u003c SHIFT_GAS_DROP | uint192(gasLimit_) \u003c\u003c SHIFT_GAS_LIMIT | version_);\n    }\n\n    /// @notice Wraps the padded encoded request into a Request-typed value.\n    /// @dev The \"padded\" request is simply an encoded request casted to uint256 (highest bits are set to zero).\n    /// Casting to uint256 is done automatically in Solidity, so no extra actions from consumers are needed.\n    /// The highest bits are discarded, so that the contracts dealing with encoded requests\n    /// don't need to be updated, if a new field is added.\n    function wrapPadded(uint256 paddedRequest) internal pure returns (Request) {\n        // Casting to uint192 will truncate the highest bits, which is the behavior we want\n        return Request.wrap(uint192(paddedRequest));\n    }\n\n    /// @notice Returns the requested of gas token to drop to the recipient.\n    function gasDrop(Request request) internal pure returns (uint96) {\n        // Casting to uint96 will truncate the highest bits, which is the behavior we want\n        return uint96(Request.unwrap(request) \u003e\u003e SHIFT_GAS_DROP);\n    }\n\n    /// @notice Returns the requested minimum amount of gas units to supply for execution.\n    function gasLimit(Request request) internal pure returns (uint64) {\n        // Casting to uint64 will truncate the highest bits, which is the behavior we want\n        return uint64(Request.unwrap(request) \u003e\u003e SHIFT_GAS_LIMIT);\n    }\n\n    /// @notice Returns the requested base message version to pass to the recipient.\n    function version(Request request) internal pure returns (uint32) {\n        // Casting to uint32 will truncate the highest bits, which is the behavior we want\n        return uint32(Request.unwrap(request));\n    }\n}\n\n// node_modules/@openzeppelin/contracts/utils/math/SafeCast.sol\n\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/math/SafeCast.sol)\n// This file was procedurally generated from scripts/generate/templates/SafeCast.js.\n\n/**\n * @dev Wrappers over Solidity's uintXX/intXX casting operators with added overflow\n * checks.\n *\n * Downcasting from uint256/int256 in Solidity does not revert on overflow. This can\n * easily result in undesired exploitation or bugs, since developers usually\n * assume that overflows raise errors. `SafeCast` restores this intuition by\n * reverting the transaction when such an operation overflows.\n *\n * Using this library instead of the unchecked operations eliminates an entire\n * class of bugs, so it's recommended to use it always.\n *\n * Can be combined with {SafeMath} and {SignedSafeMath} to extend it to smaller types, by performing\n * all math on `uint256` and `int256` and then downcasting.\n */\nlibrary SafeCast {\n    /**\n     * @dev Returns the downcasted uint248 from uint256, reverting on\n     * overflow (when the input is greater than largest uint248).\n     *\n     * Counterpart to Solidity's `uint248` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 248 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint248(uint256 value) internal pure returns (uint248) {\n        require(value \u003c= type(uint248).max, \"SafeCast: value doesn't fit in 248 bits\");\n        return uint248(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint240 from uint256, reverting on\n     * overflow (when the input is greater than largest uint240).\n     *\n     * Counterpart to Solidity's `uint240` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 240 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint240(uint256 value) internal pure returns (uint240) {\n        require(value \u003c= type(uint240).max, \"SafeCast: value doesn't fit in 240 bits\");\n        return uint240(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint232 from uint256, reverting on\n     * overflow (when the input is greater than largest uint232).\n     *\n     * Counterpart to Solidity's `uint232` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 232 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint232(uint256 value) internal pure returns (uint232) {\n        require(value \u003c= type(uint232).max, \"SafeCast: value doesn't fit in 232 bits\");\n        return uint232(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint224 from uint256, reverting on\n     * overflow (when the input is greater than largest uint224).\n     *\n     * Counterpart to Solidity's `uint224` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 224 bits\n     *\n     * _Available since v4.2._\n     */\n    function toUint224(uint256 value) internal pure returns (uint224) {\n        require(value \u003c= type(uint224).max, \"SafeCast: value doesn't fit in 224 bits\");\n        return uint224(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint216 from uint256, reverting on\n     * overflow (when the input is greater than largest uint216).\n     *\n     * Counterpart to Solidity's `uint216` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 216 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint216(uint256 value) internal pure returns (uint216) {\n        require(value \u003c= type(uint216).max, \"SafeCast: value doesn't fit in 216 bits\");\n        return uint216(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint208 from uint256, reverting on\n     * overflow (when the input is greater than largest uint208).\n     *\n     * Counterpart to Solidity's `uint208` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 208 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint208(uint256 value) internal pure returns (uint208) {\n        require(value \u003c= type(uint208).max, \"SafeCast: value doesn't fit in 208 bits\");\n        return uint208(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint200 from uint256, reverting on\n     * overflow (when the input is greater than largest uint200).\n     *\n     * Counterpart to Solidity's `uint200` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 200 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint200(uint256 value) internal pure returns (uint200) {\n        require(value \u003c= type(uint200).max, \"SafeCast: value doesn't fit in 200 bits\");\n        return uint200(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint192 from uint256, reverting on\n     * overflow (when the input is greater than largest uint192).\n     *\n     * Counterpart to Solidity's `uint192` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 192 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint192(uint256 value) internal pure returns (uint192) {\n        require(value \u003c= type(uint192).max, \"SafeCast: value doesn't fit in 192 bits\");\n        return uint192(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint184 from uint256, reverting on\n     * overflow (when the input is greater than largest uint184).\n     *\n     * Counterpart to Solidity's `uint184` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 184 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint184(uint256 value) internal pure returns (uint184) {\n        require(value \u003c= type(uint184).max, \"SafeCast: value doesn't fit in 184 bits\");\n        return uint184(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint176 from uint256, reverting on\n     * overflow (when the input is greater than largest uint176).\n     *\n     * Counterpart to Solidity's `uint176` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 176 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint176(uint256 value) internal pure returns (uint176) {\n        require(value \u003c= type(uint176).max, \"SafeCast: value doesn't fit in 176 bits\");\n        return uint176(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint168 from uint256, reverting on\n     * overflow (when the input is greater than largest uint168).\n     *\n     * Counterpart to Solidity's `uint168` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 168 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint168(uint256 value) internal pure returns (uint168) {\n        require(value \u003c= type(uint168).max, \"SafeCast: value doesn't fit in 168 bits\");\n        return uint168(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint160 from uint256, reverting on\n     * overflow (when the input is greater than largest uint160).\n     *\n     * Counterpart to Solidity's `uint160` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 160 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint160(uint256 value) internal pure returns (uint160) {\n        require(value \u003c= type(uint160).max, \"SafeCast: value doesn't fit in 160 bits\");\n        return uint160(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint152 from uint256, reverting on\n     * overflow (when the input is greater than largest uint152).\n     *\n     * Counterpart to Solidity's `uint152` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 152 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint152(uint256 value) internal pure returns (uint152) {\n        require(value \u003c= type(uint152).max, \"SafeCast: value doesn't fit in 152 bits\");\n        return uint152(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint144 from uint256, reverting on\n     * overflow (when the input is greater than largest uint144).\n     *\n     * Counterpart to Solidity's `uint144` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 144 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint144(uint256 value) internal pure returns (uint144) {\n        require(value \u003c= type(uint144).max, \"SafeCast: value doesn't fit in 144 bits\");\n        return uint144(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint136 from uint256, reverting on\n     * overflow (when the input is greater than largest uint136).\n     *\n     * Counterpart to Solidity's `uint136` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 136 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint136(uint256 value) internal pure returns (uint136) {\n        require(value \u003c= type(uint136).max, \"SafeCast: value doesn't fit in 136 bits\");\n        return uint136(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint128 from uint256, reverting on\n     * overflow (when the input is greater than largest uint128).\n     *\n     * Counterpart to Solidity's `uint128` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 128 bits\n     *\n     * _Available since v2.5._\n     */\n    function toUint128(uint256 value) internal pure returns (uint128) {\n        require(value \u003c= type(uint128).max, \"SafeCast: value doesn't fit in 128 bits\");\n        return uint128(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint120 from uint256, reverting on\n     * overflow (when the input is greater than largest uint120).\n     *\n     * Counterpart to Solidity's `uint120` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 120 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint120(uint256 value) internal pure returns (uint120) {\n        require(value \u003c= type(uint120).max, \"SafeCast: value doesn't fit in 120 bits\");\n        return uint120(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint112 from uint256, reverting on\n     * overflow (when the input is greater than largest uint112).\n     *\n     * Counterpart to Solidity's `uint112` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 112 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint112(uint256 value) internal pure returns (uint112) {\n        require(value \u003c= type(uint112).max, \"SafeCast: value doesn't fit in 112 bits\");\n        return uint112(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint104 from uint256, reverting on\n     * overflow (when the input is greater than largest uint104).\n     *\n     * Counterpart to Solidity's `uint104` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 104 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint104(uint256 value) internal pure returns (uint104) {\n        require(value \u003c= type(uint104).max, \"SafeCast: value doesn't fit in 104 bits\");\n        return uint104(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint96 from uint256, reverting on\n     * overflow (when the input is greater than largest uint96).\n     *\n     * Counterpart to Solidity's `uint96` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 96 bits\n     *\n     * _Available since v4.2._\n     */\n    function toUint96(uint256 value) internal pure returns (uint96) {\n        require(value \u003c= type(uint96).max, \"SafeCast: value doesn't fit in 96 bits\");\n        return uint96(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint88 from uint256, reverting on\n     * overflow (when the input is greater than largest uint88).\n     *\n     * Counterpart to Solidity's `uint88` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 88 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint88(uint256 value) internal pure returns (uint88) {\n        require(value \u003c= type(uint88).max, \"SafeCast: value doesn't fit in 88 bits\");\n        return uint88(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint80 from uint256, reverting on\n     * overflow (when the input is greater than largest uint80).\n     *\n     * Counterpart to Solidity's `uint80` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 80 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint80(uint256 value) internal pure returns (uint80) {\n        require(value \u003c= type(uint80).max, \"SafeCast: value doesn't fit in 80 bits\");\n        return uint80(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint72 from uint256, reverting on\n     * overflow (when the input is greater than largest uint72).\n     *\n     * Counterpart to Solidity's `uint72` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 72 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint72(uint256 value) internal pure returns (uint72) {\n        require(value \u003c= type(uint72).max, \"SafeCast: value doesn't fit in 72 bits\");\n        return uint72(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint64 from uint256, reverting on\n     * overflow (when the input is greater than largest uint64).\n     *\n     * Counterpart to Solidity's `uint64` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 64 bits\n     *\n     * _Available since v2.5._\n     */\n    function toUint64(uint256 value) internal pure returns (uint64) {\n        require(value \u003c= type(uint64).max, \"SafeCast: value doesn't fit in 64 bits\");\n        return uint64(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint56 from uint256, reverting on\n     * overflow (when the input is greater than largest uint56).\n     *\n     * Counterpart to Solidity's `uint56` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 56 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint56(uint256 value) internal pure returns (uint56) {\n        require(value \u003c= type(uint56).max, \"SafeCast: value doesn't fit in 56 bits\");\n        return uint56(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint48 from uint256, reverting on\n     * overflow (when the input is greater than largest uint48).\n     *\n     * Counterpart to Solidity's `uint48` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 48 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint48(uint256 value) internal pure returns (uint48) {\n        require(value \u003c= type(uint48).max, \"SafeCast: value doesn't fit in 48 bits\");\n        return uint48(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint40 from uint256, reverting on\n     * overflow (when the input is greater than largest uint40).\n     *\n     * Counterpart to Solidity's `uint40` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 40 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint40(uint256 value) internal pure returns (uint40) {\n        require(value \u003c= type(uint40).max, \"SafeCast: value doesn't fit in 40 bits\");\n        return uint40(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint32 from uint256, reverting on\n     * overflow (when the input is greater than largest uint32).\n     *\n     * Counterpart to Solidity's `uint32` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 32 bits\n     *\n     * _Available since v2.5._\n     */\n    function toUint32(uint256 value) internal pure returns (uint32) {\n        require(value \u003c= type(uint32).max, \"SafeCast: value doesn't fit in 32 bits\");\n        return uint32(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint24 from uint256, reverting on\n     * overflow (when the input is greater than largest uint24).\n     *\n     * Counterpart to Solidity's `uint24` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 24 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint24(uint256 value) internal pure returns (uint24) {\n        require(value \u003c= type(uint24).max, \"SafeCast: value doesn't fit in 24 bits\");\n        return uint24(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint16 from uint256, reverting on\n     * overflow (when the input is greater than largest uint16).\n     *\n     * Counterpart to Solidity's `uint16` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 16 bits\n     *\n     * _Available since v2.5._\n     */\n    function toUint16(uint256 value) internal pure returns (uint16) {\n        require(value \u003c= type(uint16).max, \"SafeCast: value doesn't fit in 16 bits\");\n        return uint16(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint8 from uint256, reverting on\n     * overflow (when the input is greater than largest uint8).\n     *\n     * Counterpart to Solidity's `uint8` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 8 bits\n     *\n     * _Available since v2.5._\n     */\n    function toUint8(uint256 value) internal pure returns (uint8) {\n        require(value \u003c= type(uint8).max, \"SafeCast: value doesn't fit in 8 bits\");\n        return uint8(value);\n    }\n\n    /**\n     * @dev Converts a signed int256 into an unsigned uint256.\n     *\n     * Requirements:\n     *\n     * - input must be greater than or equal to 0.\n     *\n     * _Available since v3.0._\n     */\n    function toUint256(int256 value) internal pure returns (uint256) {\n        require(value \u003e= 0, \"SafeCast: value must be positive\");\n        return uint256(value);\n    }\n\n    /**\n     * @dev Returns the downcasted int248 from int256, reverting on\n     * overflow (when the input is less than smallest int248 or\n     * greater than largest int248).\n     *\n     * Counterpart to Solidity's `int248` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 248 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt248(int256 value) internal pure returns (int248 downcasted) {\n        downcasted = int248(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 248 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int240 from int256, reverting on\n     * overflow (when the input is less than smallest int240 or\n     * greater than largest int240).\n     *\n     * Counterpart to Solidity's `int240` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 240 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt240(int256 value) internal pure returns (int240 downcasted) {\n        downcasted = int240(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 240 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int232 from int256, reverting on\n     * overflow (when the input is less than smallest int232 or\n     * greater than largest int232).\n     *\n     * Counterpart to Solidity's `int232` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 232 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt232(int256 value) internal pure returns (int232 downcasted) {\n        downcasted = int232(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 232 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int224 from int256, reverting on\n     * overflow (when the input is less than smallest int224 or\n     * greater than largest int224).\n     *\n     * Counterpart to Solidity's `int224` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 224 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt224(int256 value) internal pure returns (int224 downcasted) {\n        downcasted = int224(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 224 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int216 from int256, reverting on\n     * overflow (when the input is less than smallest int216 or\n     * greater than largest int216).\n     *\n     * Counterpart to Solidity's `int216` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 216 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt216(int256 value) internal pure returns (int216 downcasted) {\n        downcasted = int216(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 216 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int208 from int256, reverting on\n     * overflow (when the input is less than smallest int208 or\n     * greater than largest int208).\n     *\n     * Counterpart to Solidity's `int208` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 208 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt208(int256 value) internal pure returns (int208 downcasted) {\n        downcasted = int208(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 208 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int200 from int256, reverting on\n     * overflow (when the input is less than smallest int200 or\n     * greater than largest int200).\n     *\n     * Counterpart to Solidity's `int200` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 200 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt200(int256 value) internal pure returns (int200 downcasted) {\n        downcasted = int200(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 200 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int192 from int256, reverting on\n     * overflow (when the input is less than smallest int192 or\n     * greater than largest int192).\n     *\n     * Counterpart to Solidity's `int192` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 192 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt192(int256 value) internal pure returns (int192 downcasted) {\n        downcasted = int192(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 192 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int184 from int256, reverting on\n     * overflow (when the input is less than smallest int184 or\n     * greater than largest int184).\n     *\n     * Counterpart to Solidity's `int184` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 184 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt184(int256 value) internal pure returns (int184 downcasted) {\n        downcasted = int184(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 184 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int176 from int256, reverting on\n     * overflow (when the input is less than smallest int176 or\n     * greater than largest int176).\n     *\n     * Counterpart to Solidity's `int176` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 176 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt176(int256 value) internal pure returns (int176 downcasted) {\n        downcasted = int176(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 176 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int168 from int256, reverting on\n     * overflow (when the input is less than smallest int168 or\n     * greater than largest int168).\n     *\n     * Counterpart to Solidity's `int168` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 168 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt168(int256 value) internal pure returns (int168 downcasted) {\n        downcasted = int168(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 168 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int160 from int256, reverting on\n     * overflow (when the input is less than smallest int160 or\n     * greater than largest int160).\n     *\n     * Counterpart to Solidity's `int160` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 160 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt160(int256 value) internal pure returns (int160 downcasted) {\n        downcasted = int160(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 160 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int152 from int256, reverting on\n     * overflow (when the input is less than smallest int152 or\n     * greater than largest int152).\n     *\n     * Counterpart to Solidity's `int152` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 152 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt152(int256 value) internal pure returns (int152 downcasted) {\n        downcasted = int152(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 152 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int144 from int256, reverting on\n     * overflow (when the input is less than smallest int144 or\n     * greater than largest int144).\n     *\n     * Counterpart to Solidity's `int144` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 144 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt144(int256 value) internal pure returns (int144 downcasted) {\n        downcasted = int144(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 144 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int136 from int256, reverting on\n     * overflow (when the input is less than smallest int136 or\n     * greater than largest int136).\n     *\n     * Counterpart to Solidity's `int136` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 136 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt136(int256 value) internal pure returns (int136 downcasted) {\n        downcasted = int136(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 136 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int128 from int256, reverting on\n     * overflow (when the input is less than smallest int128 or\n     * greater than largest int128).\n     *\n     * Counterpart to Solidity's `int128` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 128 bits\n     *\n     * _Available since v3.1._\n     */\n    function toInt128(int256 value) internal pure returns (int128 downcasted) {\n        downcasted = int128(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 128 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int120 from int256, reverting on\n     * overflow (when the input is less than smallest int120 or\n     * greater than largest int120).\n     *\n     * Counterpart to Solidity's `int120` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 120 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt120(int256 value) internal pure returns (int120 downcasted) {\n        downcasted = int120(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 120 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int112 from int256, reverting on\n     * overflow (when the input is less than smallest int112 or\n     * greater than largest int112).\n     *\n     * Counterpart to Solidity's `int112` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 112 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt112(int256 value) internal pure returns (int112 downcasted) {\n        downcasted = int112(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 112 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int104 from int256, reverting on\n     * overflow (when the input is less than smallest int104 or\n     * greater than largest int104).\n     *\n     * Counterpart to Solidity's `int104` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 104 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt104(int256 value) internal pure returns (int104 downcasted) {\n        downcasted = int104(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 104 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int96 from int256, reverting on\n     * overflow (when the input is less than smallest int96 or\n     * greater than largest int96).\n     *\n     * Counterpart to Solidity's `int96` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 96 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt96(int256 value) internal pure returns (int96 downcasted) {\n        downcasted = int96(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 96 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int88 from int256, reverting on\n     * overflow (when the input is less than smallest int88 or\n     * greater than largest int88).\n     *\n     * Counterpart to Solidity's `int88` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 88 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt88(int256 value) internal pure returns (int88 downcasted) {\n        downcasted = int88(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 88 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int80 from int256, reverting on\n     * overflow (when the input is less than smallest int80 or\n     * greater than largest int80).\n     *\n     * Counterpart to Solidity's `int80` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 80 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt80(int256 value) internal pure returns (int80 downcasted) {\n        downcasted = int80(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 80 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int72 from int256, reverting on\n     * overflow (when the input is less than smallest int72 or\n     * greater than largest int72).\n     *\n     * Counterpart to Solidity's `int72` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 72 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt72(int256 value) internal pure returns (int72 downcasted) {\n        downcasted = int72(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 72 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int64 from int256, reverting on\n     * overflow (when the input is less than smallest int64 or\n     * greater than largest int64).\n     *\n     * Counterpart to Solidity's `int64` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 64 bits\n     *\n     * _Available since v3.1._\n     */\n    function toInt64(int256 value) internal pure returns (int64 downcasted) {\n        downcasted = int64(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 64 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int56 from int256, reverting on\n     * overflow (when the input is less than smallest int56 or\n     * greater than largest int56).\n     *\n     * Counterpart to Solidity's `int56` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 56 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt56(int256 value) internal pure returns (int56 downcasted) {\n        downcasted = int56(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 56 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int48 from int256, reverting on\n     * overflow (when the input is less than smallest int48 or\n     * greater than largest int48).\n     *\n     * Counterpart to Solidity's `int48` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 48 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt48(int256 value) internal pure returns (int48 downcasted) {\n        downcasted = int48(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 48 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int40 from int256, reverting on\n     * overflow (when the input is less than smallest int40 or\n     * greater than largest int40).\n     *\n     * Counterpart to Solidity's `int40` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 40 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt40(int256 value) internal pure returns (int40 downcasted) {\n        downcasted = int40(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 40 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int32 from int256, reverting on\n     * overflow (when the input is less than smallest int32 or\n     * greater than largest int32).\n     *\n     * Counterpart to Solidity's `int32` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 32 bits\n     *\n     * _Available since v3.1._\n     */\n    function toInt32(int256 value) internal pure returns (int32 downcasted) {\n        downcasted = int32(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 32 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int24 from int256, reverting on\n     * overflow (when the input is less than smallest int24 or\n     * greater than largest int24).\n     *\n     * Counterpart to Solidity's `int24` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 24 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt24(int256 value) internal pure returns (int24 downcasted) {\n        downcasted = int24(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 24 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int16 from int256, reverting on\n     * overflow (when the input is less than smallest int16 or\n     * greater than largest int16).\n     *\n     * Counterpart to Solidity's `int16` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 16 bits\n     *\n     * _Available since v3.1._\n     */\n    function toInt16(int256 value) internal pure returns (int16 downcasted) {\n        downcasted = int16(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 16 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int8 from int256, reverting on\n     * overflow (when the input is less than smallest int8 or\n     * greater than largest int8).\n     *\n     * Counterpart to Solidity's `int8` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 8 bits\n     *\n     * _Available since v3.1._\n     */\n    function toInt8(int256 value) internal pure returns (int8 downcasted) {\n        downcasted = int8(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 8 bits\");\n    }\n\n    /**\n     * @dev Converts an unsigned uint256 into a signed int256.\n     *\n     * Requirements:\n     *\n     * - input must be less than or equal to maxInt256.\n     *\n     * _Available since v3.0._\n     */\n    function toInt256(uint256 value) internal pure returns (int256) {\n        // Note: Unsafe cast below is okay because `type(int256).max` is guaranteed to be positive\n        require(value \u003c= uint256(type(int256).max), \"SafeCast: value doesn't fit in an int256\");\n        return int256(value);\n    }\n}\n\n// 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/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// contracts/libs/memory/BaseMessage.sol\n\n/// BaseMessage is a memory view over the base message supported by Origin-Destination\ntype BaseMessage is uint256;\n\nusing BaseMessageLib for BaseMessage global;\n\n/// BaseMessage structure represents a base message sent via the Origin-Destination contracts.\n/// - It only contains data relevant to the base message, the rest of data is encoded in the message header.\n/// - `sender` and `recipient` for EVM chains are EVM addresses casted to bytes32, while preserving left-alignment.\n/// - `tips` and `request` parameters are specified by a message sender\n/// \u003e Origin will calculate minimum tips for given request and content length, and will reject messages with tips\n/// lower than that.\n///\n/// # Memory layout of BaseMessage fields\n///\n/// | Position   | Field     | Type    | Bytes | Description                            |\n/// | ---------- | --------- | ------- | ----- | -------------------------------------- |\n/// | [000..032) | tips      | uint256 | 32    | Encoded tips paid on origin chain      |\n/// | [032..064) | sender    | bytes32 | 32    | Sender address on origin chain         |\n/// | [064..096) | recipient | bytes32 | 32    | Recipient address on destination chain |\n/// | [096..116) | request   | uint160 | 20    | Encoded request for message execution  |\n/// | [104..AAA) | content   | bytes   | ??    | Content to be passed to recipient      |\nlibrary BaseMessageLib {\n    using MemViewLib for bytes;\n\n    /// @dev The variables below are not supposed to be used outside of the library directly.\n    uint256 private constant OFFSET_TIPS = 0;\n    uint256 private constant OFFSET_SENDER = 32;\n    uint256 private constant OFFSET_RECIPIENT = 64;\n    uint256 private constant OFFSET_REQUEST = OFFSET_RECIPIENT + TIPS_LENGTH;\n    uint256 private constant OFFSET_CONTENT = OFFSET_REQUEST + REQUEST_LENGTH;\n\n    // ═══════════════════════════════════════════════ BASE MESSAGE ════════════════════════════════════════════════════\n\n    /**\n     * @notice Returns a formatted BaseMessage payload with provided fields.\n     * @param tips_         Encoded tips information\n     * @param sender_       Sender address on origin chain\n     * @param recipient_    Recipient address on destination chain\n     * @param request_      Encoded request for message execution\n     * @param content_      Raw content to be passed to recipient on destination chain\n     * @return Formatted base message\n     */\n    function formatBaseMessage(Tips tips_, bytes32 sender_, bytes32 recipient_, Request request_, bytes memory content_)\n        internal\n        pure\n        returns (bytes memory)\n    {\n        return abi.encodePacked(tips_, sender_, recipient_, request_, content_);\n    }\n\n    /**\n     * @notice Returns a BaseMessage view over the given payload.\n     * @dev Will revert if the payload is not a base message.\n     */\n    function castToBaseMessage(bytes memory payload) internal pure returns (BaseMessage) {\n        return castToBaseMessage(payload.ref());\n    }\n\n    /**\n     * @notice Casts a memory view to a BaseMessage view.\n     * @dev Will revert if the memory view is not over a base message payload.\n     */\n    function castToBaseMessage(MemView memView) internal pure returns (BaseMessage) {\n        if (!isBaseMessage(memView)) revert UnformattedBaseMessage();\n        return BaseMessage.wrap(MemView.unwrap(memView));\n    }\n\n    /// @notice Checks that a payload is a formatted BaseMessage.\n    function isBaseMessage(MemView memView) internal pure returns (bool) {\n        // Check if sender, recipient, tips fields exist\n        return (memView.len() \u003e= OFFSET_CONTENT);\n        // Content could be empty, so we don't check that\n    }\n\n    /// @notice Convenience shortcut for unwrapping a view.\n    function unwrap(BaseMessage baseMessage) internal pure returns (MemView) {\n        return MemView.wrap(BaseMessage.unwrap(baseMessage));\n    }\n\n    /// @notice Returns baseMessage's hash: a leaf to be inserted in the \"Message mini-Merkle tree\".\n    function leaf(BaseMessage baseMessage) internal pure returns (bytes32) {\n        // We hash \"tips\" and \"everything but tips\" to make tips proofs easier to verify\n        return MerkleMath.getParent(baseMessage.tips().leaf(), baseMessage.bodyLeaf());\n    }\n\n    /// @notice Returns hash for the \"everything but tips\" part of the base message.\n    function bodyLeaf(BaseMessage baseMessage) internal pure returns (bytes32) {\n        return baseMessage.unwrap().sliceFrom({index_: OFFSET_SENDER}).keccak();\n    }\n\n    // ═══════════════════════════════════════════ BASE MESSAGE SLICING ════════════════════════════════════════════════\n\n    /// @notice Returns encoded tips paid on origin chain.\n    function tips(BaseMessage baseMessage) internal pure returns (Tips) {\n        return TipsLib.wrapPadded((baseMessage.unwrap().indexUint({index_: OFFSET_TIPS, bytes_: TIPS_LENGTH})));\n    }\n\n    /// @notice Returns sender address on origin chain.\n    function sender(BaseMessage baseMessage) internal pure returns (bytes32) {\n        return baseMessage.unwrap().index({index_: OFFSET_SENDER, bytes_: 32});\n    }\n\n    /// @notice Returns recipient address on destination chain.\n    function recipient(BaseMessage baseMessage) internal pure returns (bytes32) {\n        return baseMessage.unwrap().index({index_: OFFSET_RECIPIENT, bytes_: 32});\n    }\n\n    /// @notice Returns an encoded request for message execution on destination chain.\n    function request(BaseMessage baseMessage) internal pure returns (Request) {\n        return RequestLib.wrapPadded((baseMessage.unwrap().indexUint({index_: OFFSET_REQUEST, bytes_: REQUEST_LENGTH})));\n    }\n\n    /// @notice Returns an untyped memory view over the content to be passed to recipient.\n    function content(BaseMessage baseMessage) internal pure returns (MemView) {\n        return baseMessage.unwrap().sliceFrom({index_: OFFSET_CONTENT});\n    }\n}\n\n// test/harnesses/libs/memory/BaseMessageHarness.t.sol\n\n// solhint-disable ordering\n/**\n * @notice Exposes BaseMessage methods for testing against golang.\n */\ncontract BaseMessageHarness {\n    using BaseMessageLib for bytes;\n    using BaseMessageLib for MemView;\n    using MemViewLib for bytes;\n\n    // Note: we don't add an empty test() function here, as it currently leads\n    // to zero coverage on the corresponding library.\n\n    // ══════════════════════════════════════════════════ GETTERS ══════════════════════════════════════════════════════\n\n    function castToBaseMessage(bytes memory payload) public view returns (bytes memory) {\n        // Walkaround to get the forge coverage working on libraries, see\n        // https://github.com/foundry-rs/foundry/pull/3128#issuecomment-1241245086\n        BaseMessage baseMessage = BaseMessageLib.castToBaseMessage(payload);\n        return baseMessage.unwrap().clone();\n    }\n\n    /// @notice Returns baseMessage's sender field\n    function sender(bytes memory payload) public pure returns (bytes32) {\n        return payload.castToBaseMessage().sender();\n    }\n\n    /// @notice Returns baseMessage's recipient field as bytes32\n    function recipient(bytes memory payload) public pure returns (bytes32) {\n        return payload.castToBaseMessage().recipient();\n    }\n\n    /// @notice Returns baseMessage's tips field\n    function tips(bytes memory payload) public pure returns (uint256) {\n        return Tips.unwrap(payload.castToBaseMessage().tips());\n    }\n\n    /// @notice Returns baseMessage's request field\n    function request(bytes memory payload) public pure returns (uint192) {\n        return Request.unwrap(payload.castToBaseMessage().request());\n    }\n\n    /// @notice Returns baseMessage's content field\n    function content(bytes memory payload) public view returns (bytes memory) {\n        return payload.castToBaseMessage().content().clone();\n    }\n\n    function isBaseMessage(bytes memory payload) public pure returns (bool) {\n        return payload.ref().isBaseMessage();\n    }\n\n    // ════════════════════════════════════════════════ FORMATTERS ═════════════════════════════════════════════════════\n\n    function formatBaseMessage(Tips tips_, bytes32 sender_, bytes32 recipient_, Request request_, bytes memory content_)\n        public\n        pure\n        returns (bytes memory)\n    {\n        return BaseMessageLib.formatBaseMessage(tips_, sender_, recipient_, request_, content_);\n    }\n\n    function leaf(bytes memory payload) public pure returns (bytes32) {\n        return payload.castToBaseMessage().leaf();\n    }\n\n    function bodyLeaf(bytes memory payload) public pure returns (bytes32) {\n        return payload.castToBaseMessage().bodyLeaf();\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":"48711:19162:0:-:0;;;;;;;;;;;;;;;-1:-1:-1;;;48711:19162:0;;;;;;;;;;;;;;;;;","srcMapRuntime":"48711: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/BaseMessageHarness.t.sol\":\"MemViewLib\"},\"evmVersion\":\"london\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\"},\"optimizer\":{\"enabled\":true,\"runs\":10000},\"remappings\":[]},\"sources\":{\"solidity/BaseMessageHarness.t.sol\":{\"keccak256\":\"0x0b644d75605ac5a83f42b70984b4f8c78046e7756cf276e43df1e1f8c1c57ce6\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://89e64be85f0b7caad7e5d5fe0d77b92bb4c97bf9542651212fb3563a019d5bac\",\"dweb:/ipfs/QmVsD4QYYzmJVCjC85GjGjbY2Jooz9rZHSJmvp4hkWxxbR\"]}},\"version\":1}"},"hashes":{}},"solidity/BaseMessageHarness.t.sol:MerkleMath":{"code":"0x60566037600b82828239805160001a607314602a57634e487b7160e01b600052600060045260246000fd5b30600052607381538281f3fe73000000000000000000000000000000000000000030146080604052600080fdfea2646970667358221220e11de69a75bfa1dbf1d2635a988abf30873ebec3174f83156997242219a55c6564736f6c63430008110033","runtime-code":"0x73000000000000000000000000000000000000000030146080604052600080fdfea2646970667358221220e11de69a75bfa1dbf1d2635a988abf30873ebec3174f83156997242219a55c6564736f6c63430008110033","info":{"source":"// SPDX-License-Identifier: MIT\npragma solidity =0.8.17 ^0.8.0;\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/Request.sol\n\n/// Request is encoded data with \"message execution request\".\ntype Request is uint192;\n\nusing RequestLib for Request global;\n\n/// Library for formatting _the request part_ of _the base messages_.\n/// - Request represents a message sender requirements for the message execution on the destination chain.\n/// - Request occupies a single storage word, and thus is stored on stack instead of being stored in memory.\n/// \u003e gasDrop field is included for future compatibility and is ignored at the moment.\n///\n/// # Request stack layout (from highest bits to lowest)\n///\n/// | Position   | Field    | Type   | Bytes | Description                                          |\n/// | ---------- | -------- | ------ | ----- | ---------------------------------------------------- |\n/// | (024..012] | gasDrop  | uint96 | 12    | Minimum amount of gas token to drop to the recipient |\n/// | (012..004] | gasLimit | uint64 | 8     | Minimum amount of gas units to supply for execution  |\n/// | (004..000] | version  | uint32 | 4     | Base message version to pass to the recipient        |\n\nlibrary RequestLib {\n    /// @dev Amount of bits to shift to gasDrop field\n    uint192 private constant SHIFT_GAS_DROP = 12 * 8;\n    /// @dev Amount of bits to shift to gasLimit field\n    uint192 private constant SHIFT_GAS_LIMIT = 4 * 8;\n\n    /// @notice Returns an encoded request with the given fields\n    /// @param gasDrop_     Minimum amount of gas token to drop to the recipient (ignored at the moment)\n    /// @param gasLimit_    Minimum amount of gas units to supply for execution\n    /// @param version_     Base message version to pass to the recipient\n    function encodeRequest(uint96 gasDrop_, uint64 gasLimit_, uint32 version_) internal pure returns (Request) {\n        // Casts below are upcasts, so they are safe\n        return Request.wrap(uint192(gasDrop_) \u003c\u003c SHIFT_GAS_DROP | uint192(gasLimit_) \u003c\u003c SHIFT_GAS_LIMIT | version_);\n    }\n\n    /// @notice Wraps the padded encoded request into a Request-typed value.\n    /// @dev The \"padded\" request is simply an encoded request casted to uint256 (highest bits are set to zero).\n    /// Casting to uint256 is done automatically in Solidity, so no extra actions from consumers are needed.\n    /// The highest bits are discarded, so that the contracts dealing with encoded requests\n    /// don't need to be updated, if a new field is added.\n    function wrapPadded(uint256 paddedRequest) internal pure returns (Request) {\n        // Casting to uint192 will truncate the highest bits, which is the behavior we want\n        return Request.wrap(uint192(paddedRequest));\n    }\n\n    /// @notice Returns the requested of gas token to drop to the recipient.\n    function gasDrop(Request request) internal pure returns (uint96) {\n        // Casting to uint96 will truncate the highest bits, which is the behavior we want\n        return uint96(Request.unwrap(request) \u003e\u003e SHIFT_GAS_DROP);\n    }\n\n    /// @notice Returns the requested minimum amount of gas units to supply for execution.\n    function gasLimit(Request request) internal pure returns (uint64) {\n        // Casting to uint64 will truncate the highest bits, which is the behavior we want\n        return uint64(Request.unwrap(request) \u003e\u003e SHIFT_GAS_LIMIT);\n    }\n\n    /// @notice Returns the requested base message version to pass to the recipient.\n    function version(Request request) internal pure returns (uint32) {\n        // Casting to uint32 will truncate the highest bits, which is the behavior we want\n        return uint32(Request.unwrap(request));\n    }\n}\n\n// node_modules/@openzeppelin/contracts/utils/math/SafeCast.sol\n\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/math/SafeCast.sol)\n// This file was procedurally generated from scripts/generate/templates/SafeCast.js.\n\n/**\n * @dev Wrappers over Solidity's uintXX/intXX casting operators with added overflow\n * checks.\n *\n * Downcasting from uint256/int256 in Solidity does not revert on overflow. This can\n * easily result in undesired exploitation or bugs, since developers usually\n * assume that overflows raise errors. `SafeCast` restores this intuition by\n * reverting the transaction when such an operation overflows.\n *\n * Using this library instead of the unchecked operations eliminates an entire\n * class of bugs, so it's recommended to use it always.\n *\n * Can be combined with {SafeMath} and {SignedSafeMath} to extend it to smaller types, by performing\n * all math on `uint256` and `int256` and then downcasting.\n */\nlibrary SafeCast {\n    /**\n     * @dev Returns the downcasted uint248 from uint256, reverting on\n     * overflow (when the input is greater than largest uint248).\n     *\n     * Counterpart to Solidity's `uint248` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 248 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint248(uint256 value) internal pure returns (uint248) {\n        require(value \u003c= type(uint248).max, \"SafeCast: value doesn't fit in 248 bits\");\n        return uint248(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint240 from uint256, reverting on\n     * overflow (when the input is greater than largest uint240).\n     *\n     * Counterpart to Solidity's `uint240` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 240 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint240(uint256 value) internal pure returns (uint240) {\n        require(value \u003c= type(uint240).max, \"SafeCast: value doesn't fit in 240 bits\");\n        return uint240(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint232 from uint256, reverting on\n     * overflow (when the input is greater than largest uint232).\n     *\n     * Counterpart to Solidity's `uint232` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 232 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint232(uint256 value) internal pure returns (uint232) {\n        require(value \u003c= type(uint232).max, \"SafeCast: value doesn't fit in 232 bits\");\n        return uint232(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint224 from uint256, reverting on\n     * overflow (when the input is greater than largest uint224).\n     *\n     * Counterpart to Solidity's `uint224` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 224 bits\n     *\n     * _Available since v4.2._\n     */\n    function toUint224(uint256 value) internal pure returns (uint224) {\n        require(value \u003c= type(uint224).max, \"SafeCast: value doesn't fit in 224 bits\");\n        return uint224(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint216 from uint256, reverting on\n     * overflow (when the input is greater than largest uint216).\n     *\n     * Counterpart to Solidity's `uint216` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 216 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint216(uint256 value) internal pure returns (uint216) {\n        require(value \u003c= type(uint216).max, \"SafeCast: value doesn't fit in 216 bits\");\n        return uint216(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint208 from uint256, reverting on\n     * overflow (when the input is greater than largest uint208).\n     *\n     * Counterpart to Solidity's `uint208` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 208 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint208(uint256 value) internal pure returns (uint208) {\n        require(value \u003c= type(uint208).max, \"SafeCast: value doesn't fit in 208 bits\");\n        return uint208(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint200 from uint256, reverting on\n     * overflow (when the input is greater than largest uint200).\n     *\n     * Counterpart to Solidity's `uint200` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 200 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint200(uint256 value) internal pure returns (uint200) {\n        require(value \u003c= type(uint200).max, \"SafeCast: value doesn't fit in 200 bits\");\n        return uint200(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint192 from uint256, reverting on\n     * overflow (when the input is greater than largest uint192).\n     *\n     * Counterpart to Solidity's `uint192` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 192 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint192(uint256 value) internal pure returns (uint192) {\n        require(value \u003c= type(uint192).max, \"SafeCast: value doesn't fit in 192 bits\");\n        return uint192(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint184 from uint256, reverting on\n     * overflow (when the input is greater than largest uint184).\n     *\n     * Counterpart to Solidity's `uint184` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 184 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint184(uint256 value) internal pure returns (uint184) {\n        require(value \u003c= type(uint184).max, \"SafeCast: value doesn't fit in 184 bits\");\n        return uint184(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint176 from uint256, reverting on\n     * overflow (when the input is greater than largest uint176).\n     *\n     * Counterpart to Solidity's `uint176` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 176 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint176(uint256 value) internal pure returns (uint176) {\n        require(value \u003c= type(uint176).max, \"SafeCast: value doesn't fit in 176 bits\");\n        return uint176(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint168 from uint256, reverting on\n     * overflow (when the input is greater than largest uint168).\n     *\n     * Counterpart to Solidity's `uint168` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 168 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint168(uint256 value) internal pure returns (uint168) {\n        require(value \u003c= type(uint168).max, \"SafeCast: value doesn't fit in 168 bits\");\n        return uint168(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint160 from uint256, reverting on\n     * overflow (when the input is greater than largest uint160).\n     *\n     * Counterpart to Solidity's `uint160` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 160 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint160(uint256 value) internal pure returns (uint160) {\n        require(value \u003c= type(uint160).max, \"SafeCast: value doesn't fit in 160 bits\");\n        return uint160(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint152 from uint256, reverting on\n     * overflow (when the input is greater than largest uint152).\n     *\n     * Counterpart to Solidity's `uint152` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 152 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint152(uint256 value) internal pure returns (uint152) {\n        require(value \u003c= type(uint152).max, \"SafeCast: value doesn't fit in 152 bits\");\n        return uint152(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint144 from uint256, reverting on\n     * overflow (when the input is greater than largest uint144).\n     *\n     * Counterpart to Solidity's `uint144` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 144 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint144(uint256 value) internal pure returns (uint144) {\n        require(value \u003c= type(uint144).max, \"SafeCast: value doesn't fit in 144 bits\");\n        return uint144(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint136 from uint256, reverting on\n     * overflow (when the input is greater than largest uint136).\n     *\n     * Counterpart to Solidity's `uint136` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 136 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint136(uint256 value) internal pure returns (uint136) {\n        require(value \u003c= type(uint136).max, \"SafeCast: value doesn't fit in 136 bits\");\n        return uint136(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint128 from uint256, reverting on\n     * overflow (when the input is greater than largest uint128).\n     *\n     * Counterpart to Solidity's `uint128` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 128 bits\n     *\n     * _Available since v2.5._\n     */\n    function toUint128(uint256 value) internal pure returns (uint128) {\n        require(value \u003c= type(uint128).max, \"SafeCast: value doesn't fit in 128 bits\");\n        return uint128(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint120 from uint256, reverting on\n     * overflow (when the input is greater than largest uint120).\n     *\n     * Counterpart to Solidity's `uint120` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 120 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint120(uint256 value) internal pure returns (uint120) {\n        require(value \u003c= type(uint120).max, \"SafeCast: value doesn't fit in 120 bits\");\n        return uint120(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint112 from uint256, reverting on\n     * overflow (when the input is greater than largest uint112).\n     *\n     * Counterpart to Solidity's `uint112` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 112 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint112(uint256 value) internal pure returns (uint112) {\n        require(value \u003c= type(uint112).max, \"SafeCast: value doesn't fit in 112 bits\");\n        return uint112(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint104 from uint256, reverting on\n     * overflow (when the input is greater than largest uint104).\n     *\n     * Counterpart to Solidity's `uint104` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 104 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint104(uint256 value) internal pure returns (uint104) {\n        require(value \u003c= type(uint104).max, \"SafeCast: value doesn't fit in 104 bits\");\n        return uint104(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint96 from uint256, reverting on\n     * overflow (when the input is greater than largest uint96).\n     *\n     * Counterpart to Solidity's `uint96` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 96 bits\n     *\n     * _Available since v4.2._\n     */\n    function toUint96(uint256 value) internal pure returns (uint96) {\n        require(value \u003c= type(uint96).max, \"SafeCast: value doesn't fit in 96 bits\");\n        return uint96(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint88 from uint256, reverting on\n     * overflow (when the input is greater than largest uint88).\n     *\n     * Counterpart to Solidity's `uint88` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 88 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint88(uint256 value) internal pure returns (uint88) {\n        require(value \u003c= type(uint88).max, \"SafeCast: value doesn't fit in 88 bits\");\n        return uint88(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint80 from uint256, reverting on\n     * overflow (when the input is greater than largest uint80).\n     *\n     * Counterpart to Solidity's `uint80` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 80 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint80(uint256 value) internal pure returns (uint80) {\n        require(value \u003c= type(uint80).max, \"SafeCast: value doesn't fit in 80 bits\");\n        return uint80(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint72 from uint256, reverting on\n     * overflow (when the input is greater than largest uint72).\n     *\n     * Counterpart to Solidity's `uint72` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 72 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint72(uint256 value) internal pure returns (uint72) {\n        require(value \u003c= type(uint72).max, \"SafeCast: value doesn't fit in 72 bits\");\n        return uint72(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint64 from uint256, reverting on\n     * overflow (when the input is greater than largest uint64).\n     *\n     * Counterpart to Solidity's `uint64` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 64 bits\n     *\n     * _Available since v2.5._\n     */\n    function toUint64(uint256 value) internal pure returns (uint64) {\n        require(value \u003c= type(uint64).max, \"SafeCast: value doesn't fit in 64 bits\");\n        return uint64(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint56 from uint256, reverting on\n     * overflow (when the input is greater than largest uint56).\n     *\n     * Counterpart to Solidity's `uint56` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 56 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint56(uint256 value) internal pure returns (uint56) {\n        require(value \u003c= type(uint56).max, \"SafeCast: value doesn't fit in 56 bits\");\n        return uint56(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint48 from uint256, reverting on\n     * overflow (when the input is greater than largest uint48).\n     *\n     * Counterpart to Solidity's `uint48` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 48 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint48(uint256 value) internal pure returns (uint48) {\n        require(value \u003c= type(uint48).max, \"SafeCast: value doesn't fit in 48 bits\");\n        return uint48(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint40 from uint256, reverting on\n     * overflow (when the input is greater than largest uint40).\n     *\n     * Counterpart to Solidity's `uint40` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 40 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint40(uint256 value) internal pure returns (uint40) {\n        require(value \u003c= type(uint40).max, \"SafeCast: value doesn't fit in 40 bits\");\n        return uint40(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint32 from uint256, reverting on\n     * overflow (when the input is greater than largest uint32).\n     *\n     * Counterpart to Solidity's `uint32` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 32 bits\n     *\n     * _Available since v2.5._\n     */\n    function toUint32(uint256 value) internal pure returns (uint32) {\n        require(value \u003c= type(uint32).max, \"SafeCast: value doesn't fit in 32 bits\");\n        return uint32(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint24 from uint256, reverting on\n     * overflow (when the input is greater than largest uint24).\n     *\n     * Counterpart to Solidity's `uint24` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 24 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint24(uint256 value) internal pure returns (uint24) {\n        require(value \u003c= type(uint24).max, \"SafeCast: value doesn't fit in 24 bits\");\n        return uint24(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint16 from uint256, reverting on\n     * overflow (when the input is greater than largest uint16).\n     *\n     * Counterpart to Solidity's `uint16` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 16 bits\n     *\n     * _Available since v2.5._\n     */\n    function toUint16(uint256 value) internal pure returns (uint16) {\n        require(value \u003c= type(uint16).max, \"SafeCast: value doesn't fit in 16 bits\");\n        return uint16(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint8 from uint256, reverting on\n     * overflow (when the input is greater than largest uint8).\n     *\n     * Counterpart to Solidity's `uint8` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 8 bits\n     *\n     * _Available since v2.5._\n     */\n    function toUint8(uint256 value) internal pure returns (uint8) {\n        require(value \u003c= type(uint8).max, \"SafeCast: value doesn't fit in 8 bits\");\n        return uint8(value);\n    }\n\n    /**\n     * @dev Converts a signed int256 into an unsigned uint256.\n     *\n     * Requirements:\n     *\n     * - input must be greater than or equal to 0.\n     *\n     * _Available since v3.0._\n     */\n    function toUint256(int256 value) internal pure returns (uint256) {\n        require(value \u003e= 0, \"SafeCast: value must be positive\");\n        return uint256(value);\n    }\n\n    /**\n     * @dev Returns the downcasted int248 from int256, reverting on\n     * overflow (when the input is less than smallest int248 or\n     * greater than largest int248).\n     *\n     * Counterpart to Solidity's `int248` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 248 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt248(int256 value) internal pure returns (int248 downcasted) {\n        downcasted = int248(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 248 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int240 from int256, reverting on\n     * overflow (when the input is less than smallest int240 or\n     * greater than largest int240).\n     *\n     * Counterpart to Solidity's `int240` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 240 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt240(int256 value) internal pure returns (int240 downcasted) {\n        downcasted = int240(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 240 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int232 from int256, reverting on\n     * overflow (when the input is less than smallest int232 or\n     * greater than largest int232).\n     *\n     * Counterpart to Solidity's `int232` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 232 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt232(int256 value) internal pure returns (int232 downcasted) {\n        downcasted = int232(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 232 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int224 from int256, reverting on\n     * overflow (when the input is less than smallest int224 or\n     * greater than largest int224).\n     *\n     * Counterpart to Solidity's `int224` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 224 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt224(int256 value) internal pure returns (int224 downcasted) {\n        downcasted = int224(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 224 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int216 from int256, reverting on\n     * overflow (when the input is less than smallest int216 or\n     * greater than largest int216).\n     *\n     * Counterpart to Solidity's `int216` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 216 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt216(int256 value) internal pure returns (int216 downcasted) {\n        downcasted = int216(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 216 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int208 from int256, reverting on\n     * overflow (when the input is less than smallest int208 or\n     * greater than largest int208).\n     *\n     * Counterpart to Solidity's `int208` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 208 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt208(int256 value) internal pure returns (int208 downcasted) {\n        downcasted = int208(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 208 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int200 from int256, reverting on\n     * overflow (when the input is less than smallest int200 or\n     * greater than largest int200).\n     *\n     * Counterpart to Solidity's `int200` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 200 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt200(int256 value) internal pure returns (int200 downcasted) {\n        downcasted = int200(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 200 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int192 from int256, reverting on\n     * overflow (when the input is less than smallest int192 or\n     * greater than largest int192).\n     *\n     * Counterpart to Solidity's `int192` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 192 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt192(int256 value) internal pure returns (int192 downcasted) {\n        downcasted = int192(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 192 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int184 from int256, reverting on\n     * overflow (when the input is less than smallest int184 or\n     * greater than largest int184).\n     *\n     * Counterpart to Solidity's `int184` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 184 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt184(int256 value) internal pure returns (int184 downcasted) {\n        downcasted = int184(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 184 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int176 from int256, reverting on\n     * overflow (when the input is less than smallest int176 or\n     * greater than largest int176).\n     *\n     * Counterpart to Solidity's `int176` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 176 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt176(int256 value) internal pure returns (int176 downcasted) {\n        downcasted = int176(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 176 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int168 from int256, reverting on\n     * overflow (when the input is less than smallest int168 or\n     * greater than largest int168).\n     *\n     * Counterpart to Solidity's `int168` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 168 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt168(int256 value) internal pure returns (int168 downcasted) {\n        downcasted = int168(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 168 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int160 from int256, reverting on\n     * overflow (when the input is less than smallest int160 or\n     * greater than largest int160).\n     *\n     * Counterpart to Solidity's `int160` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 160 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt160(int256 value) internal pure returns (int160 downcasted) {\n        downcasted = int160(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 160 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int152 from int256, reverting on\n     * overflow (when the input is less than smallest int152 or\n     * greater than largest int152).\n     *\n     * Counterpart to Solidity's `int152` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 152 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt152(int256 value) internal pure returns (int152 downcasted) {\n        downcasted = int152(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 152 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int144 from int256, reverting on\n     * overflow (when the input is less than smallest int144 or\n     * greater than largest int144).\n     *\n     * Counterpart to Solidity's `int144` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 144 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt144(int256 value) internal pure returns (int144 downcasted) {\n        downcasted = int144(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 144 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int136 from int256, reverting on\n     * overflow (when the input is less than smallest int136 or\n     * greater than largest int136).\n     *\n     * Counterpart to Solidity's `int136` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 136 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt136(int256 value) internal pure returns (int136 downcasted) {\n        downcasted = int136(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 136 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int128 from int256, reverting on\n     * overflow (when the input is less than smallest int128 or\n     * greater than largest int128).\n     *\n     * Counterpart to Solidity's `int128` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 128 bits\n     *\n     * _Available since v3.1._\n     */\n    function toInt128(int256 value) internal pure returns (int128 downcasted) {\n        downcasted = int128(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 128 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int120 from int256, reverting on\n     * overflow (when the input is less than smallest int120 or\n     * greater than largest int120).\n     *\n     * Counterpart to Solidity's `int120` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 120 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt120(int256 value) internal pure returns (int120 downcasted) {\n        downcasted = int120(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 120 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int112 from int256, reverting on\n     * overflow (when the input is less than smallest int112 or\n     * greater than largest int112).\n     *\n     * Counterpart to Solidity's `int112` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 112 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt112(int256 value) internal pure returns (int112 downcasted) {\n        downcasted = int112(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 112 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int104 from int256, reverting on\n     * overflow (when the input is less than smallest int104 or\n     * greater than largest int104).\n     *\n     * Counterpart to Solidity's `int104` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 104 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt104(int256 value) internal pure returns (int104 downcasted) {\n        downcasted = int104(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 104 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int96 from int256, reverting on\n     * overflow (when the input is less than smallest int96 or\n     * greater than largest int96).\n     *\n     * Counterpart to Solidity's `int96` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 96 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt96(int256 value) internal pure returns (int96 downcasted) {\n        downcasted = int96(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 96 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int88 from int256, reverting on\n     * overflow (when the input is less than smallest int88 or\n     * greater than largest int88).\n     *\n     * Counterpart to Solidity's `int88` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 88 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt88(int256 value) internal pure returns (int88 downcasted) {\n        downcasted = int88(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 88 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int80 from int256, reverting on\n     * overflow (when the input is less than smallest int80 or\n     * greater than largest int80).\n     *\n     * Counterpart to Solidity's `int80` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 80 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt80(int256 value) internal pure returns (int80 downcasted) {\n        downcasted = int80(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 80 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int72 from int256, reverting on\n     * overflow (when the input is less than smallest int72 or\n     * greater than largest int72).\n     *\n     * Counterpart to Solidity's `int72` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 72 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt72(int256 value) internal pure returns (int72 downcasted) {\n        downcasted = int72(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 72 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int64 from int256, reverting on\n     * overflow (when the input is less than smallest int64 or\n     * greater than largest int64).\n     *\n     * Counterpart to Solidity's `int64` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 64 bits\n     *\n     * _Available since v3.1._\n     */\n    function toInt64(int256 value) internal pure returns (int64 downcasted) {\n        downcasted = int64(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 64 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int56 from int256, reverting on\n     * overflow (when the input is less than smallest int56 or\n     * greater than largest int56).\n     *\n     * Counterpart to Solidity's `int56` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 56 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt56(int256 value) internal pure returns (int56 downcasted) {\n        downcasted = int56(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 56 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int48 from int256, reverting on\n     * overflow (when the input is less than smallest int48 or\n     * greater than largest int48).\n     *\n     * Counterpart to Solidity's `int48` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 48 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt48(int256 value) internal pure returns (int48 downcasted) {\n        downcasted = int48(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 48 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int40 from int256, reverting on\n     * overflow (when the input is less than smallest int40 or\n     * greater than largest int40).\n     *\n     * Counterpart to Solidity's `int40` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 40 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt40(int256 value) internal pure returns (int40 downcasted) {\n        downcasted = int40(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 40 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int32 from int256, reverting on\n     * overflow (when the input is less than smallest int32 or\n     * greater than largest int32).\n     *\n     * Counterpart to Solidity's `int32` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 32 bits\n     *\n     * _Available since v3.1._\n     */\n    function toInt32(int256 value) internal pure returns (int32 downcasted) {\n        downcasted = int32(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 32 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int24 from int256, reverting on\n     * overflow (when the input is less than smallest int24 or\n     * greater than largest int24).\n     *\n     * Counterpart to Solidity's `int24` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 24 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt24(int256 value) internal pure returns (int24 downcasted) {\n        downcasted = int24(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 24 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int16 from int256, reverting on\n     * overflow (when the input is less than smallest int16 or\n     * greater than largest int16).\n     *\n     * Counterpart to Solidity's `int16` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 16 bits\n     *\n     * _Available since v3.1._\n     */\n    function toInt16(int256 value) internal pure returns (int16 downcasted) {\n        downcasted = int16(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 16 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int8 from int256, reverting on\n     * overflow (when the input is less than smallest int8 or\n     * greater than largest int8).\n     *\n     * Counterpart to Solidity's `int8` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 8 bits\n     *\n     * _Available since v3.1._\n     */\n    function toInt8(int256 value) internal pure returns (int8 downcasted) {\n        downcasted = int8(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 8 bits\");\n    }\n\n    /**\n     * @dev Converts an unsigned uint256 into a signed int256.\n     *\n     * Requirements:\n     *\n     * - input must be less than or equal to maxInt256.\n     *\n     * _Available since v3.0._\n     */\n    function toInt256(uint256 value) internal pure returns (int256) {\n        // Note: Unsafe cast below is okay because `type(int256).max` is guaranteed to be positive\n        require(value \u003c= uint256(type(int256).max), \"SafeCast: value doesn't fit in an int256\");\n        return int256(value);\n    }\n}\n\n// 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/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// contracts/libs/memory/BaseMessage.sol\n\n/// BaseMessage is a memory view over the base message supported by Origin-Destination\ntype BaseMessage is uint256;\n\nusing BaseMessageLib for BaseMessage global;\n\n/// BaseMessage structure represents a base message sent via the Origin-Destination contracts.\n/// - It only contains data relevant to the base message, the rest of data is encoded in the message header.\n/// - `sender` and `recipient` for EVM chains are EVM addresses casted to bytes32, while preserving left-alignment.\n/// - `tips` and `request` parameters are specified by a message sender\n/// \u003e Origin will calculate minimum tips for given request and content length, and will reject messages with tips\n/// lower than that.\n///\n/// # Memory layout of BaseMessage fields\n///\n/// | Position   | Field     | Type    | Bytes | Description                            |\n/// | ---------- | --------- | ------- | ----- | -------------------------------------- |\n/// | [000..032) | tips      | uint256 | 32    | Encoded tips paid on origin chain      |\n/// | [032..064) | sender    | bytes32 | 32    | Sender address on origin chain         |\n/// | [064..096) | recipient | bytes32 | 32    | Recipient address on destination chain |\n/// | [096..116) | request   | uint160 | 20    | Encoded request for message execution  |\n/// | [104..AAA) | content   | bytes   | ??    | Content to be passed to recipient      |\nlibrary BaseMessageLib {\n    using MemViewLib for bytes;\n\n    /// @dev The variables below are not supposed to be used outside of the library directly.\n    uint256 private constant OFFSET_TIPS = 0;\n    uint256 private constant OFFSET_SENDER = 32;\n    uint256 private constant OFFSET_RECIPIENT = 64;\n    uint256 private constant OFFSET_REQUEST = OFFSET_RECIPIENT + TIPS_LENGTH;\n    uint256 private constant OFFSET_CONTENT = OFFSET_REQUEST + REQUEST_LENGTH;\n\n    // ═══════════════════════════════════════════════ BASE MESSAGE ════════════════════════════════════════════════════\n\n    /**\n     * @notice Returns a formatted BaseMessage payload with provided fields.\n     * @param tips_         Encoded tips information\n     * @param sender_       Sender address on origin chain\n     * @param recipient_    Recipient address on destination chain\n     * @param request_      Encoded request for message execution\n     * @param content_      Raw content to be passed to recipient on destination chain\n     * @return Formatted base message\n     */\n    function formatBaseMessage(Tips tips_, bytes32 sender_, bytes32 recipient_, Request request_, bytes memory content_)\n        internal\n        pure\n        returns (bytes memory)\n    {\n        return abi.encodePacked(tips_, sender_, recipient_, request_, content_);\n    }\n\n    /**\n     * @notice Returns a BaseMessage view over the given payload.\n     * @dev Will revert if the payload is not a base message.\n     */\n    function castToBaseMessage(bytes memory payload) internal pure returns (BaseMessage) {\n        return castToBaseMessage(payload.ref());\n    }\n\n    /**\n     * @notice Casts a memory view to a BaseMessage view.\n     * @dev Will revert if the memory view is not over a base message payload.\n     */\n    function castToBaseMessage(MemView memView) internal pure returns (BaseMessage) {\n        if (!isBaseMessage(memView)) revert UnformattedBaseMessage();\n        return BaseMessage.wrap(MemView.unwrap(memView));\n    }\n\n    /// @notice Checks that a payload is a formatted BaseMessage.\n    function isBaseMessage(MemView memView) internal pure returns (bool) {\n        // Check if sender, recipient, tips fields exist\n        return (memView.len() \u003e= OFFSET_CONTENT);\n        // Content could be empty, so we don't check that\n    }\n\n    /// @notice Convenience shortcut for unwrapping a view.\n    function unwrap(BaseMessage baseMessage) internal pure returns (MemView) {\n        return MemView.wrap(BaseMessage.unwrap(baseMessage));\n    }\n\n    /// @notice Returns baseMessage's hash: a leaf to be inserted in the \"Message mini-Merkle tree\".\n    function leaf(BaseMessage baseMessage) internal pure returns (bytes32) {\n        // We hash \"tips\" and \"everything but tips\" to make tips proofs easier to verify\n        return MerkleMath.getParent(baseMessage.tips().leaf(), baseMessage.bodyLeaf());\n    }\n\n    /// @notice Returns hash for the \"everything but tips\" part of the base message.\n    function bodyLeaf(BaseMessage baseMessage) internal pure returns (bytes32) {\n        return baseMessage.unwrap().sliceFrom({index_: OFFSET_SENDER}).keccak();\n    }\n\n    // ═══════════════════════════════════════════ BASE MESSAGE SLICING ════════════════════════════════════════════════\n\n    /// @notice Returns encoded tips paid on origin chain.\n    function tips(BaseMessage baseMessage) internal pure returns (Tips) {\n        return TipsLib.wrapPadded((baseMessage.unwrap().indexUint({index_: OFFSET_TIPS, bytes_: TIPS_LENGTH})));\n    }\n\n    /// @notice Returns sender address on origin chain.\n    function sender(BaseMessage baseMessage) internal pure returns (bytes32) {\n        return baseMessage.unwrap().index({index_: OFFSET_SENDER, bytes_: 32});\n    }\n\n    /// @notice Returns recipient address on destination chain.\n    function recipient(BaseMessage baseMessage) internal pure returns (bytes32) {\n        return baseMessage.unwrap().index({index_: OFFSET_RECIPIENT, bytes_: 32});\n    }\n\n    /// @notice Returns an encoded request for message execution on destination chain.\n    function request(BaseMessage baseMessage) internal pure returns (Request) {\n        return RequestLib.wrapPadded((baseMessage.unwrap().indexUint({index_: OFFSET_REQUEST, bytes_: REQUEST_LENGTH})));\n    }\n\n    /// @notice Returns an untyped memory view over the content to be passed to recipient.\n    function content(BaseMessage baseMessage) internal pure returns (MemView) {\n        return baseMessage.unwrap().sliceFrom({index_: OFFSET_CONTENT});\n    }\n}\n\n// test/harnesses/libs/memory/BaseMessageHarness.t.sol\n\n// solhint-disable ordering\n/**\n * @notice Exposes BaseMessage methods for testing against golang.\n */\ncontract BaseMessageHarness {\n    using BaseMessageLib for bytes;\n    using BaseMessageLib for MemView;\n    using MemViewLib for bytes;\n\n    // Note: we don't add an empty test() function here, as it currently leads\n    // to zero coverage on the corresponding library.\n\n    // ══════════════════════════════════════════════════ GETTERS ══════════════════════════════════════════════════════\n\n    function castToBaseMessage(bytes memory payload) public view returns (bytes memory) {\n        // Walkaround to get the forge coverage working on libraries, see\n        // https://github.com/foundry-rs/foundry/pull/3128#issuecomment-1241245086\n        BaseMessage baseMessage = BaseMessageLib.castToBaseMessage(payload);\n        return baseMessage.unwrap().clone();\n    }\n\n    /// @notice Returns baseMessage's sender field\n    function sender(bytes memory payload) public pure returns (bytes32) {\n        return payload.castToBaseMessage().sender();\n    }\n\n    /// @notice Returns baseMessage's recipient field as bytes32\n    function recipient(bytes memory payload) public pure returns (bytes32) {\n        return payload.castToBaseMessage().recipient();\n    }\n\n    /// @notice Returns baseMessage's tips field\n    function tips(bytes memory payload) public pure returns (uint256) {\n        return Tips.unwrap(payload.castToBaseMessage().tips());\n    }\n\n    /// @notice Returns baseMessage's request field\n    function request(bytes memory payload) public pure returns (uint192) {\n        return Request.unwrap(payload.castToBaseMessage().request());\n    }\n\n    /// @notice Returns baseMessage's content field\n    function content(bytes memory payload) public view returns (bytes memory) {\n        return payload.castToBaseMessage().content().clone();\n    }\n\n    function isBaseMessage(bytes memory payload) public pure returns (bool) {\n        return payload.ref().isBaseMessage();\n    }\n\n    // ════════════════════════════════════════════════ FORMATTERS ═════════════════════════════════════════════════════\n\n    function formatBaseMessage(Tips tips_, bytes32 sender_, bytes32 recipient_, Request request_, bytes memory content_)\n        public\n        pure\n        returns (bytes memory)\n    {\n        return BaseMessageLib.formatBaseMessage(tips_, sender_, recipient_, request_, content_);\n    }\n\n    function leaf(bytes memory payload) public pure returns (bytes32) {\n        return payload.castToBaseMessage().leaf();\n    }\n\n    function bodyLeaf(bytes memory payload) public pure returns (bytes32) {\n        return payload.castToBaseMessage().bodyLeaf();\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":"67916:9845:0:-:0;;;;;;;;;;;;;;;-1:-1:-1;;;67916:9845:0;;;;;;;;;;;;;;;;;","srcMapRuntime":"67916: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/BaseMessageHarness.t.sol\":\"MerkleMath\"},\"evmVersion\":\"london\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\"},\"optimizer\":{\"enabled\":true,\"runs\":10000},\"remappings\":[]},\"sources\":{\"solidity/BaseMessageHarness.t.sol\":{\"keccak256\":\"0x0b644d75605ac5a83f42b70984b4f8c78046e7756cf276e43df1e1f8c1c57ce6\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://89e64be85f0b7caad7e5d5fe0d77b92bb4c97bf9542651212fb3563a019d5bac\",\"dweb:/ipfs/QmVsD4QYYzmJVCjC85GjGjbY2Jooz9rZHSJmvp4hkWxxbR\"]}},\"version\":1}"},"hashes":{}},"solidity/BaseMessageHarness.t.sol:RequestLib":{"code":"0x60566037600b82828239805160001a607314602a57634e487b7160e01b600052600060045260246000fd5b30600052607381538281f3fe73000000000000000000000000000000000000000030146080604052600080fdfea26469706673582212207370c1a4c3f111b5538fae934b0b9696b85931ee817a241fb23460bcaccbab2d64736f6c63430008110033","runtime-code":"0x73000000000000000000000000000000000000000030146080604052600080fdfea26469706673582212207370c1a4c3f111b5538fae934b0b9696b85931ee817a241fb23460bcaccbab2d64736f6c63430008110033","info":{"source":"// SPDX-License-Identifier: MIT\npragma solidity =0.8.17 ^0.8.0;\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/Request.sol\n\n/// Request is encoded data with \"message execution request\".\ntype Request is uint192;\n\nusing RequestLib for Request global;\n\n/// Library for formatting _the request part_ of _the base messages_.\n/// - Request represents a message sender requirements for the message execution on the destination chain.\n/// - Request occupies a single storage word, and thus is stored on stack instead of being stored in memory.\n/// \u003e gasDrop field is included for future compatibility and is ignored at the moment.\n///\n/// # Request stack layout (from highest bits to lowest)\n///\n/// | Position   | Field    | Type   | Bytes | Description                                          |\n/// | ---------- | -------- | ------ | ----- | ---------------------------------------------------- |\n/// | (024..012] | gasDrop  | uint96 | 12    | Minimum amount of gas token to drop to the recipient |\n/// | (012..004] | gasLimit | uint64 | 8     | Minimum amount of gas units to supply for execution  |\n/// | (004..000] | version  | uint32 | 4     | Base message version to pass to the recipient        |\n\nlibrary RequestLib {\n    /// @dev Amount of bits to shift to gasDrop field\n    uint192 private constant SHIFT_GAS_DROP = 12 * 8;\n    /// @dev Amount of bits to shift to gasLimit field\n    uint192 private constant SHIFT_GAS_LIMIT = 4 * 8;\n\n    /// @notice Returns an encoded request with the given fields\n    /// @param gasDrop_     Minimum amount of gas token to drop to the recipient (ignored at the moment)\n    /// @param gasLimit_    Minimum amount of gas units to supply for execution\n    /// @param version_     Base message version to pass to the recipient\n    function encodeRequest(uint96 gasDrop_, uint64 gasLimit_, uint32 version_) internal pure returns (Request) {\n        // Casts below are upcasts, so they are safe\n        return Request.wrap(uint192(gasDrop_) \u003c\u003c SHIFT_GAS_DROP | uint192(gasLimit_) \u003c\u003c SHIFT_GAS_LIMIT | version_);\n    }\n\n    /// @notice Wraps the padded encoded request into a Request-typed value.\n    /// @dev The \"padded\" request is simply an encoded request casted to uint256 (highest bits are set to zero).\n    /// Casting to uint256 is done automatically in Solidity, so no extra actions from consumers are needed.\n    /// The highest bits are discarded, so that the contracts dealing with encoded requests\n    /// don't need to be updated, if a new field is added.\n    function wrapPadded(uint256 paddedRequest) internal pure returns (Request) {\n        // Casting to uint192 will truncate the highest bits, which is the behavior we want\n        return Request.wrap(uint192(paddedRequest));\n    }\n\n    /// @notice Returns the requested of gas token to drop to the recipient.\n    function gasDrop(Request request) internal pure returns (uint96) {\n        // Casting to uint96 will truncate the highest bits, which is the behavior we want\n        return uint96(Request.unwrap(request) \u003e\u003e SHIFT_GAS_DROP);\n    }\n\n    /// @notice Returns the requested minimum amount of gas units to supply for execution.\n    function gasLimit(Request request) internal pure returns (uint64) {\n        // Casting to uint64 will truncate the highest bits, which is the behavior we want\n        return uint64(Request.unwrap(request) \u003e\u003e SHIFT_GAS_LIMIT);\n    }\n\n    /// @notice Returns the requested base message version to pass to the recipient.\n    function version(Request request) internal pure returns (uint32) {\n        // Casting to uint32 will truncate the highest bits, which is the behavior we want\n        return uint32(Request.unwrap(request));\n    }\n}\n\n// node_modules/@openzeppelin/contracts/utils/math/SafeCast.sol\n\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/math/SafeCast.sol)\n// This file was procedurally generated from scripts/generate/templates/SafeCast.js.\n\n/**\n * @dev Wrappers over Solidity's uintXX/intXX casting operators with added overflow\n * checks.\n *\n * Downcasting from uint256/int256 in Solidity does not revert on overflow. This can\n * easily result in undesired exploitation or bugs, since developers usually\n * assume that overflows raise errors. `SafeCast` restores this intuition by\n * reverting the transaction when such an operation overflows.\n *\n * Using this library instead of the unchecked operations eliminates an entire\n * class of bugs, so it's recommended to use it always.\n *\n * Can be combined with {SafeMath} and {SignedSafeMath} to extend it to smaller types, by performing\n * all math on `uint256` and `int256` and then downcasting.\n */\nlibrary SafeCast {\n    /**\n     * @dev Returns the downcasted uint248 from uint256, reverting on\n     * overflow (when the input is greater than largest uint248).\n     *\n     * Counterpart to Solidity's `uint248` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 248 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint248(uint256 value) internal pure returns (uint248) {\n        require(value \u003c= type(uint248).max, \"SafeCast: value doesn't fit in 248 bits\");\n        return uint248(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint240 from uint256, reverting on\n     * overflow (when the input is greater than largest uint240).\n     *\n     * Counterpart to Solidity's `uint240` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 240 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint240(uint256 value) internal pure returns (uint240) {\n        require(value \u003c= type(uint240).max, \"SafeCast: value doesn't fit in 240 bits\");\n        return uint240(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint232 from uint256, reverting on\n     * overflow (when the input is greater than largest uint232).\n     *\n     * Counterpart to Solidity's `uint232` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 232 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint232(uint256 value) internal pure returns (uint232) {\n        require(value \u003c= type(uint232).max, \"SafeCast: value doesn't fit in 232 bits\");\n        return uint232(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint224 from uint256, reverting on\n     * overflow (when the input is greater than largest uint224).\n     *\n     * Counterpart to Solidity's `uint224` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 224 bits\n     *\n     * _Available since v4.2._\n     */\n    function toUint224(uint256 value) internal pure returns (uint224) {\n        require(value \u003c= type(uint224).max, \"SafeCast: value doesn't fit in 224 bits\");\n        return uint224(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint216 from uint256, reverting on\n     * overflow (when the input is greater than largest uint216).\n     *\n     * Counterpart to Solidity's `uint216` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 216 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint216(uint256 value) internal pure returns (uint216) {\n        require(value \u003c= type(uint216).max, \"SafeCast: value doesn't fit in 216 bits\");\n        return uint216(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint208 from uint256, reverting on\n     * overflow (when the input is greater than largest uint208).\n     *\n     * Counterpart to Solidity's `uint208` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 208 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint208(uint256 value) internal pure returns (uint208) {\n        require(value \u003c= type(uint208).max, \"SafeCast: value doesn't fit in 208 bits\");\n        return uint208(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint200 from uint256, reverting on\n     * overflow (when the input is greater than largest uint200).\n     *\n     * Counterpart to Solidity's `uint200` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 200 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint200(uint256 value) internal pure returns (uint200) {\n        require(value \u003c= type(uint200).max, \"SafeCast: value doesn't fit in 200 bits\");\n        return uint200(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint192 from uint256, reverting on\n     * overflow (when the input is greater than largest uint192).\n     *\n     * Counterpart to Solidity's `uint192` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 192 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint192(uint256 value) internal pure returns (uint192) {\n        require(value \u003c= type(uint192).max, \"SafeCast: value doesn't fit in 192 bits\");\n        return uint192(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint184 from uint256, reverting on\n     * overflow (when the input is greater than largest uint184).\n     *\n     * Counterpart to Solidity's `uint184` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 184 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint184(uint256 value) internal pure returns (uint184) {\n        require(value \u003c= type(uint184).max, \"SafeCast: value doesn't fit in 184 bits\");\n        return uint184(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint176 from uint256, reverting on\n     * overflow (when the input is greater than largest uint176).\n     *\n     * Counterpart to Solidity's `uint176` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 176 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint176(uint256 value) internal pure returns (uint176) {\n        require(value \u003c= type(uint176).max, \"SafeCast: value doesn't fit in 176 bits\");\n        return uint176(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint168 from uint256, reverting on\n     * overflow (when the input is greater than largest uint168).\n     *\n     * Counterpart to Solidity's `uint168` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 168 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint168(uint256 value) internal pure returns (uint168) {\n        require(value \u003c= type(uint168).max, \"SafeCast: value doesn't fit in 168 bits\");\n        return uint168(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint160 from uint256, reverting on\n     * overflow (when the input is greater than largest uint160).\n     *\n     * Counterpart to Solidity's `uint160` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 160 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint160(uint256 value) internal pure returns (uint160) {\n        require(value \u003c= type(uint160).max, \"SafeCast: value doesn't fit in 160 bits\");\n        return uint160(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint152 from uint256, reverting on\n     * overflow (when the input is greater than largest uint152).\n     *\n     * Counterpart to Solidity's `uint152` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 152 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint152(uint256 value) internal pure returns (uint152) {\n        require(value \u003c= type(uint152).max, \"SafeCast: value doesn't fit in 152 bits\");\n        return uint152(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint144 from uint256, reverting on\n     * overflow (when the input is greater than largest uint144).\n     *\n     * Counterpart to Solidity's `uint144` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 144 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint144(uint256 value) internal pure returns (uint144) {\n        require(value \u003c= type(uint144).max, \"SafeCast: value doesn't fit in 144 bits\");\n        return uint144(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint136 from uint256, reverting on\n     * overflow (when the input is greater than largest uint136).\n     *\n     * Counterpart to Solidity's `uint136` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 136 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint136(uint256 value) internal pure returns (uint136) {\n        require(value \u003c= type(uint136).max, \"SafeCast: value doesn't fit in 136 bits\");\n        return uint136(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint128 from uint256, reverting on\n     * overflow (when the input is greater than largest uint128).\n     *\n     * Counterpart to Solidity's `uint128` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 128 bits\n     *\n     * _Available since v2.5._\n     */\n    function toUint128(uint256 value) internal pure returns (uint128) {\n        require(value \u003c= type(uint128).max, \"SafeCast: value doesn't fit in 128 bits\");\n        return uint128(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint120 from uint256, reverting on\n     * overflow (when the input is greater than largest uint120).\n     *\n     * Counterpart to Solidity's `uint120` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 120 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint120(uint256 value) internal pure returns (uint120) {\n        require(value \u003c= type(uint120).max, \"SafeCast: value doesn't fit in 120 bits\");\n        return uint120(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint112 from uint256, reverting on\n     * overflow (when the input is greater than largest uint112).\n     *\n     * Counterpart to Solidity's `uint112` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 112 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint112(uint256 value) internal pure returns (uint112) {\n        require(value \u003c= type(uint112).max, \"SafeCast: value doesn't fit in 112 bits\");\n        return uint112(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint104 from uint256, reverting on\n     * overflow (when the input is greater than largest uint104).\n     *\n     * Counterpart to Solidity's `uint104` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 104 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint104(uint256 value) internal pure returns (uint104) {\n        require(value \u003c= type(uint104).max, \"SafeCast: value doesn't fit in 104 bits\");\n        return uint104(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint96 from uint256, reverting on\n     * overflow (when the input is greater than largest uint96).\n     *\n     * Counterpart to Solidity's `uint96` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 96 bits\n     *\n     * _Available since v4.2._\n     */\n    function toUint96(uint256 value) internal pure returns (uint96) {\n        require(value \u003c= type(uint96).max, \"SafeCast: value doesn't fit in 96 bits\");\n        return uint96(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint88 from uint256, reverting on\n     * overflow (when the input is greater than largest uint88).\n     *\n     * Counterpart to Solidity's `uint88` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 88 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint88(uint256 value) internal pure returns (uint88) {\n        require(value \u003c= type(uint88).max, \"SafeCast: value doesn't fit in 88 bits\");\n        return uint88(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint80 from uint256, reverting on\n     * overflow (when the input is greater than largest uint80).\n     *\n     * Counterpart to Solidity's `uint80` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 80 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint80(uint256 value) internal pure returns (uint80) {\n        require(value \u003c= type(uint80).max, \"SafeCast: value doesn't fit in 80 bits\");\n        return uint80(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint72 from uint256, reverting on\n     * overflow (when the input is greater than largest uint72).\n     *\n     * Counterpart to Solidity's `uint72` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 72 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint72(uint256 value) internal pure returns (uint72) {\n        require(value \u003c= type(uint72).max, \"SafeCast: value doesn't fit in 72 bits\");\n        return uint72(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint64 from uint256, reverting on\n     * overflow (when the input is greater than largest uint64).\n     *\n     * Counterpart to Solidity's `uint64` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 64 bits\n     *\n     * _Available since v2.5._\n     */\n    function toUint64(uint256 value) internal pure returns (uint64) {\n        require(value \u003c= type(uint64).max, \"SafeCast: value doesn't fit in 64 bits\");\n        return uint64(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint56 from uint256, reverting on\n     * overflow (when the input is greater than largest uint56).\n     *\n     * Counterpart to Solidity's `uint56` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 56 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint56(uint256 value) internal pure returns (uint56) {\n        require(value \u003c= type(uint56).max, \"SafeCast: value doesn't fit in 56 bits\");\n        return uint56(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint48 from uint256, reverting on\n     * overflow (when the input is greater than largest uint48).\n     *\n     * Counterpart to Solidity's `uint48` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 48 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint48(uint256 value) internal pure returns (uint48) {\n        require(value \u003c= type(uint48).max, \"SafeCast: value doesn't fit in 48 bits\");\n        return uint48(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint40 from uint256, reverting on\n     * overflow (when the input is greater than largest uint40).\n     *\n     * Counterpart to Solidity's `uint40` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 40 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint40(uint256 value) internal pure returns (uint40) {\n        require(value \u003c= type(uint40).max, \"SafeCast: value doesn't fit in 40 bits\");\n        return uint40(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint32 from uint256, reverting on\n     * overflow (when the input is greater than largest uint32).\n     *\n     * Counterpart to Solidity's `uint32` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 32 bits\n     *\n     * _Available since v2.5._\n     */\n    function toUint32(uint256 value) internal pure returns (uint32) {\n        require(value \u003c= type(uint32).max, \"SafeCast: value doesn't fit in 32 bits\");\n        return uint32(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint24 from uint256, reverting on\n     * overflow (when the input is greater than largest uint24).\n     *\n     * Counterpart to Solidity's `uint24` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 24 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint24(uint256 value) internal pure returns (uint24) {\n        require(value \u003c= type(uint24).max, \"SafeCast: value doesn't fit in 24 bits\");\n        return uint24(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint16 from uint256, reverting on\n     * overflow (when the input is greater than largest uint16).\n     *\n     * Counterpart to Solidity's `uint16` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 16 bits\n     *\n     * _Available since v2.5._\n     */\n    function toUint16(uint256 value) internal pure returns (uint16) {\n        require(value \u003c= type(uint16).max, \"SafeCast: value doesn't fit in 16 bits\");\n        return uint16(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint8 from uint256, reverting on\n     * overflow (when the input is greater than largest uint8).\n     *\n     * Counterpart to Solidity's `uint8` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 8 bits\n     *\n     * _Available since v2.5._\n     */\n    function toUint8(uint256 value) internal pure returns (uint8) {\n        require(value \u003c= type(uint8).max, \"SafeCast: value doesn't fit in 8 bits\");\n        return uint8(value);\n    }\n\n    /**\n     * @dev Converts a signed int256 into an unsigned uint256.\n     *\n     * Requirements:\n     *\n     * - input must be greater than or equal to 0.\n     *\n     * _Available since v3.0._\n     */\n    function toUint256(int256 value) internal pure returns (uint256) {\n        require(value \u003e= 0, \"SafeCast: value must be positive\");\n        return uint256(value);\n    }\n\n    /**\n     * @dev Returns the downcasted int248 from int256, reverting on\n     * overflow (when the input is less than smallest int248 or\n     * greater than largest int248).\n     *\n     * Counterpart to Solidity's `int248` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 248 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt248(int256 value) internal pure returns (int248 downcasted) {\n        downcasted = int248(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 248 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int240 from int256, reverting on\n     * overflow (when the input is less than smallest int240 or\n     * greater than largest int240).\n     *\n     * Counterpart to Solidity's `int240` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 240 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt240(int256 value) internal pure returns (int240 downcasted) {\n        downcasted = int240(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 240 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int232 from int256, reverting on\n     * overflow (when the input is less than smallest int232 or\n     * greater than largest int232).\n     *\n     * Counterpart to Solidity's `int232` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 232 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt232(int256 value) internal pure returns (int232 downcasted) {\n        downcasted = int232(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 232 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int224 from int256, reverting on\n     * overflow (when the input is less than smallest int224 or\n     * greater than largest int224).\n     *\n     * Counterpart to Solidity's `int224` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 224 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt224(int256 value) internal pure returns (int224 downcasted) {\n        downcasted = int224(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 224 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int216 from int256, reverting on\n     * overflow (when the input is less than smallest int216 or\n     * greater than largest int216).\n     *\n     * Counterpart to Solidity's `int216` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 216 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt216(int256 value) internal pure returns (int216 downcasted) {\n        downcasted = int216(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 216 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int208 from int256, reverting on\n     * overflow (when the input is less than smallest int208 or\n     * greater than largest int208).\n     *\n     * Counterpart to Solidity's `int208` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 208 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt208(int256 value) internal pure returns (int208 downcasted) {\n        downcasted = int208(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 208 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int200 from int256, reverting on\n     * overflow (when the input is less than smallest int200 or\n     * greater than largest int200).\n     *\n     * Counterpart to Solidity's `int200` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 200 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt200(int256 value) internal pure returns (int200 downcasted) {\n        downcasted = int200(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 200 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int192 from int256, reverting on\n     * overflow (when the input is less than smallest int192 or\n     * greater than largest int192).\n     *\n     * Counterpart to Solidity's `int192` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 192 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt192(int256 value) internal pure returns (int192 downcasted) {\n        downcasted = int192(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 192 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int184 from int256, reverting on\n     * overflow (when the input is less than smallest int184 or\n     * greater than largest int184).\n     *\n     * Counterpart to Solidity's `int184` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 184 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt184(int256 value) internal pure returns (int184 downcasted) {\n        downcasted = int184(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 184 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int176 from int256, reverting on\n     * overflow (when the input is less than smallest int176 or\n     * greater than largest int176).\n     *\n     * Counterpart to Solidity's `int176` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 176 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt176(int256 value) internal pure returns (int176 downcasted) {\n        downcasted = int176(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 176 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int168 from int256, reverting on\n     * overflow (when the input is less than smallest int168 or\n     * greater than largest int168).\n     *\n     * Counterpart to Solidity's `int168` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 168 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt168(int256 value) internal pure returns (int168 downcasted) {\n        downcasted = int168(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 168 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int160 from int256, reverting on\n     * overflow (when the input is less than smallest int160 or\n     * greater than largest int160).\n     *\n     * Counterpart to Solidity's `int160` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 160 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt160(int256 value) internal pure returns (int160 downcasted) {\n        downcasted = int160(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 160 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int152 from int256, reverting on\n     * overflow (when the input is less than smallest int152 or\n     * greater than largest int152).\n     *\n     * Counterpart to Solidity's `int152` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 152 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt152(int256 value) internal pure returns (int152 downcasted) {\n        downcasted = int152(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 152 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int144 from int256, reverting on\n     * overflow (when the input is less than smallest int144 or\n     * greater than largest int144).\n     *\n     * Counterpart to Solidity's `int144` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 144 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt144(int256 value) internal pure returns (int144 downcasted) {\n        downcasted = int144(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 144 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int136 from int256, reverting on\n     * overflow (when the input is less than smallest int136 or\n     * greater than largest int136).\n     *\n     * Counterpart to Solidity's `int136` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 136 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt136(int256 value) internal pure returns (int136 downcasted) {\n        downcasted = int136(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 136 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int128 from int256, reverting on\n     * overflow (when the input is less than smallest int128 or\n     * greater than largest int128).\n     *\n     * Counterpart to Solidity's `int128` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 128 bits\n     *\n     * _Available since v3.1._\n     */\n    function toInt128(int256 value) internal pure returns (int128 downcasted) {\n        downcasted = int128(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 128 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int120 from int256, reverting on\n     * overflow (when the input is less than smallest int120 or\n     * greater than largest int120).\n     *\n     * Counterpart to Solidity's `int120` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 120 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt120(int256 value) internal pure returns (int120 downcasted) {\n        downcasted = int120(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 120 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int112 from int256, reverting on\n     * overflow (when the input is less than smallest int112 or\n     * greater than largest int112).\n     *\n     * Counterpart to Solidity's `int112` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 112 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt112(int256 value) internal pure returns (int112 downcasted) {\n        downcasted = int112(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 112 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int104 from int256, reverting on\n     * overflow (when the input is less than smallest int104 or\n     * greater than largest int104).\n     *\n     * Counterpart to Solidity's `int104` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 104 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt104(int256 value) internal pure returns (int104 downcasted) {\n        downcasted = int104(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 104 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int96 from int256, reverting on\n     * overflow (when the input is less than smallest int96 or\n     * greater than largest int96).\n     *\n     * Counterpart to Solidity's `int96` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 96 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt96(int256 value) internal pure returns (int96 downcasted) {\n        downcasted = int96(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 96 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int88 from int256, reverting on\n     * overflow (when the input is less than smallest int88 or\n     * greater than largest int88).\n     *\n     * Counterpart to Solidity's `int88` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 88 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt88(int256 value) internal pure returns (int88 downcasted) {\n        downcasted = int88(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 88 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int80 from int256, reverting on\n     * overflow (when the input is less than smallest int80 or\n     * greater than largest int80).\n     *\n     * Counterpart to Solidity's `int80` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 80 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt80(int256 value) internal pure returns (int80 downcasted) {\n        downcasted = int80(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 80 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int72 from int256, reverting on\n     * overflow (when the input is less than smallest int72 or\n     * greater than largest int72).\n     *\n     * Counterpart to Solidity's `int72` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 72 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt72(int256 value) internal pure returns (int72 downcasted) {\n        downcasted = int72(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 72 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int64 from int256, reverting on\n     * overflow (when the input is less than smallest int64 or\n     * greater than largest int64).\n     *\n     * Counterpart to Solidity's `int64` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 64 bits\n     *\n     * _Available since v3.1._\n     */\n    function toInt64(int256 value) internal pure returns (int64 downcasted) {\n        downcasted = int64(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 64 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int56 from int256, reverting on\n     * overflow (when the input is less than smallest int56 or\n     * greater than largest int56).\n     *\n     * Counterpart to Solidity's `int56` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 56 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt56(int256 value) internal pure returns (int56 downcasted) {\n        downcasted = int56(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 56 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int48 from int256, reverting on\n     * overflow (when the input is less than smallest int48 or\n     * greater than largest int48).\n     *\n     * Counterpart to Solidity's `int48` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 48 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt48(int256 value) internal pure returns (int48 downcasted) {\n        downcasted = int48(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 48 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int40 from int256, reverting on\n     * overflow (when the input is less than smallest int40 or\n     * greater than largest int40).\n     *\n     * Counterpart to Solidity's `int40` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 40 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt40(int256 value) internal pure returns (int40 downcasted) {\n        downcasted = int40(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 40 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int32 from int256, reverting on\n     * overflow (when the input is less than smallest int32 or\n     * greater than largest int32).\n     *\n     * Counterpart to Solidity's `int32` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 32 bits\n     *\n     * _Available since v3.1._\n     */\n    function toInt32(int256 value) internal pure returns (int32 downcasted) {\n        downcasted = int32(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 32 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int24 from int256, reverting on\n     * overflow (when the input is less than smallest int24 or\n     * greater than largest int24).\n     *\n     * Counterpart to Solidity's `int24` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 24 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt24(int256 value) internal pure returns (int24 downcasted) {\n        downcasted = int24(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 24 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int16 from int256, reverting on\n     * overflow (when the input is less than smallest int16 or\n     * greater than largest int16).\n     *\n     * Counterpart to Solidity's `int16` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 16 bits\n     *\n     * _Available since v3.1._\n     */\n    function toInt16(int256 value) internal pure returns (int16 downcasted) {\n        downcasted = int16(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 16 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int8 from int256, reverting on\n     * overflow (when the input is less than smallest int8 or\n     * greater than largest int8).\n     *\n     * Counterpart to Solidity's `int8` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 8 bits\n     *\n     * _Available since v3.1._\n     */\n    function toInt8(int256 value) internal pure returns (int8 downcasted) {\n        downcasted = int8(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 8 bits\");\n    }\n\n    /**\n     * @dev Converts an unsigned uint256 into a signed int256.\n     *\n     * Requirements:\n     *\n     * - input must be less than or equal to maxInt256.\n     *\n     * _Available since v3.0._\n     */\n    function toInt256(uint256 value) internal pure returns (int256) {\n        // Note: Unsafe cast below is okay because `type(int256).max` is guaranteed to be positive\n        require(value \u003c= uint256(type(int256).max), \"SafeCast: value doesn't fit in an int256\");\n        return int256(value);\n    }\n}\n\n// 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/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// contracts/libs/memory/BaseMessage.sol\n\n/// BaseMessage is a memory view over the base message supported by Origin-Destination\ntype BaseMessage is uint256;\n\nusing BaseMessageLib for BaseMessage global;\n\n/// BaseMessage structure represents a base message sent via the Origin-Destination contracts.\n/// - It only contains data relevant to the base message, the rest of data is encoded in the message header.\n/// - `sender` and `recipient` for EVM chains are EVM addresses casted to bytes32, while preserving left-alignment.\n/// - `tips` and `request` parameters are specified by a message sender\n/// \u003e Origin will calculate minimum tips for given request and content length, and will reject messages with tips\n/// lower than that.\n///\n/// # Memory layout of BaseMessage fields\n///\n/// | Position   | Field     | Type    | Bytes | Description                            |\n/// | ---------- | --------- | ------- | ----- | -------------------------------------- |\n/// | [000..032) | tips      | uint256 | 32    | Encoded tips paid on origin chain      |\n/// | [032..064) | sender    | bytes32 | 32    | Sender address on origin chain         |\n/// | [064..096) | recipient | bytes32 | 32    | Recipient address on destination chain |\n/// | [096..116) | request   | uint160 | 20    | Encoded request for message execution  |\n/// | [104..AAA) | content   | bytes   | ??    | Content to be passed to recipient      |\nlibrary BaseMessageLib {\n    using MemViewLib for bytes;\n\n    /// @dev The variables below are not supposed to be used outside of the library directly.\n    uint256 private constant OFFSET_TIPS = 0;\n    uint256 private constant OFFSET_SENDER = 32;\n    uint256 private constant OFFSET_RECIPIENT = 64;\n    uint256 private constant OFFSET_REQUEST = OFFSET_RECIPIENT + TIPS_LENGTH;\n    uint256 private constant OFFSET_CONTENT = OFFSET_REQUEST + REQUEST_LENGTH;\n\n    // ═══════════════════════════════════════════════ BASE MESSAGE ════════════════════════════════════════════════════\n\n    /**\n     * @notice Returns a formatted BaseMessage payload with provided fields.\n     * @param tips_         Encoded tips information\n     * @param sender_       Sender address on origin chain\n     * @param recipient_    Recipient address on destination chain\n     * @param request_      Encoded request for message execution\n     * @param content_      Raw content to be passed to recipient on destination chain\n     * @return Formatted base message\n     */\n    function formatBaseMessage(Tips tips_, bytes32 sender_, bytes32 recipient_, Request request_, bytes memory content_)\n        internal\n        pure\n        returns (bytes memory)\n    {\n        return abi.encodePacked(tips_, sender_, recipient_, request_, content_);\n    }\n\n    /**\n     * @notice Returns a BaseMessage view over the given payload.\n     * @dev Will revert if the payload is not a base message.\n     */\n    function castToBaseMessage(bytes memory payload) internal pure returns (BaseMessage) {\n        return castToBaseMessage(payload.ref());\n    }\n\n    /**\n     * @notice Casts a memory view to a BaseMessage view.\n     * @dev Will revert if the memory view is not over a base message payload.\n     */\n    function castToBaseMessage(MemView memView) internal pure returns (BaseMessage) {\n        if (!isBaseMessage(memView)) revert UnformattedBaseMessage();\n        return BaseMessage.wrap(MemView.unwrap(memView));\n    }\n\n    /// @notice Checks that a payload is a formatted BaseMessage.\n    function isBaseMessage(MemView memView) internal pure returns (bool) {\n        // Check if sender, recipient, tips fields exist\n        return (memView.len() \u003e= OFFSET_CONTENT);\n        // Content could be empty, so we don't check that\n    }\n\n    /// @notice Convenience shortcut for unwrapping a view.\n    function unwrap(BaseMessage baseMessage) internal pure returns (MemView) {\n        return MemView.wrap(BaseMessage.unwrap(baseMessage));\n    }\n\n    /// @notice Returns baseMessage's hash: a leaf to be inserted in the \"Message mini-Merkle tree\".\n    function leaf(BaseMessage baseMessage) internal pure returns (bytes32) {\n        // We hash \"tips\" and \"everything but tips\" to make tips proofs easier to verify\n        return MerkleMath.getParent(baseMessage.tips().leaf(), baseMessage.bodyLeaf());\n    }\n\n    /// @notice Returns hash for the \"everything but tips\" part of the base message.\n    function bodyLeaf(BaseMessage baseMessage) internal pure returns (bytes32) {\n        return baseMessage.unwrap().sliceFrom({index_: OFFSET_SENDER}).keccak();\n    }\n\n    // ═══════════════════════════════════════════ BASE MESSAGE SLICING ════════════════════════════════════════════════\n\n    /// @notice Returns encoded tips paid on origin chain.\n    function tips(BaseMessage baseMessage) internal pure returns (Tips) {\n        return TipsLib.wrapPadded((baseMessage.unwrap().indexUint({index_: OFFSET_TIPS, bytes_: TIPS_LENGTH})));\n    }\n\n    /// @notice Returns sender address on origin chain.\n    function sender(BaseMessage baseMessage) internal pure returns (bytes32) {\n        return baseMessage.unwrap().index({index_: OFFSET_SENDER, bytes_: 32});\n    }\n\n    /// @notice Returns recipient address on destination chain.\n    function recipient(BaseMessage baseMessage) internal pure returns (bytes32) {\n        return baseMessage.unwrap().index({index_: OFFSET_RECIPIENT, bytes_: 32});\n    }\n\n    /// @notice Returns an encoded request for message execution on destination chain.\n    function request(BaseMessage baseMessage) internal pure returns (Request) {\n        return RequestLib.wrapPadded((baseMessage.unwrap().indexUint({index_: OFFSET_REQUEST, bytes_: REQUEST_LENGTH})));\n    }\n\n    /// @notice Returns an untyped memory view over the content to be passed to recipient.\n    function content(BaseMessage baseMessage) internal pure returns (MemView) {\n        return baseMessage.unwrap().sliceFrom({index_: OFFSET_CONTENT});\n    }\n}\n\n// test/harnesses/libs/memory/BaseMessageHarness.t.sol\n\n// solhint-disable ordering\n/**\n * @notice Exposes BaseMessage methods for testing against golang.\n */\ncontract BaseMessageHarness {\n    using BaseMessageLib for bytes;\n    using BaseMessageLib for MemView;\n    using MemViewLib for bytes;\n\n    // Note: we don't add an empty test() function here, as it currently leads\n    // to zero coverage on the corresponding library.\n\n    // ══════════════════════════════════════════════════ GETTERS ══════════════════════════════════════════════════════\n\n    function castToBaseMessage(bytes memory payload) public view returns (bytes memory) {\n        // Walkaround to get the forge coverage working on libraries, see\n        // https://github.com/foundry-rs/foundry/pull/3128#issuecomment-1241245086\n        BaseMessage baseMessage = BaseMessageLib.castToBaseMessage(payload);\n        return baseMessage.unwrap().clone();\n    }\n\n    /// @notice Returns baseMessage's sender field\n    function sender(bytes memory payload) public pure returns (bytes32) {\n        return payload.castToBaseMessage().sender();\n    }\n\n    /// @notice Returns baseMessage's recipient field as bytes32\n    function recipient(bytes memory payload) public pure returns (bytes32) {\n        return payload.castToBaseMessage().recipient();\n    }\n\n    /// @notice Returns baseMessage's tips field\n    function tips(bytes memory payload) public pure returns (uint256) {\n        return Tips.unwrap(payload.castToBaseMessage().tips());\n    }\n\n    /// @notice Returns baseMessage's request field\n    function request(bytes memory payload) public pure returns (uint192) {\n        return Request.unwrap(payload.castToBaseMessage().request());\n    }\n\n    /// @notice Returns baseMessage's content field\n    function content(bytes memory payload) public view returns (bytes memory) {\n        return payload.castToBaseMessage().content().clone();\n    }\n\n    function isBaseMessage(bytes memory payload) public pure returns (bool) {\n        return payload.ref().isBaseMessage();\n    }\n\n    // ════════════════════════════════════════════════ FORMATTERS ═════════════════════════════════════════════════════\n\n    function formatBaseMessage(Tips tips_, bytes32 sender_, bytes32 recipient_, Request request_, bytes memory content_)\n        public\n        pure\n        returns (bytes memory)\n    {\n        return BaseMessageLib.formatBaseMessage(tips_, sender_, recipient_, request_, content_);\n    }\n\n    function leaf(bytes memory payload) public pure returns (bytes32) {\n        return payload.castToBaseMessage().leaf();\n    }\n\n    function bodyLeaf(bytes memory payload) public pure returns (bytes32) {\n        return payload.castToBaseMessage().bodyLeaf();\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":"10042:2478:0:-:0;;;;;;;;;;;;;;;-1:-1:-1;;;10042:2478:0;;;;;;;;;;;;;;;;;","srcMapRuntime":"10042:2478:0:-:0;;;;;;;;","abiDefinition":[],"userDoc":{"kind":"user","methods":{},"notice":"Library for formatting _the request part_ of _the base messages_. - Request represents a message sender requirements for the message execution on the destination chain. - Request occupies a single storage word, and thus is stored on stack instead of being stored in memory. \u003e gasDrop field is included for future compatibility and is ignored at the moment. # Request stack layout (from highest bits to lowest) | Position   | Field    | Type   | Bytes | Description                                          | | ---------- | -------- | ------ | ----- | ---------------------------------------------------- | | (024..012] | gasDrop  | uint96 | 12    | Minimum amount of gas token to drop to the recipient | | (012..004] | gasLimit | uint64 | 8     | Minimum amount of gas units to supply for execution  | | (004..000] | version  | uint32 | 4     | Base message version to pass to the recipient        |","version":1},"developerDoc":{"kind":"dev","methods":{},"stateVariables":{"SHIFT_GAS_DROP":{"details":"Amount of bits to shift to gasDrop field"},"SHIFT_GAS_LIMIT":{"details":"Amount of bits to shift to gasLimit field"}},"version":1},"metadata":"{\"compiler\":{\"version\":\"0.8.17+commit.8df45f5f\"},\"language\":\"Solidity\",\"output\":{\"abi\":[],\"devdoc\":{\"kind\":\"dev\",\"methods\":{},\"stateVariables\":{\"SHIFT_GAS_DROP\":{\"details\":\"Amount of bits to shift to gasDrop field\"},\"SHIFT_GAS_LIMIT\":{\"details\":\"Amount of bits to shift to gasLimit field\"}},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"notice\":\"Library for formatting _the request part_ of _the base messages_. - Request represents a message sender requirements for the message execution on the destination chain. - Request occupies a single storage word, and thus is stored on stack instead of being stored in memory. \u003e gasDrop field is included for future compatibility and is ignored at the moment. # Request stack layout (from highest bits to lowest) | Position   | Field    | Type   | Bytes | Description                                          | | ---------- | -------- | ------ | ----- | ---------------------------------------------------- | | (024..012] | gasDrop  | uint96 | 12    | Minimum amount of gas token to drop to the recipient | | (012..004] | gasLimit | uint64 | 8     | Minimum amount of gas units to supply for execution  | | (004..000] | version  | uint32 | 4     | Base message version to pass to the recipient        |\",\"version\":1}},\"settings\":{\"compilationTarget\":{\"solidity/BaseMessageHarness.t.sol\":\"RequestLib\"},\"evmVersion\":\"london\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\"},\"optimizer\":{\"enabled\":true,\"runs\":10000},\"remappings\":[]},\"sources\":{\"solidity/BaseMessageHarness.t.sol\":{\"keccak256\":\"0x0b644d75605ac5a83f42b70984b4f8c78046e7756cf276e43df1e1f8c1c57ce6\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://89e64be85f0b7caad7e5d5fe0d77b92bb4c97bf9542651212fb3563a019d5bac\",\"dweb:/ipfs/QmVsD4QYYzmJVCjC85GjGjbY2Jooz9rZHSJmvp4hkWxxbR\"]}},\"version\":1}"},"hashes":{}},"solidity/BaseMessageHarness.t.sol:SafeCast":{"code":"0x60566037600b82828239805160001a607314602a57634e487b7160e01b600052600060045260246000fd5b30600052607381538281f3fe73000000000000000000000000000000000000000030146080604052600080fdfea264697066735822122094037a80a6f851fd59815dd73375e751e20926d3b60e5ef4e815ad997ea9b13064736f6c63430008110033","runtime-code":"0x73000000000000000000000000000000000000000030146080604052600080fdfea264697066735822122094037a80a6f851fd59815dd73375e751e20926d3b60e5ef4e815ad997ea9b13064736f6c63430008110033","info":{"source":"// SPDX-License-Identifier: MIT\npragma solidity =0.8.17 ^0.8.0;\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/Request.sol\n\n/// Request is encoded data with \"message execution request\".\ntype Request is uint192;\n\nusing RequestLib for Request global;\n\n/// Library for formatting _the request part_ of _the base messages_.\n/// - Request represents a message sender requirements for the message execution on the destination chain.\n/// - Request occupies a single storage word, and thus is stored on stack instead of being stored in memory.\n/// \u003e gasDrop field is included for future compatibility and is ignored at the moment.\n///\n/// # Request stack layout (from highest bits to lowest)\n///\n/// | Position   | Field    | Type   | Bytes | Description                                          |\n/// | ---------- | -------- | ------ | ----- | ---------------------------------------------------- |\n/// | (024..012] | gasDrop  | uint96 | 12    | Minimum amount of gas token to drop to the recipient |\n/// | (012..004] | gasLimit | uint64 | 8     | Minimum amount of gas units to supply for execution  |\n/// | (004..000] | version  | uint32 | 4     | Base message version to pass to the recipient        |\n\nlibrary RequestLib {\n    /// @dev Amount of bits to shift to gasDrop field\n    uint192 private constant SHIFT_GAS_DROP = 12 * 8;\n    /// @dev Amount of bits to shift to gasLimit field\n    uint192 private constant SHIFT_GAS_LIMIT = 4 * 8;\n\n    /// @notice Returns an encoded request with the given fields\n    /// @param gasDrop_     Minimum amount of gas token to drop to the recipient (ignored at the moment)\n    /// @param gasLimit_    Minimum amount of gas units to supply for execution\n    /// @param version_     Base message version to pass to the recipient\n    function encodeRequest(uint96 gasDrop_, uint64 gasLimit_, uint32 version_) internal pure returns (Request) {\n        // Casts below are upcasts, so they are safe\n        return Request.wrap(uint192(gasDrop_) \u003c\u003c SHIFT_GAS_DROP | uint192(gasLimit_) \u003c\u003c SHIFT_GAS_LIMIT | version_);\n    }\n\n    /// @notice Wraps the padded encoded request into a Request-typed value.\n    /// @dev The \"padded\" request is simply an encoded request casted to uint256 (highest bits are set to zero).\n    /// Casting to uint256 is done automatically in Solidity, so no extra actions from consumers are needed.\n    /// The highest bits are discarded, so that the contracts dealing with encoded requests\n    /// don't need to be updated, if a new field is added.\n    function wrapPadded(uint256 paddedRequest) internal pure returns (Request) {\n        // Casting to uint192 will truncate the highest bits, which is the behavior we want\n        return Request.wrap(uint192(paddedRequest));\n    }\n\n    /// @notice Returns the requested of gas token to drop to the recipient.\n    function gasDrop(Request request) internal pure returns (uint96) {\n        // Casting to uint96 will truncate the highest bits, which is the behavior we want\n        return uint96(Request.unwrap(request) \u003e\u003e SHIFT_GAS_DROP);\n    }\n\n    /// @notice Returns the requested minimum amount of gas units to supply for execution.\n    function gasLimit(Request request) internal pure returns (uint64) {\n        // Casting to uint64 will truncate the highest bits, which is the behavior we want\n        return uint64(Request.unwrap(request) \u003e\u003e SHIFT_GAS_LIMIT);\n    }\n\n    /// @notice Returns the requested base message version to pass to the recipient.\n    function version(Request request) internal pure returns (uint32) {\n        // Casting to uint32 will truncate the highest bits, which is the behavior we want\n        return uint32(Request.unwrap(request));\n    }\n}\n\n// node_modules/@openzeppelin/contracts/utils/math/SafeCast.sol\n\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/math/SafeCast.sol)\n// This file was procedurally generated from scripts/generate/templates/SafeCast.js.\n\n/**\n * @dev Wrappers over Solidity's uintXX/intXX casting operators with added overflow\n * checks.\n *\n * Downcasting from uint256/int256 in Solidity does not revert on overflow. This can\n * easily result in undesired exploitation or bugs, since developers usually\n * assume that overflows raise errors. `SafeCast` restores this intuition by\n * reverting the transaction when such an operation overflows.\n *\n * Using this library instead of the unchecked operations eliminates an entire\n * class of bugs, so it's recommended to use it always.\n *\n * Can be combined with {SafeMath} and {SignedSafeMath} to extend it to smaller types, by performing\n * all math on `uint256` and `int256` and then downcasting.\n */\nlibrary SafeCast {\n    /**\n     * @dev Returns the downcasted uint248 from uint256, reverting on\n     * overflow (when the input is greater than largest uint248).\n     *\n     * Counterpart to Solidity's `uint248` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 248 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint248(uint256 value) internal pure returns (uint248) {\n        require(value \u003c= type(uint248).max, \"SafeCast: value doesn't fit in 248 bits\");\n        return uint248(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint240 from uint256, reverting on\n     * overflow (when the input is greater than largest uint240).\n     *\n     * Counterpart to Solidity's `uint240` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 240 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint240(uint256 value) internal pure returns (uint240) {\n        require(value \u003c= type(uint240).max, \"SafeCast: value doesn't fit in 240 bits\");\n        return uint240(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint232 from uint256, reverting on\n     * overflow (when the input is greater than largest uint232).\n     *\n     * Counterpart to Solidity's `uint232` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 232 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint232(uint256 value) internal pure returns (uint232) {\n        require(value \u003c= type(uint232).max, \"SafeCast: value doesn't fit in 232 bits\");\n        return uint232(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint224 from uint256, reverting on\n     * overflow (when the input is greater than largest uint224).\n     *\n     * Counterpart to Solidity's `uint224` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 224 bits\n     *\n     * _Available since v4.2._\n     */\n    function toUint224(uint256 value) internal pure returns (uint224) {\n        require(value \u003c= type(uint224).max, \"SafeCast: value doesn't fit in 224 bits\");\n        return uint224(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint216 from uint256, reverting on\n     * overflow (when the input is greater than largest uint216).\n     *\n     * Counterpart to Solidity's `uint216` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 216 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint216(uint256 value) internal pure returns (uint216) {\n        require(value \u003c= type(uint216).max, \"SafeCast: value doesn't fit in 216 bits\");\n        return uint216(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint208 from uint256, reverting on\n     * overflow (when the input is greater than largest uint208).\n     *\n     * Counterpart to Solidity's `uint208` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 208 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint208(uint256 value) internal pure returns (uint208) {\n        require(value \u003c= type(uint208).max, \"SafeCast: value doesn't fit in 208 bits\");\n        return uint208(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint200 from uint256, reverting on\n     * overflow (when the input is greater than largest uint200).\n     *\n     * Counterpart to Solidity's `uint200` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 200 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint200(uint256 value) internal pure returns (uint200) {\n        require(value \u003c= type(uint200).max, \"SafeCast: value doesn't fit in 200 bits\");\n        return uint200(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint192 from uint256, reverting on\n     * overflow (when the input is greater than largest uint192).\n     *\n     * Counterpart to Solidity's `uint192` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 192 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint192(uint256 value) internal pure returns (uint192) {\n        require(value \u003c= type(uint192).max, \"SafeCast: value doesn't fit in 192 bits\");\n        return uint192(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint184 from uint256, reverting on\n     * overflow (when the input is greater than largest uint184).\n     *\n     * Counterpart to Solidity's `uint184` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 184 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint184(uint256 value) internal pure returns (uint184) {\n        require(value \u003c= type(uint184).max, \"SafeCast: value doesn't fit in 184 bits\");\n        return uint184(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint176 from uint256, reverting on\n     * overflow (when the input is greater than largest uint176).\n     *\n     * Counterpart to Solidity's `uint176` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 176 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint176(uint256 value) internal pure returns (uint176) {\n        require(value \u003c= type(uint176).max, \"SafeCast: value doesn't fit in 176 bits\");\n        return uint176(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint168 from uint256, reverting on\n     * overflow (when the input is greater than largest uint168).\n     *\n     * Counterpart to Solidity's `uint168` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 168 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint168(uint256 value) internal pure returns (uint168) {\n        require(value \u003c= type(uint168).max, \"SafeCast: value doesn't fit in 168 bits\");\n        return uint168(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint160 from uint256, reverting on\n     * overflow (when the input is greater than largest uint160).\n     *\n     * Counterpart to Solidity's `uint160` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 160 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint160(uint256 value) internal pure returns (uint160) {\n        require(value \u003c= type(uint160).max, \"SafeCast: value doesn't fit in 160 bits\");\n        return uint160(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint152 from uint256, reverting on\n     * overflow (when the input is greater than largest uint152).\n     *\n     * Counterpart to Solidity's `uint152` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 152 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint152(uint256 value) internal pure returns (uint152) {\n        require(value \u003c= type(uint152).max, \"SafeCast: value doesn't fit in 152 bits\");\n        return uint152(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint144 from uint256, reverting on\n     * overflow (when the input is greater than largest uint144).\n     *\n     * Counterpart to Solidity's `uint144` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 144 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint144(uint256 value) internal pure returns (uint144) {\n        require(value \u003c= type(uint144).max, \"SafeCast: value doesn't fit in 144 bits\");\n        return uint144(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint136 from uint256, reverting on\n     * overflow (when the input is greater than largest uint136).\n     *\n     * Counterpart to Solidity's `uint136` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 136 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint136(uint256 value) internal pure returns (uint136) {\n        require(value \u003c= type(uint136).max, \"SafeCast: value doesn't fit in 136 bits\");\n        return uint136(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint128 from uint256, reverting on\n     * overflow (when the input is greater than largest uint128).\n     *\n     * Counterpart to Solidity's `uint128` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 128 bits\n     *\n     * _Available since v2.5._\n     */\n    function toUint128(uint256 value) internal pure returns (uint128) {\n        require(value \u003c= type(uint128).max, \"SafeCast: value doesn't fit in 128 bits\");\n        return uint128(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint120 from uint256, reverting on\n     * overflow (when the input is greater than largest uint120).\n     *\n     * Counterpart to Solidity's `uint120` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 120 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint120(uint256 value) internal pure returns (uint120) {\n        require(value \u003c= type(uint120).max, \"SafeCast: value doesn't fit in 120 bits\");\n        return uint120(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint112 from uint256, reverting on\n     * overflow (when the input is greater than largest uint112).\n     *\n     * Counterpart to Solidity's `uint112` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 112 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint112(uint256 value) internal pure returns (uint112) {\n        require(value \u003c= type(uint112).max, \"SafeCast: value doesn't fit in 112 bits\");\n        return uint112(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint104 from uint256, reverting on\n     * overflow (when the input is greater than largest uint104).\n     *\n     * Counterpart to Solidity's `uint104` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 104 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint104(uint256 value) internal pure returns (uint104) {\n        require(value \u003c= type(uint104).max, \"SafeCast: value doesn't fit in 104 bits\");\n        return uint104(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint96 from uint256, reverting on\n     * overflow (when the input is greater than largest uint96).\n     *\n     * Counterpart to Solidity's `uint96` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 96 bits\n     *\n     * _Available since v4.2._\n     */\n    function toUint96(uint256 value) internal pure returns (uint96) {\n        require(value \u003c= type(uint96).max, \"SafeCast: value doesn't fit in 96 bits\");\n        return uint96(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint88 from uint256, reverting on\n     * overflow (when the input is greater than largest uint88).\n     *\n     * Counterpart to Solidity's `uint88` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 88 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint88(uint256 value) internal pure returns (uint88) {\n        require(value \u003c= type(uint88).max, \"SafeCast: value doesn't fit in 88 bits\");\n        return uint88(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint80 from uint256, reverting on\n     * overflow (when the input is greater than largest uint80).\n     *\n     * Counterpart to Solidity's `uint80` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 80 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint80(uint256 value) internal pure returns (uint80) {\n        require(value \u003c= type(uint80).max, \"SafeCast: value doesn't fit in 80 bits\");\n        return uint80(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint72 from uint256, reverting on\n     * overflow (when the input is greater than largest uint72).\n     *\n     * Counterpart to Solidity's `uint72` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 72 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint72(uint256 value) internal pure returns (uint72) {\n        require(value \u003c= type(uint72).max, \"SafeCast: value doesn't fit in 72 bits\");\n        return uint72(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint64 from uint256, reverting on\n     * overflow (when the input is greater than largest uint64).\n     *\n     * Counterpart to Solidity's `uint64` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 64 bits\n     *\n     * _Available since v2.5._\n     */\n    function toUint64(uint256 value) internal pure returns (uint64) {\n        require(value \u003c= type(uint64).max, \"SafeCast: value doesn't fit in 64 bits\");\n        return uint64(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint56 from uint256, reverting on\n     * overflow (when the input is greater than largest uint56).\n     *\n     * Counterpart to Solidity's `uint56` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 56 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint56(uint256 value) internal pure returns (uint56) {\n        require(value \u003c= type(uint56).max, \"SafeCast: value doesn't fit in 56 bits\");\n        return uint56(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint48 from uint256, reverting on\n     * overflow (when the input is greater than largest uint48).\n     *\n     * Counterpart to Solidity's `uint48` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 48 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint48(uint256 value) internal pure returns (uint48) {\n        require(value \u003c= type(uint48).max, \"SafeCast: value doesn't fit in 48 bits\");\n        return uint48(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint40 from uint256, reverting on\n     * overflow (when the input is greater than largest uint40).\n     *\n     * Counterpart to Solidity's `uint40` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 40 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint40(uint256 value) internal pure returns (uint40) {\n        require(value \u003c= type(uint40).max, \"SafeCast: value doesn't fit in 40 bits\");\n        return uint40(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint32 from uint256, reverting on\n     * overflow (when the input is greater than largest uint32).\n     *\n     * Counterpart to Solidity's `uint32` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 32 bits\n     *\n     * _Available since v2.5._\n     */\n    function toUint32(uint256 value) internal pure returns (uint32) {\n        require(value \u003c= type(uint32).max, \"SafeCast: value doesn't fit in 32 bits\");\n        return uint32(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint24 from uint256, reverting on\n     * overflow (when the input is greater than largest uint24).\n     *\n     * Counterpart to Solidity's `uint24` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 24 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint24(uint256 value) internal pure returns (uint24) {\n        require(value \u003c= type(uint24).max, \"SafeCast: value doesn't fit in 24 bits\");\n        return uint24(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint16 from uint256, reverting on\n     * overflow (when the input is greater than largest uint16).\n     *\n     * Counterpart to Solidity's `uint16` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 16 bits\n     *\n     * _Available since v2.5._\n     */\n    function toUint16(uint256 value) internal pure returns (uint16) {\n        require(value \u003c= type(uint16).max, \"SafeCast: value doesn't fit in 16 bits\");\n        return uint16(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint8 from uint256, reverting on\n     * overflow (when the input is greater than largest uint8).\n     *\n     * Counterpart to Solidity's `uint8` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 8 bits\n     *\n     * _Available since v2.5._\n     */\n    function toUint8(uint256 value) internal pure returns (uint8) {\n        require(value \u003c= type(uint8).max, \"SafeCast: value doesn't fit in 8 bits\");\n        return uint8(value);\n    }\n\n    /**\n     * @dev Converts a signed int256 into an unsigned uint256.\n     *\n     * Requirements:\n     *\n     * - input must be greater than or equal to 0.\n     *\n     * _Available since v3.0._\n     */\n    function toUint256(int256 value) internal pure returns (uint256) {\n        require(value \u003e= 0, \"SafeCast: value must be positive\");\n        return uint256(value);\n    }\n\n    /**\n     * @dev Returns the downcasted int248 from int256, reverting on\n     * overflow (when the input is less than smallest int248 or\n     * greater than largest int248).\n     *\n     * Counterpart to Solidity's `int248` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 248 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt248(int256 value) internal pure returns (int248 downcasted) {\n        downcasted = int248(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 248 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int240 from int256, reverting on\n     * overflow (when the input is less than smallest int240 or\n     * greater than largest int240).\n     *\n     * Counterpart to Solidity's `int240` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 240 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt240(int256 value) internal pure returns (int240 downcasted) {\n        downcasted = int240(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 240 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int232 from int256, reverting on\n     * overflow (when the input is less than smallest int232 or\n     * greater than largest int232).\n     *\n     * Counterpart to Solidity's `int232` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 232 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt232(int256 value) internal pure returns (int232 downcasted) {\n        downcasted = int232(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 232 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int224 from int256, reverting on\n     * overflow (when the input is less than smallest int224 or\n     * greater than largest int224).\n     *\n     * Counterpart to Solidity's `int224` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 224 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt224(int256 value) internal pure returns (int224 downcasted) {\n        downcasted = int224(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 224 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int216 from int256, reverting on\n     * overflow (when the input is less than smallest int216 or\n     * greater than largest int216).\n     *\n     * Counterpart to Solidity's `int216` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 216 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt216(int256 value) internal pure returns (int216 downcasted) {\n        downcasted = int216(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 216 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int208 from int256, reverting on\n     * overflow (when the input is less than smallest int208 or\n     * greater than largest int208).\n     *\n     * Counterpart to Solidity's `int208` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 208 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt208(int256 value) internal pure returns (int208 downcasted) {\n        downcasted = int208(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 208 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int200 from int256, reverting on\n     * overflow (when the input is less than smallest int200 or\n     * greater than largest int200).\n     *\n     * Counterpart to Solidity's `int200` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 200 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt200(int256 value) internal pure returns (int200 downcasted) {\n        downcasted = int200(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 200 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int192 from int256, reverting on\n     * overflow (when the input is less than smallest int192 or\n     * greater than largest int192).\n     *\n     * Counterpart to Solidity's `int192` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 192 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt192(int256 value) internal pure returns (int192 downcasted) {\n        downcasted = int192(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 192 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int184 from int256, reverting on\n     * overflow (when the input is less than smallest int184 or\n     * greater than largest int184).\n     *\n     * Counterpart to Solidity's `int184` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 184 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt184(int256 value) internal pure returns (int184 downcasted) {\n        downcasted = int184(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 184 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int176 from int256, reverting on\n     * overflow (when the input is less than smallest int176 or\n     * greater than largest int176).\n     *\n     * Counterpart to Solidity's `int176` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 176 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt176(int256 value) internal pure returns (int176 downcasted) {\n        downcasted = int176(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 176 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int168 from int256, reverting on\n     * overflow (when the input is less than smallest int168 or\n     * greater than largest int168).\n     *\n     * Counterpart to Solidity's `int168` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 168 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt168(int256 value) internal pure returns (int168 downcasted) {\n        downcasted = int168(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 168 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int160 from int256, reverting on\n     * overflow (when the input is less than smallest int160 or\n     * greater than largest int160).\n     *\n     * Counterpart to Solidity's `int160` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 160 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt160(int256 value) internal pure returns (int160 downcasted) {\n        downcasted = int160(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 160 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int152 from int256, reverting on\n     * overflow (when the input is less than smallest int152 or\n     * greater than largest int152).\n     *\n     * Counterpart to Solidity's `int152` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 152 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt152(int256 value) internal pure returns (int152 downcasted) {\n        downcasted = int152(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 152 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int144 from int256, reverting on\n     * overflow (when the input is less than smallest int144 or\n     * greater than largest int144).\n     *\n     * Counterpart to Solidity's `int144` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 144 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt144(int256 value) internal pure returns (int144 downcasted) {\n        downcasted = int144(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 144 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int136 from int256, reverting on\n     * overflow (when the input is less than smallest int136 or\n     * greater than largest int136).\n     *\n     * Counterpart to Solidity's `int136` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 136 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt136(int256 value) internal pure returns (int136 downcasted) {\n        downcasted = int136(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 136 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int128 from int256, reverting on\n     * overflow (when the input is less than smallest int128 or\n     * greater than largest int128).\n     *\n     * Counterpart to Solidity's `int128` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 128 bits\n     *\n     * _Available since v3.1._\n     */\n    function toInt128(int256 value) internal pure returns (int128 downcasted) {\n        downcasted = int128(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 128 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int120 from int256, reverting on\n     * overflow (when the input is less than smallest int120 or\n     * greater than largest int120).\n     *\n     * Counterpart to Solidity's `int120` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 120 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt120(int256 value) internal pure returns (int120 downcasted) {\n        downcasted = int120(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 120 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int112 from int256, reverting on\n     * overflow (when the input is less than smallest int112 or\n     * greater than largest int112).\n     *\n     * Counterpart to Solidity's `int112` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 112 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt112(int256 value) internal pure returns (int112 downcasted) {\n        downcasted = int112(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 112 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int104 from int256, reverting on\n     * overflow (when the input is less than smallest int104 or\n     * greater than largest int104).\n     *\n     * Counterpart to Solidity's `int104` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 104 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt104(int256 value) internal pure returns (int104 downcasted) {\n        downcasted = int104(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 104 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int96 from int256, reverting on\n     * overflow (when the input is less than smallest int96 or\n     * greater than largest int96).\n     *\n     * Counterpart to Solidity's `int96` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 96 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt96(int256 value) internal pure returns (int96 downcasted) {\n        downcasted = int96(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 96 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int88 from int256, reverting on\n     * overflow (when the input is less than smallest int88 or\n     * greater than largest int88).\n     *\n     * Counterpart to Solidity's `int88` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 88 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt88(int256 value) internal pure returns (int88 downcasted) {\n        downcasted = int88(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 88 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int80 from int256, reverting on\n     * overflow (when the input is less than smallest int80 or\n     * greater than largest int80).\n     *\n     * Counterpart to Solidity's `int80` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 80 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt80(int256 value) internal pure returns (int80 downcasted) {\n        downcasted = int80(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 80 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int72 from int256, reverting on\n     * overflow (when the input is less than smallest int72 or\n     * greater than largest int72).\n     *\n     * Counterpart to Solidity's `int72` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 72 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt72(int256 value) internal pure returns (int72 downcasted) {\n        downcasted = int72(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 72 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int64 from int256, reverting on\n     * overflow (when the input is less than smallest int64 or\n     * greater than largest int64).\n     *\n     * Counterpart to Solidity's `int64` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 64 bits\n     *\n     * _Available since v3.1._\n     */\n    function toInt64(int256 value) internal pure returns (int64 downcasted) {\n        downcasted = int64(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 64 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int56 from int256, reverting on\n     * overflow (when the input is less than smallest int56 or\n     * greater than largest int56).\n     *\n     * Counterpart to Solidity's `int56` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 56 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt56(int256 value) internal pure returns (int56 downcasted) {\n        downcasted = int56(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 56 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int48 from int256, reverting on\n     * overflow (when the input is less than smallest int48 or\n     * greater than largest int48).\n     *\n     * Counterpart to Solidity's `int48` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 48 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt48(int256 value) internal pure returns (int48 downcasted) {\n        downcasted = int48(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 48 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int40 from int256, reverting on\n     * overflow (when the input is less than smallest int40 or\n     * greater than largest int40).\n     *\n     * Counterpart to Solidity's `int40` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 40 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt40(int256 value) internal pure returns (int40 downcasted) {\n        downcasted = int40(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 40 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int32 from int256, reverting on\n     * overflow (when the input is less than smallest int32 or\n     * greater than largest int32).\n     *\n     * Counterpart to Solidity's `int32` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 32 bits\n     *\n     * _Available since v3.1._\n     */\n    function toInt32(int256 value) internal pure returns (int32 downcasted) {\n        downcasted = int32(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 32 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int24 from int256, reverting on\n     * overflow (when the input is less than smallest int24 or\n     * greater than largest int24).\n     *\n     * Counterpart to Solidity's `int24` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 24 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt24(int256 value) internal pure returns (int24 downcasted) {\n        downcasted = int24(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 24 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int16 from int256, reverting on\n     * overflow (when the input is less than smallest int16 or\n     * greater than largest int16).\n     *\n     * Counterpart to Solidity's `int16` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 16 bits\n     *\n     * _Available since v3.1._\n     */\n    function toInt16(int256 value) internal pure returns (int16 downcasted) {\n        downcasted = int16(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 16 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int8 from int256, reverting on\n     * overflow (when the input is less than smallest int8 or\n     * greater than largest int8).\n     *\n     * Counterpart to Solidity's `int8` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 8 bits\n     *\n     * _Available since v3.1._\n     */\n    function toInt8(int256 value) internal pure returns (int8 downcasted) {\n        downcasted = int8(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 8 bits\");\n    }\n\n    /**\n     * @dev Converts an unsigned uint256 into a signed int256.\n     *\n     * Requirements:\n     *\n     * - input must be less than or equal to maxInt256.\n     *\n     * _Available since v3.0._\n     */\n    function toInt256(uint256 value) internal pure returns (int256) {\n        // Note: Unsafe cast below is okay because `type(int256).max` is guaranteed to be positive\n        require(value \u003c= uint256(type(int256).max), \"SafeCast: value doesn't fit in an int256\");\n        return int256(value);\n    }\n}\n\n// 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/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// contracts/libs/memory/BaseMessage.sol\n\n/// BaseMessage is a memory view over the base message supported by Origin-Destination\ntype BaseMessage is uint256;\n\nusing BaseMessageLib for BaseMessage global;\n\n/// BaseMessage structure represents a base message sent via the Origin-Destination contracts.\n/// - It only contains data relevant to the base message, the rest of data is encoded in the message header.\n/// - `sender` and `recipient` for EVM chains are EVM addresses casted to bytes32, while preserving left-alignment.\n/// - `tips` and `request` parameters are specified by a message sender\n/// \u003e Origin will calculate minimum tips for given request and content length, and will reject messages with tips\n/// lower than that.\n///\n/// # Memory layout of BaseMessage fields\n///\n/// | Position   | Field     | Type    | Bytes | Description                            |\n/// | ---------- | --------- | ------- | ----- | -------------------------------------- |\n/// | [000..032) | tips      | uint256 | 32    | Encoded tips paid on origin chain      |\n/// | [032..064) | sender    | bytes32 | 32    | Sender address on origin chain         |\n/// | [064..096) | recipient | bytes32 | 32    | Recipient address on destination chain |\n/// | [096..116) | request   | uint160 | 20    | Encoded request for message execution  |\n/// | [104..AAA) | content   | bytes   | ??    | Content to be passed to recipient      |\nlibrary BaseMessageLib {\n    using MemViewLib for bytes;\n\n    /// @dev The variables below are not supposed to be used outside of the library directly.\n    uint256 private constant OFFSET_TIPS = 0;\n    uint256 private constant OFFSET_SENDER = 32;\n    uint256 private constant OFFSET_RECIPIENT = 64;\n    uint256 private constant OFFSET_REQUEST = OFFSET_RECIPIENT + TIPS_LENGTH;\n    uint256 private constant OFFSET_CONTENT = OFFSET_REQUEST + REQUEST_LENGTH;\n\n    // ═══════════════════════════════════════════════ BASE MESSAGE ════════════════════════════════════════════════════\n\n    /**\n     * @notice Returns a formatted BaseMessage payload with provided fields.\n     * @param tips_         Encoded tips information\n     * @param sender_       Sender address on origin chain\n     * @param recipient_    Recipient address on destination chain\n     * @param request_      Encoded request for message execution\n     * @param content_      Raw content to be passed to recipient on destination chain\n     * @return Formatted base message\n     */\n    function formatBaseMessage(Tips tips_, bytes32 sender_, bytes32 recipient_, Request request_, bytes memory content_)\n        internal\n        pure\n        returns (bytes memory)\n    {\n        return abi.encodePacked(tips_, sender_, recipient_, request_, content_);\n    }\n\n    /**\n     * @notice Returns a BaseMessage view over the given payload.\n     * @dev Will revert if the payload is not a base message.\n     */\n    function castToBaseMessage(bytes memory payload) internal pure returns (BaseMessage) {\n        return castToBaseMessage(payload.ref());\n    }\n\n    /**\n     * @notice Casts a memory view to a BaseMessage view.\n     * @dev Will revert if the memory view is not over a base message payload.\n     */\n    function castToBaseMessage(MemView memView) internal pure returns (BaseMessage) {\n        if (!isBaseMessage(memView)) revert UnformattedBaseMessage();\n        return BaseMessage.wrap(MemView.unwrap(memView));\n    }\n\n    /// @notice Checks that a payload is a formatted BaseMessage.\n    function isBaseMessage(MemView memView) internal pure returns (bool) {\n        // Check if sender, recipient, tips fields exist\n        return (memView.len() \u003e= OFFSET_CONTENT);\n        // Content could be empty, so we don't check that\n    }\n\n    /// @notice Convenience shortcut for unwrapping a view.\n    function unwrap(BaseMessage baseMessage) internal pure returns (MemView) {\n        return MemView.wrap(BaseMessage.unwrap(baseMessage));\n    }\n\n    /// @notice Returns baseMessage's hash: a leaf to be inserted in the \"Message mini-Merkle tree\".\n    function leaf(BaseMessage baseMessage) internal pure returns (bytes32) {\n        // We hash \"tips\" and \"everything but tips\" to make tips proofs easier to verify\n        return MerkleMath.getParent(baseMessage.tips().leaf(), baseMessage.bodyLeaf());\n    }\n\n    /// @notice Returns hash for the \"everything but tips\" part of the base message.\n    function bodyLeaf(BaseMessage baseMessage) internal pure returns (bytes32) {\n        return baseMessage.unwrap().sliceFrom({index_: OFFSET_SENDER}).keccak();\n    }\n\n    // ═══════════════════════════════════════════ BASE MESSAGE SLICING ════════════════════════════════════════════════\n\n    /// @notice Returns encoded tips paid on origin chain.\n    function tips(BaseMessage baseMessage) internal pure returns (Tips) {\n        return TipsLib.wrapPadded((baseMessage.unwrap().indexUint({index_: OFFSET_TIPS, bytes_: TIPS_LENGTH})));\n    }\n\n    /// @notice Returns sender address on origin chain.\n    function sender(BaseMessage baseMessage) internal pure returns (bytes32) {\n        return baseMessage.unwrap().index({index_: OFFSET_SENDER, bytes_: 32});\n    }\n\n    /// @notice Returns recipient address on destination chain.\n    function recipient(BaseMessage baseMessage) internal pure returns (bytes32) {\n        return baseMessage.unwrap().index({index_: OFFSET_RECIPIENT, bytes_: 32});\n    }\n\n    /// @notice Returns an encoded request for message execution on destination chain.\n    function request(BaseMessage baseMessage) internal pure returns (Request) {\n        return RequestLib.wrapPadded((baseMessage.unwrap().indexUint({index_: OFFSET_REQUEST, bytes_: REQUEST_LENGTH})));\n    }\n\n    /// @notice Returns an untyped memory view over the content to be passed to recipient.\n    function content(BaseMessage baseMessage) internal pure returns (MemView) {\n        return baseMessage.unwrap().sliceFrom({index_: OFFSET_CONTENT});\n    }\n}\n\n// test/harnesses/libs/memory/BaseMessageHarness.t.sol\n\n// solhint-disable ordering\n/**\n * @notice Exposes BaseMessage methods for testing against golang.\n */\ncontract BaseMessageHarness {\n    using BaseMessageLib for bytes;\n    using BaseMessageLib for MemView;\n    using MemViewLib for bytes;\n\n    // Note: we don't add an empty test() function here, as it currently leads\n    // to zero coverage on the corresponding library.\n\n    // ══════════════════════════════════════════════════ GETTERS ══════════════════════════════════════════════════════\n\n    function castToBaseMessage(bytes memory payload) public view returns (bytes memory) {\n        // Walkaround to get the forge coverage working on libraries, see\n        // https://github.com/foundry-rs/foundry/pull/3128#issuecomment-1241245086\n        BaseMessage baseMessage = BaseMessageLib.castToBaseMessage(payload);\n        return baseMessage.unwrap().clone();\n    }\n\n    /// @notice Returns baseMessage's sender field\n    function sender(bytes memory payload) public pure returns (bytes32) {\n        return payload.castToBaseMessage().sender();\n    }\n\n    /// @notice Returns baseMessage's recipient field as bytes32\n    function recipient(bytes memory payload) public pure returns (bytes32) {\n        return payload.castToBaseMessage().recipient();\n    }\n\n    /// @notice Returns baseMessage's tips field\n    function tips(bytes memory payload) public pure returns (uint256) {\n        return Tips.unwrap(payload.castToBaseMessage().tips());\n    }\n\n    /// @notice Returns baseMessage's request field\n    function request(bytes memory payload) public pure returns (uint192) {\n        return Request.unwrap(payload.castToBaseMessage().request());\n    }\n\n    /// @notice Returns baseMessage's content field\n    function content(bytes memory payload) public view returns (bytes memory) {\n        return payload.castToBaseMessage().content().clone();\n    }\n\n    function isBaseMessage(bytes memory payload) public pure returns (bool) {\n        return payload.ref().isBaseMessage();\n    }\n\n    // ════════════════════════════════════════════════ FORMATTERS ═════════════════════════════════════════════════════\n\n    function formatBaseMessage(Tips tips_, bytes32 sender_, bytes32 recipient_, Request request_, bytes memory content_)\n        public\n        pure\n        returns (bytes memory)\n    {\n        return BaseMessageLib.formatBaseMessage(tips_, sender_, recipient_, request_, content_);\n    }\n\n    function leaf(bytes memory payload) public pure returns (bytes32) {\n        return payload.castToBaseMessage().leaf();\n    }\n\n    function bodyLeaf(bytes memory payload) public pure returns (bytes32) {\n        return payload.castToBaseMessage().bodyLeaf();\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":"13457:34153:0:-:0;;;;;;;;;;;;;;;-1:-1:-1;;;13457:34153:0;;;;;;;;;;;;;;;;;","srcMapRuntime":"13457: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/BaseMessageHarness.t.sol\":\"SafeCast\"},\"evmVersion\":\"london\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\"},\"optimizer\":{\"enabled\":true,\"runs\":10000},\"remappings\":[]},\"sources\":{\"solidity/BaseMessageHarness.t.sol\":{\"keccak256\":\"0x0b644d75605ac5a83f42b70984b4f8c78046e7756cf276e43df1e1f8c1c57ce6\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://89e64be85f0b7caad7e5d5fe0d77b92bb4c97bf9542651212fb3563a019d5bac\",\"dweb:/ipfs/QmVsD4QYYzmJVCjC85GjGjbY2Jooz9rZHSJmvp4hkWxxbR\"]}},\"version\":1}"},"hashes":{}},"solidity/BaseMessageHarness.t.sol:TipsLib":{"code":"0x60566037600b82828239805160001a607314602a57634e487b7160e01b600052600060045260246000fd5b30600052607381538281f3fe73000000000000000000000000000000000000000030146080604052600080fdfea26469706673582212202c02d9b3d77569dbc0274d1528aa80d6f5f375685e9d9087d54aad18d29c7e9564736f6c63430008110033","runtime-code":"0x73000000000000000000000000000000000000000030146080604052600080fdfea26469706673582212202c02d9b3d77569dbc0274d1528aa80d6f5f375685e9d9087d54aad18d29c7e9564736f6c63430008110033","info":{"source":"// SPDX-License-Identifier: MIT\npragma solidity =0.8.17 ^0.8.0;\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/Request.sol\n\n/// Request is encoded data with \"message execution request\".\ntype Request is uint192;\n\nusing RequestLib for Request global;\n\n/// Library for formatting _the request part_ of _the base messages_.\n/// - Request represents a message sender requirements for the message execution on the destination chain.\n/// - Request occupies a single storage word, and thus is stored on stack instead of being stored in memory.\n/// \u003e gasDrop field is included for future compatibility and is ignored at the moment.\n///\n/// # Request stack layout (from highest bits to lowest)\n///\n/// | Position   | Field    | Type   | Bytes | Description                                          |\n/// | ---------- | -------- | ------ | ----- | ---------------------------------------------------- |\n/// | (024..012] | gasDrop  | uint96 | 12    | Minimum amount of gas token to drop to the recipient |\n/// | (012..004] | gasLimit | uint64 | 8     | Minimum amount of gas units to supply for execution  |\n/// | (004..000] | version  | uint32 | 4     | Base message version to pass to the recipient        |\n\nlibrary RequestLib {\n    /// @dev Amount of bits to shift to gasDrop field\n    uint192 private constant SHIFT_GAS_DROP = 12 * 8;\n    /// @dev Amount of bits to shift to gasLimit field\n    uint192 private constant SHIFT_GAS_LIMIT = 4 * 8;\n\n    /// @notice Returns an encoded request with the given fields\n    /// @param gasDrop_     Minimum amount of gas token to drop to the recipient (ignored at the moment)\n    /// @param gasLimit_    Minimum amount of gas units to supply for execution\n    /// @param version_     Base message version to pass to the recipient\n    function encodeRequest(uint96 gasDrop_, uint64 gasLimit_, uint32 version_) internal pure returns (Request) {\n        // Casts below are upcasts, so they are safe\n        return Request.wrap(uint192(gasDrop_) \u003c\u003c SHIFT_GAS_DROP | uint192(gasLimit_) \u003c\u003c SHIFT_GAS_LIMIT | version_);\n    }\n\n    /// @notice Wraps the padded encoded request into a Request-typed value.\n    /// @dev The \"padded\" request is simply an encoded request casted to uint256 (highest bits are set to zero).\n    /// Casting to uint256 is done automatically in Solidity, so no extra actions from consumers are needed.\n    /// The highest bits are discarded, so that the contracts dealing with encoded requests\n    /// don't need to be updated, if a new field is added.\n    function wrapPadded(uint256 paddedRequest) internal pure returns (Request) {\n        // Casting to uint192 will truncate the highest bits, which is the behavior we want\n        return Request.wrap(uint192(paddedRequest));\n    }\n\n    /// @notice Returns the requested of gas token to drop to the recipient.\n    function gasDrop(Request request) internal pure returns (uint96) {\n        // Casting to uint96 will truncate the highest bits, which is the behavior we want\n        return uint96(Request.unwrap(request) \u003e\u003e SHIFT_GAS_DROP);\n    }\n\n    /// @notice Returns the requested minimum amount of gas units to supply for execution.\n    function gasLimit(Request request) internal pure returns (uint64) {\n        // Casting to uint64 will truncate the highest bits, which is the behavior we want\n        return uint64(Request.unwrap(request) \u003e\u003e SHIFT_GAS_LIMIT);\n    }\n\n    /// @notice Returns the requested base message version to pass to the recipient.\n    function version(Request request) internal pure returns (uint32) {\n        // Casting to uint32 will truncate the highest bits, which is the behavior we want\n        return uint32(Request.unwrap(request));\n    }\n}\n\n// node_modules/@openzeppelin/contracts/utils/math/SafeCast.sol\n\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/math/SafeCast.sol)\n// This file was procedurally generated from scripts/generate/templates/SafeCast.js.\n\n/**\n * @dev Wrappers over Solidity's uintXX/intXX casting operators with added overflow\n * checks.\n *\n * Downcasting from uint256/int256 in Solidity does not revert on overflow. This can\n * easily result in undesired exploitation or bugs, since developers usually\n * assume that overflows raise errors. `SafeCast` restores this intuition by\n * reverting the transaction when such an operation overflows.\n *\n * Using this library instead of the unchecked operations eliminates an entire\n * class of bugs, so it's recommended to use it always.\n *\n * Can be combined with {SafeMath} and {SignedSafeMath} to extend it to smaller types, by performing\n * all math on `uint256` and `int256` and then downcasting.\n */\nlibrary SafeCast {\n    /**\n     * @dev Returns the downcasted uint248 from uint256, reverting on\n     * overflow (when the input is greater than largest uint248).\n     *\n     * Counterpart to Solidity's `uint248` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 248 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint248(uint256 value) internal pure returns (uint248) {\n        require(value \u003c= type(uint248).max, \"SafeCast: value doesn't fit in 248 bits\");\n        return uint248(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint240 from uint256, reverting on\n     * overflow (when the input is greater than largest uint240).\n     *\n     * Counterpart to Solidity's `uint240` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 240 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint240(uint256 value) internal pure returns (uint240) {\n        require(value \u003c= type(uint240).max, \"SafeCast: value doesn't fit in 240 bits\");\n        return uint240(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint232 from uint256, reverting on\n     * overflow (when the input is greater than largest uint232).\n     *\n     * Counterpart to Solidity's `uint232` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 232 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint232(uint256 value) internal pure returns (uint232) {\n        require(value \u003c= type(uint232).max, \"SafeCast: value doesn't fit in 232 bits\");\n        return uint232(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint224 from uint256, reverting on\n     * overflow (when the input is greater than largest uint224).\n     *\n     * Counterpart to Solidity's `uint224` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 224 bits\n     *\n     * _Available since v4.2._\n     */\n    function toUint224(uint256 value) internal pure returns (uint224) {\n        require(value \u003c= type(uint224).max, \"SafeCast: value doesn't fit in 224 bits\");\n        return uint224(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint216 from uint256, reverting on\n     * overflow (when the input is greater than largest uint216).\n     *\n     * Counterpart to Solidity's `uint216` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 216 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint216(uint256 value) internal pure returns (uint216) {\n        require(value \u003c= type(uint216).max, \"SafeCast: value doesn't fit in 216 bits\");\n        return uint216(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint208 from uint256, reverting on\n     * overflow (when the input is greater than largest uint208).\n     *\n     * Counterpart to Solidity's `uint208` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 208 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint208(uint256 value) internal pure returns (uint208) {\n        require(value \u003c= type(uint208).max, \"SafeCast: value doesn't fit in 208 bits\");\n        return uint208(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint200 from uint256, reverting on\n     * overflow (when the input is greater than largest uint200).\n     *\n     * Counterpart to Solidity's `uint200` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 200 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint200(uint256 value) internal pure returns (uint200) {\n        require(value \u003c= type(uint200).max, \"SafeCast: value doesn't fit in 200 bits\");\n        return uint200(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint192 from uint256, reverting on\n     * overflow (when the input is greater than largest uint192).\n     *\n     * Counterpart to Solidity's `uint192` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 192 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint192(uint256 value) internal pure returns (uint192) {\n        require(value \u003c= type(uint192).max, \"SafeCast: value doesn't fit in 192 bits\");\n        return uint192(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint184 from uint256, reverting on\n     * overflow (when the input is greater than largest uint184).\n     *\n     * Counterpart to Solidity's `uint184` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 184 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint184(uint256 value) internal pure returns (uint184) {\n        require(value \u003c= type(uint184).max, \"SafeCast: value doesn't fit in 184 bits\");\n        return uint184(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint176 from uint256, reverting on\n     * overflow (when the input is greater than largest uint176).\n     *\n     * Counterpart to Solidity's `uint176` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 176 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint176(uint256 value) internal pure returns (uint176) {\n        require(value \u003c= type(uint176).max, \"SafeCast: value doesn't fit in 176 bits\");\n        return uint176(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint168 from uint256, reverting on\n     * overflow (when the input is greater than largest uint168).\n     *\n     * Counterpart to Solidity's `uint168` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 168 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint168(uint256 value) internal pure returns (uint168) {\n        require(value \u003c= type(uint168).max, \"SafeCast: value doesn't fit in 168 bits\");\n        return uint168(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint160 from uint256, reverting on\n     * overflow (when the input is greater than largest uint160).\n     *\n     * Counterpart to Solidity's `uint160` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 160 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint160(uint256 value) internal pure returns (uint160) {\n        require(value \u003c= type(uint160).max, \"SafeCast: value doesn't fit in 160 bits\");\n        return uint160(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint152 from uint256, reverting on\n     * overflow (when the input is greater than largest uint152).\n     *\n     * Counterpart to Solidity's `uint152` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 152 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint152(uint256 value) internal pure returns (uint152) {\n        require(value \u003c= type(uint152).max, \"SafeCast: value doesn't fit in 152 bits\");\n        return uint152(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint144 from uint256, reverting on\n     * overflow (when the input is greater than largest uint144).\n     *\n     * Counterpart to Solidity's `uint144` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 144 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint144(uint256 value) internal pure returns (uint144) {\n        require(value \u003c= type(uint144).max, \"SafeCast: value doesn't fit in 144 bits\");\n        return uint144(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint136 from uint256, reverting on\n     * overflow (when the input is greater than largest uint136).\n     *\n     * Counterpart to Solidity's `uint136` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 136 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint136(uint256 value) internal pure returns (uint136) {\n        require(value \u003c= type(uint136).max, \"SafeCast: value doesn't fit in 136 bits\");\n        return uint136(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint128 from uint256, reverting on\n     * overflow (when the input is greater than largest uint128).\n     *\n     * Counterpart to Solidity's `uint128` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 128 bits\n     *\n     * _Available since v2.5._\n     */\n    function toUint128(uint256 value) internal pure returns (uint128) {\n        require(value \u003c= type(uint128).max, \"SafeCast: value doesn't fit in 128 bits\");\n        return uint128(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint120 from uint256, reverting on\n     * overflow (when the input is greater than largest uint120).\n     *\n     * Counterpart to Solidity's `uint120` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 120 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint120(uint256 value) internal pure returns (uint120) {\n        require(value \u003c= type(uint120).max, \"SafeCast: value doesn't fit in 120 bits\");\n        return uint120(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint112 from uint256, reverting on\n     * overflow (when the input is greater than largest uint112).\n     *\n     * Counterpart to Solidity's `uint112` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 112 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint112(uint256 value) internal pure returns (uint112) {\n        require(value \u003c= type(uint112).max, \"SafeCast: value doesn't fit in 112 bits\");\n        return uint112(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint104 from uint256, reverting on\n     * overflow (when the input is greater than largest uint104).\n     *\n     * Counterpart to Solidity's `uint104` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 104 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint104(uint256 value) internal pure returns (uint104) {\n        require(value \u003c= type(uint104).max, \"SafeCast: value doesn't fit in 104 bits\");\n        return uint104(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint96 from uint256, reverting on\n     * overflow (when the input is greater than largest uint96).\n     *\n     * Counterpart to Solidity's `uint96` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 96 bits\n     *\n     * _Available since v4.2._\n     */\n    function toUint96(uint256 value) internal pure returns (uint96) {\n        require(value \u003c= type(uint96).max, \"SafeCast: value doesn't fit in 96 bits\");\n        return uint96(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint88 from uint256, reverting on\n     * overflow (when the input is greater than largest uint88).\n     *\n     * Counterpart to Solidity's `uint88` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 88 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint88(uint256 value) internal pure returns (uint88) {\n        require(value \u003c= type(uint88).max, \"SafeCast: value doesn't fit in 88 bits\");\n        return uint88(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint80 from uint256, reverting on\n     * overflow (when the input is greater than largest uint80).\n     *\n     * Counterpart to Solidity's `uint80` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 80 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint80(uint256 value) internal pure returns (uint80) {\n        require(value \u003c= type(uint80).max, \"SafeCast: value doesn't fit in 80 bits\");\n        return uint80(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint72 from uint256, reverting on\n     * overflow (when the input is greater than largest uint72).\n     *\n     * Counterpart to Solidity's `uint72` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 72 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint72(uint256 value) internal pure returns (uint72) {\n        require(value \u003c= type(uint72).max, \"SafeCast: value doesn't fit in 72 bits\");\n        return uint72(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint64 from uint256, reverting on\n     * overflow (when the input is greater than largest uint64).\n     *\n     * Counterpart to Solidity's `uint64` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 64 bits\n     *\n     * _Available since v2.5._\n     */\n    function toUint64(uint256 value) internal pure returns (uint64) {\n        require(value \u003c= type(uint64).max, \"SafeCast: value doesn't fit in 64 bits\");\n        return uint64(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint56 from uint256, reverting on\n     * overflow (when the input is greater than largest uint56).\n     *\n     * Counterpart to Solidity's `uint56` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 56 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint56(uint256 value) internal pure returns (uint56) {\n        require(value \u003c= type(uint56).max, \"SafeCast: value doesn't fit in 56 bits\");\n        return uint56(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint48 from uint256, reverting on\n     * overflow (when the input is greater than largest uint48).\n     *\n     * Counterpart to Solidity's `uint48` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 48 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint48(uint256 value) internal pure returns (uint48) {\n        require(value \u003c= type(uint48).max, \"SafeCast: value doesn't fit in 48 bits\");\n        return uint48(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint40 from uint256, reverting on\n     * overflow (when the input is greater than largest uint40).\n     *\n     * Counterpart to Solidity's `uint40` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 40 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint40(uint256 value) internal pure returns (uint40) {\n        require(value \u003c= type(uint40).max, \"SafeCast: value doesn't fit in 40 bits\");\n        return uint40(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint32 from uint256, reverting on\n     * overflow (when the input is greater than largest uint32).\n     *\n     * Counterpart to Solidity's `uint32` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 32 bits\n     *\n     * _Available since v2.5._\n     */\n    function toUint32(uint256 value) internal pure returns (uint32) {\n        require(value \u003c= type(uint32).max, \"SafeCast: value doesn't fit in 32 bits\");\n        return uint32(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint24 from uint256, reverting on\n     * overflow (when the input is greater than largest uint24).\n     *\n     * Counterpart to Solidity's `uint24` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 24 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint24(uint256 value) internal pure returns (uint24) {\n        require(value \u003c= type(uint24).max, \"SafeCast: value doesn't fit in 24 bits\");\n        return uint24(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint16 from uint256, reverting on\n     * overflow (when the input is greater than largest uint16).\n     *\n     * Counterpart to Solidity's `uint16` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 16 bits\n     *\n     * _Available since v2.5._\n     */\n    function toUint16(uint256 value) internal pure returns (uint16) {\n        require(value \u003c= type(uint16).max, \"SafeCast: value doesn't fit in 16 bits\");\n        return uint16(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint8 from uint256, reverting on\n     * overflow (when the input is greater than largest uint8).\n     *\n     * Counterpart to Solidity's `uint8` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 8 bits\n     *\n     * _Available since v2.5._\n     */\n    function toUint8(uint256 value) internal pure returns (uint8) {\n        require(value \u003c= type(uint8).max, \"SafeCast: value doesn't fit in 8 bits\");\n        return uint8(value);\n    }\n\n    /**\n     * @dev Converts a signed int256 into an unsigned uint256.\n     *\n     * Requirements:\n     *\n     * - input must be greater than or equal to 0.\n     *\n     * _Available since v3.0._\n     */\n    function toUint256(int256 value) internal pure returns (uint256) {\n        require(value \u003e= 0, \"SafeCast: value must be positive\");\n        return uint256(value);\n    }\n\n    /**\n     * @dev Returns the downcasted int248 from int256, reverting on\n     * overflow (when the input is less than smallest int248 or\n     * greater than largest int248).\n     *\n     * Counterpart to Solidity's `int248` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 248 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt248(int256 value) internal pure returns (int248 downcasted) {\n        downcasted = int248(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 248 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int240 from int256, reverting on\n     * overflow (when the input is less than smallest int240 or\n     * greater than largest int240).\n     *\n     * Counterpart to Solidity's `int240` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 240 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt240(int256 value) internal pure returns (int240 downcasted) {\n        downcasted = int240(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 240 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int232 from int256, reverting on\n     * overflow (when the input is less than smallest int232 or\n     * greater than largest int232).\n     *\n     * Counterpart to Solidity's `int232` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 232 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt232(int256 value) internal pure returns (int232 downcasted) {\n        downcasted = int232(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 232 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int224 from int256, reverting on\n     * overflow (when the input is less than smallest int224 or\n     * greater than largest int224).\n     *\n     * Counterpart to Solidity's `int224` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 224 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt224(int256 value) internal pure returns (int224 downcasted) {\n        downcasted = int224(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 224 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int216 from int256, reverting on\n     * overflow (when the input is less than smallest int216 or\n     * greater than largest int216).\n     *\n     * Counterpart to Solidity's `int216` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 216 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt216(int256 value) internal pure returns (int216 downcasted) {\n        downcasted = int216(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 216 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int208 from int256, reverting on\n     * overflow (when the input is less than smallest int208 or\n     * greater than largest int208).\n     *\n     * Counterpart to Solidity's `int208` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 208 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt208(int256 value) internal pure returns (int208 downcasted) {\n        downcasted = int208(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 208 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int200 from int256, reverting on\n     * overflow (when the input is less than smallest int200 or\n     * greater than largest int200).\n     *\n     * Counterpart to Solidity's `int200` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 200 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt200(int256 value) internal pure returns (int200 downcasted) {\n        downcasted = int200(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 200 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int192 from int256, reverting on\n     * overflow (when the input is less than smallest int192 or\n     * greater than largest int192).\n     *\n     * Counterpart to Solidity's `int192` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 192 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt192(int256 value) internal pure returns (int192 downcasted) {\n        downcasted = int192(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 192 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int184 from int256, reverting on\n     * overflow (when the input is less than smallest int184 or\n     * greater than largest int184).\n     *\n     * Counterpart to Solidity's `int184` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 184 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt184(int256 value) internal pure returns (int184 downcasted) {\n        downcasted = int184(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 184 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int176 from int256, reverting on\n     * overflow (when the input is less than smallest int176 or\n     * greater than largest int176).\n     *\n     * Counterpart to Solidity's `int176` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 176 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt176(int256 value) internal pure returns (int176 downcasted) {\n        downcasted = int176(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 176 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int168 from int256, reverting on\n     * overflow (when the input is less than smallest int168 or\n     * greater than largest int168).\n     *\n     * Counterpart to Solidity's `int168` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 168 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt168(int256 value) internal pure returns (int168 downcasted) {\n        downcasted = int168(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 168 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int160 from int256, reverting on\n     * overflow (when the input is less than smallest int160 or\n     * greater than largest int160).\n     *\n     * Counterpart to Solidity's `int160` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 160 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt160(int256 value) internal pure returns (int160 downcasted) {\n        downcasted = int160(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 160 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int152 from int256, reverting on\n     * overflow (when the input is less than smallest int152 or\n     * greater than largest int152).\n     *\n     * Counterpart to Solidity's `int152` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 152 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt152(int256 value) internal pure returns (int152 downcasted) {\n        downcasted = int152(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 152 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int144 from int256, reverting on\n     * overflow (when the input is less than smallest int144 or\n     * greater than largest int144).\n     *\n     * Counterpart to Solidity's `int144` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 144 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt144(int256 value) internal pure returns (int144 downcasted) {\n        downcasted = int144(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 144 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int136 from int256, reverting on\n     * overflow (when the input is less than smallest int136 or\n     * greater than largest int136).\n     *\n     * Counterpart to Solidity's `int136` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 136 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt136(int256 value) internal pure returns (int136 downcasted) {\n        downcasted = int136(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 136 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int128 from int256, reverting on\n     * overflow (when the input is less than smallest int128 or\n     * greater than largest int128).\n     *\n     * Counterpart to Solidity's `int128` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 128 bits\n     *\n     * _Available since v3.1._\n     */\n    function toInt128(int256 value) internal pure returns (int128 downcasted) {\n        downcasted = int128(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 128 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int120 from int256, reverting on\n     * overflow (when the input is less than smallest int120 or\n     * greater than largest int120).\n     *\n     * Counterpart to Solidity's `int120` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 120 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt120(int256 value) internal pure returns (int120 downcasted) {\n        downcasted = int120(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 120 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int112 from int256, reverting on\n     * overflow (when the input is less than smallest int112 or\n     * greater than largest int112).\n     *\n     * Counterpart to Solidity's `int112` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 112 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt112(int256 value) internal pure returns (int112 downcasted) {\n        downcasted = int112(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 112 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int104 from int256, reverting on\n     * overflow (when the input is less than smallest int104 or\n     * greater than largest int104).\n     *\n     * Counterpart to Solidity's `int104` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 104 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt104(int256 value) internal pure returns (int104 downcasted) {\n        downcasted = int104(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 104 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int96 from int256, reverting on\n     * overflow (when the input is less than smallest int96 or\n     * greater than largest int96).\n     *\n     * Counterpart to Solidity's `int96` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 96 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt96(int256 value) internal pure returns (int96 downcasted) {\n        downcasted = int96(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 96 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int88 from int256, reverting on\n     * overflow (when the input is less than smallest int88 or\n     * greater than largest int88).\n     *\n     * Counterpart to Solidity's `int88` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 88 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt88(int256 value) internal pure returns (int88 downcasted) {\n        downcasted = int88(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 88 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int80 from int256, reverting on\n     * overflow (when the input is less than smallest int80 or\n     * greater than largest int80).\n     *\n     * Counterpart to Solidity's `int80` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 80 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt80(int256 value) internal pure returns (int80 downcasted) {\n        downcasted = int80(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 80 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int72 from int256, reverting on\n     * overflow (when the input is less than smallest int72 or\n     * greater than largest int72).\n     *\n     * Counterpart to Solidity's `int72` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 72 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt72(int256 value) internal pure returns (int72 downcasted) {\n        downcasted = int72(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 72 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int64 from int256, reverting on\n     * overflow (when the input is less than smallest int64 or\n     * greater than largest int64).\n     *\n     * Counterpart to Solidity's `int64` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 64 bits\n     *\n     * _Available since v3.1._\n     */\n    function toInt64(int256 value) internal pure returns (int64 downcasted) {\n        downcasted = int64(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 64 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int56 from int256, reverting on\n     * overflow (when the input is less than smallest int56 or\n     * greater than largest int56).\n     *\n     * Counterpart to Solidity's `int56` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 56 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt56(int256 value) internal pure returns (int56 downcasted) {\n        downcasted = int56(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 56 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int48 from int256, reverting on\n     * overflow (when the input is less than smallest int48 or\n     * greater than largest int48).\n     *\n     * Counterpart to Solidity's `int48` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 48 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt48(int256 value) internal pure returns (int48 downcasted) {\n        downcasted = int48(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 48 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int40 from int256, reverting on\n     * overflow (when the input is less than smallest int40 or\n     * greater than largest int40).\n     *\n     * Counterpart to Solidity's `int40` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 40 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt40(int256 value) internal pure returns (int40 downcasted) {\n        downcasted = int40(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 40 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int32 from int256, reverting on\n     * overflow (when the input is less than smallest int32 or\n     * greater than largest int32).\n     *\n     * Counterpart to Solidity's `int32` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 32 bits\n     *\n     * _Available since v3.1._\n     */\n    function toInt32(int256 value) internal pure returns (int32 downcasted) {\n        downcasted = int32(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 32 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int24 from int256, reverting on\n     * overflow (when the input is less than smallest int24 or\n     * greater than largest int24).\n     *\n     * Counterpart to Solidity's `int24` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 24 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt24(int256 value) internal pure returns (int24 downcasted) {\n        downcasted = int24(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 24 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int16 from int256, reverting on\n     * overflow (when the input is less than smallest int16 or\n     * greater than largest int16).\n     *\n     * Counterpart to Solidity's `int16` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 16 bits\n     *\n     * _Available since v3.1._\n     */\n    function toInt16(int256 value) internal pure returns (int16 downcasted) {\n        downcasted = int16(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 16 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int8 from int256, reverting on\n     * overflow (when the input is less than smallest int8 or\n     * greater than largest int8).\n     *\n     * Counterpart to Solidity's `int8` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 8 bits\n     *\n     * _Available since v3.1._\n     */\n    function toInt8(int256 value) internal pure returns (int8 downcasted) {\n        downcasted = int8(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 8 bits\");\n    }\n\n    /**\n     * @dev Converts an unsigned uint256 into a signed int256.\n     *\n     * Requirements:\n     *\n     * - input must be less than or equal to maxInt256.\n     *\n     * _Available since v3.0._\n     */\n    function toInt256(uint256 value) internal pure returns (int256) {\n        // Note: Unsafe cast below is okay because `type(int256).max` is guaranteed to be positive\n        require(value \u003c= uint256(type(int256).max), \"SafeCast: value doesn't fit in an int256\");\n        return int256(value);\n    }\n}\n\n// 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/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// contracts/libs/memory/BaseMessage.sol\n\n/// BaseMessage is a memory view over the base message supported by Origin-Destination\ntype BaseMessage is uint256;\n\nusing BaseMessageLib for BaseMessage global;\n\n/// BaseMessage structure represents a base message sent via the Origin-Destination contracts.\n/// - It only contains data relevant to the base message, the rest of data is encoded in the message header.\n/// - `sender` and `recipient` for EVM chains are EVM addresses casted to bytes32, while preserving left-alignment.\n/// - `tips` and `request` parameters are specified by a message sender\n/// \u003e Origin will calculate minimum tips for given request and content length, and will reject messages with tips\n/// lower than that.\n///\n/// # Memory layout of BaseMessage fields\n///\n/// | Position   | Field     | Type    | Bytes | Description                            |\n/// | ---------- | --------- | ------- | ----- | -------------------------------------- |\n/// | [000..032) | tips      | uint256 | 32    | Encoded tips paid on origin chain      |\n/// | [032..064) | sender    | bytes32 | 32    | Sender address on origin chain         |\n/// | [064..096) | recipient | bytes32 | 32    | Recipient address on destination chain |\n/// | [096..116) | request   | uint160 | 20    | Encoded request for message execution  |\n/// | [104..AAA) | content   | bytes   | ??    | Content to be passed to recipient      |\nlibrary BaseMessageLib {\n    using MemViewLib for bytes;\n\n    /// @dev The variables below are not supposed to be used outside of the library directly.\n    uint256 private constant OFFSET_TIPS = 0;\n    uint256 private constant OFFSET_SENDER = 32;\n    uint256 private constant OFFSET_RECIPIENT = 64;\n    uint256 private constant OFFSET_REQUEST = OFFSET_RECIPIENT + TIPS_LENGTH;\n    uint256 private constant OFFSET_CONTENT = OFFSET_REQUEST + REQUEST_LENGTH;\n\n    // ═══════════════════════════════════════════════ BASE MESSAGE ════════════════════════════════════════════════════\n\n    /**\n     * @notice Returns a formatted BaseMessage payload with provided fields.\n     * @param tips_         Encoded tips information\n     * @param sender_       Sender address on origin chain\n     * @param recipient_    Recipient address on destination chain\n     * @param request_      Encoded request for message execution\n     * @param content_      Raw content to be passed to recipient on destination chain\n     * @return Formatted base message\n     */\n    function formatBaseMessage(Tips tips_, bytes32 sender_, bytes32 recipient_, Request request_, bytes memory content_)\n        internal\n        pure\n        returns (bytes memory)\n    {\n        return abi.encodePacked(tips_, sender_, recipient_, request_, content_);\n    }\n\n    /**\n     * @notice Returns a BaseMessage view over the given payload.\n     * @dev Will revert if the payload is not a base message.\n     */\n    function castToBaseMessage(bytes memory payload) internal pure returns (BaseMessage) {\n        return castToBaseMessage(payload.ref());\n    }\n\n    /**\n     * @notice Casts a memory view to a BaseMessage view.\n     * @dev Will revert if the memory view is not over a base message payload.\n     */\n    function castToBaseMessage(MemView memView) internal pure returns (BaseMessage) {\n        if (!isBaseMessage(memView)) revert UnformattedBaseMessage();\n        return BaseMessage.wrap(MemView.unwrap(memView));\n    }\n\n    /// @notice Checks that a payload is a formatted BaseMessage.\n    function isBaseMessage(MemView memView) internal pure returns (bool) {\n        // Check if sender, recipient, tips fields exist\n        return (memView.len() \u003e= OFFSET_CONTENT);\n        // Content could be empty, so we don't check that\n    }\n\n    /// @notice Convenience shortcut for unwrapping a view.\n    function unwrap(BaseMessage baseMessage) internal pure returns (MemView) {\n        return MemView.wrap(BaseMessage.unwrap(baseMessage));\n    }\n\n    /// @notice Returns baseMessage's hash: a leaf to be inserted in the \"Message mini-Merkle tree\".\n    function leaf(BaseMessage baseMessage) internal pure returns (bytes32) {\n        // We hash \"tips\" and \"everything but tips\" to make tips proofs easier to verify\n        return MerkleMath.getParent(baseMessage.tips().leaf(), baseMessage.bodyLeaf());\n    }\n\n    /// @notice Returns hash for the \"everything but tips\" part of the base message.\n    function bodyLeaf(BaseMessage baseMessage) internal pure returns (bytes32) {\n        return baseMessage.unwrap().sliceFrom({index_: OFFSET_SENDER}).keccak();\n    }\n\n    // ═══════════════════════════════════════════ BASE MESSAGE SLICING ════════════════════════════════════════════════\n\n    /// @notice Returns encoded tips paid on origin chain.\n    function tips(BaseMessage baseMessage) internal pure returns (Tips) {\n        return TipsLib.wrapPadded((baseMessage.unwrap().indexUint({index_: OFFSET_TIPS, bytes_: TIPS_LENGTH})));\n    }\n\n    /// @notice Returns sender address on origin chain.\n    function sender(BaseMessage baseMessage) internal pure returns (bytes32) {\n        return baseMessage.unwrap().index({index_: OFFSET_SENDER, bytes_: 32});\n    }\n\n    /// @notice Returns recipient address on destination chain.\n    function recipient(BaseMessage baseMessage) internal pure returns (bytes32) {\n        return baseMessage.unwrap().index({index_: OFFSET_RECIPIENT, bytes_: 32});\n    }\n\n    /// @notice Returns an encoded request for message execution on destination chain.\n    function request(BaseMessage baseMessage) internal pure returns (Request) {\n        return RequestLib.wrapPadded((baseMessage.unwrap().indexUint({index_: OFFSET_REQUEST, bytes_: REQUEST_LENGTH})));\n    }\n\n    /// @notice Returns an untyped memory view over the content to be passed to recipient.\n    function content(BaseMessage baseMessage) internal pure returns (MemView) {\n        return baseMessage.unwrap().sliceFrom({index_: OFFSET_CONTENT});\n    }\n}\n\n// test/harnesses/libs/memory/BaseMessageHarness.t.sol\n\n// solhint-disable ordering\n/**\n * @notice Exposes BaseMessage methods for testing against golang.\n */\ncontract BaseMessageHarness {\n    using BaseMessageLib for bytes;\n    using BaseMessageLib for MemView;\n    using MemViewLib for bytes;\n\n    // Note: we don't add an empty test() function here, as it currently leads\n    // to zero coverage on the corresponding library.\n\n    // ══════════════════════════════════════════════════ GETTERS ══════════════════════════════════════════════════════\n\n    function castToBaseMessage(bytes memory payload) public view returns (bytes memory) {\n        // Walkaround to get the forge coverage working on libraries, see\n        // https://github.com/foundry-rs/foundry/pull/3128#issuecomment-1241245086\n        BaseMessage baseMessage = BaseMessageLib.castToBaseMessage(payload);\n        return baseMessage.unwrap().clone();\n    }\n\n    /// @notice Returns baseMessage's sender field\n    function sender(bytes memory payload) public pure returns (bytes32) {\n        return payload.castToBaseMessage().sender();\n    }\n\n    /// @notice Returns baseMessage's recipient field as bytes32\n    function recipient(bytes memory payload) public pure returns (bytes32) {\n        return payload.castToBaseMessage().recipient();\n    }\n\n    /// @notice Returns baseMessage's tips field\n    function tips(bytes memory payload) public pure returns (uint256) {\n        return Tips.unwrap(payload.castToBaseMessage().tips());\n    }\n\n    /// @notice Returns baseMessage's request field\n    function request(bytes memory payload) public pure returns (uint192) {\n        return Request.unwrap(payload.castToBaseMessage().request());\n    }\n\n    /// @notice Returns baseMessage's content field\n    function content(bytes memory payload) public view returns (bytes memory) {\n        return payload.castToBaseMessage().content().clone();\n    }\n\n    function isBaseMessage(bytes memory payload) public pure returns (bool) {\n        return payload.ref().isBaseMessage();\n    }\n\n    // ════════════════════════════════════════════════ FORMATTERS ═════════════════════════════════════════════════════\n\n    function formatBaseMessage(Tips tips_, bytes32 sender_, bytes32 recipient_, Request request_, bytes memory content_)\n        public\n        pure\n        returns (bytes memory)\n    {\n        return BaseMessageLib.formatBaseMessage(tips_, sender_, recipient_, request_, content_);\n    }\n\n    function leaf(bytes memory payload) public pure returns (bytes32) {\n        return payload.castToBaseMessage().leaf();\n    }\n\n    function bodyLeaf(bytes memory payload) public pure returns (bytes32) {\n        return payload.castToBaseMessage().bodyLeaf();\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":"80302:6743:0:-:0;;;;;;;;;;;;;;;-1:-1:-1;;;80302:6743:0;;;;;;;;;;;;;;;;;","srcMapRuntime":"80302:6743:0:-:0;;;;;;;;","abiDefinition":[],"userDoc":{"kind":"user","methods":{},"notice":"# Tips Library for formatting _the tips part_ of _the base messages_. ## How the tips are awarded Tips are paid for sending a base message, and are split across all the agents that made the message execution on destination chain possible. ### Summit tips Split between:     - Guard posting a snapshot with state ST_G for the origin chain.     - Notary posting a snapshot SN_N using ST_G. This creates attestation A.     - Notary posting a message receipt after it is executed on destination chain. ### Attestation tips Paid to:     - Notary posting attestation A to destination chain. ### Execution tips Paid to:     - First executor performing a valid execution attempt (correct proofs, optimistic period over),      using attestation A to prove message inclusion on origin chain, whether the recipient reverted or not. ### Delivery tips. Paid to:     - Executor who successfully executed the message on destination chain. ## Tips encoding - Tips occupy a single storage word, and thus are stored on stack instead of being stored in memory. - The actual tip values should be determined by multiplying stored values by divided by TIPS_MULTIPLIER=2**32. - Tips are packed into a single word of storage, while allowing real values up to ~8*10**28 for every tip category. \u003e The only downside is that the \"real tip values\" are now multiplies of ~4*10**9, which should be fine even for the chains with the most expensive gas currency. # Tips stack layout (from highest bits to lowest) | Position   | Field          | Type   | Bytes | Description                                                | | ---------- | -------------- | ------ | ----- | ---------------------------------------------------------- | | (032..024] | summitTip      | uint64 | 8     | Tip for agents interacting with Summit contract            | | (024..016] | attestationTip | uint64 | 8     | Tip for Notary posting attestation to Destination contract | | (016..008] | executionTip   | uint64 | 8     | Tip for valid execution attempt on destination chain       | | (008..000] | deliveryTip    | uint64 | 8     | Tip for successful message delivery on destination chain   |","version":1},"developerDoc":{"kind":"dev","methods":{},"stateVariables":{"SHIFT_ATTESTATION_TIP":{"details":"Amount of bits to shift to attestationTip field"},"SHIFT_EXECUTION_TIP":{"details":"Amount of bits to shift to executionTip field"},"SHIFT_SUMMIT_TIP":{"details":"Amount of bits to shift to summitTip field"}},"version":1},"metadata":"{\"compiler\":{\"version\":\"0.8.17+commit.8df45f5f\"},\"language\":\"Solidity\",\"output\":{\"abi\":[],\"devdoc\":{\"kind\":\"dev\",\"methods\":{},\"stateVariables\":{\"SHIFT_ATTESTATION_TIP\":{\"details\":\"Amount of bits to shift to attestationTip field\"},\"SHIFT_EXECUTION_TIP\":{\"details\":\"Amount of bits to shift to executionTip field\"},\"SHIFT_SUMMIT_TIP\":{\"details\":\"Amount of bits to shift to summitTip field\"}},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"notice\":\"# Tips Library for formatting _the tips part_ of _the base messages_. ## How the tips are awarded Tips are paid for sending a base message, and are split across all the agents that made the message execution on destination chain possible. ### Summit tips Split between:     - Guard posting a snapshot with state ST_G for the origin chain.     - Notary posting a snapshot SN_N using ST_G. This creates attestation A.     - Notary posting a message receipt after it is executed on destination chain. ### Attestation tips Paid to:     - Notary posting attestation A to destination chain. ### Execution tips Paid to:     - First executor performing a valid execution attempt (correct proofs, optimistic period over),      using attestation A to prove message inclusion on origin chain, whether the recipient reverted or not. ### Delivery tips. Paid to:     - Executor who successfully executed the message on destination chain. ## Tips encoding - Tips occupy a single storage word, and thus are stored on stack instead of being stored in memory. - The actual tip values should be determined by multiplying stored values by divided by TIPS_MULTIPLIER=2**32. - Tips are packed into a single word of storage, while allowing real values up to ~8*10**28 for every tip category. \u003e The only downside is that the \\\"real tip values\\\" are now multiplies of ~4*10**9, which should be fine even for the chains with the most expensive gas currency. # Tips stack layout (from highest bits to lowest) | Position   | Field          | Type   | Bytes | Description                                                | | ---------- | -------------- | ------ | ----- | ---------------------------------------------------------- | | (032..024] | summitTip      | uint64 | 8     | Tip for agents interacting with Summit contract            | | (024..016] | attestationTip | uint64 | 8     | Tip for Notary posting attestation to Destination contract | | (016..008] | executionTip   | uint64 | 8     | Tip for valid execution attempt on destination chain       | | (008..000] | deliveryTip    | uint64 | 8     | Tip for successful message delivery on destination chain   |\",\"version\":1}},\"settings\":{\"compilationTarget\":{\"solidity/BaseMessageHarness.t.sol\":\"TipsLib\"},\"evmVersion\":\"london\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\"},\"optimizer\":{\"enabled\":true,\"runs\":10000},\"remappings\":[]},\"sources\":{\"solidity/BaseMessageHarness.t.sol\":{\"keccak256\":\"0x0b644d75605ac5a83f42b70984b4f8c78046e7756cf276e43df1e1f8c1c57ce6\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://89e64be85f0b7caad7e5d5fe0d77b92bb4c97bf9542651212fb3563a019d5bac\",\"dweb:/ipfs/QmVsD4QYYzmJVCjC85GjGjbY2Jooz9rZHSJmvp4hkWxxbR\"]}},\"version\":1}"},"hashes":{}}}