synapsecns/sanguine

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

Summary

Maintainability
Test Coverage
{"solidity/TestClient.sol:IMessageRecipient":{"code":"0x","runtime-code":"0x","info":{"source":"// SPDX-License-Identifier: MIT\npragma solidity =0.8.17;\n\n// contracts/interfaces/IMessageRecipient.sol\n\ninterface IMessageRecipient {\n    /**\n     * @notice Message recipient needs to implement this function in order to\n     * receive cross-chain messages.\n     * @dev Message recipient needs to ensure that merkle proof for the message\n     * is at least as old as the optimistic period that the recipient is using.\n     * Note: as this point it is checked that the \"message optimistic period\" has passed,\n     * however the period value itself could be anything, and thus could differ from the one\n     * that the recipient would like to enforce.\n     * @param origin            Domain where message originated\n     * @param nonce             Message nonce on the origin domain\n     * @param sender            Sender address on origin chain\n     * @param proofMaturity     Message's merkle proof age in seconds\n     * @param version           Message version specified by sender\n     * @param content           Raw bytes content of message\n     */\n    function receiveBaseMessage(\n        uint32 origin,\n        uint32 nonce,\n        bytes32 sender,\n        uint256 proofMaturity,\n        uint32 version,\n        bytes memory content\n    ) external payable;\n}\n\n// contracts/interfaces/InterfaceOrigin.sol\n\ninterface InterfaceOrigin {\n    // ═══════════════════════════════════════════════ SEND MESSAGES ═══════════════════════════════════════════════════\n\n    /**\n     * @notice Send a message to the recipient located on destination domain.\n     * @dev Recipient has to conform to IMessageRecipient interface, otherwise message won't be delivered.\n     * Will revert if any of these is true:\n     * - `destination` is equal to contract's local domain\n     * - `content` length is greater than `MAX_CONTENT_BYTES`\n     * - `msg.value` is lower than value of minimum tips for the given message\n     * @param destination           Domain of destination chain\n     * @param recipient             Address of recipient on destination chain as bytes32\n     * @param optimisticPeriod      Optimistic period for message execution on destination chain\n     * @param paddedRequest         Padded encoded message execution request on destination chain\n     * @param content               Raw bytes content of message\n     * @return messageNonce         Nonce of the sent message\n     * @return messageHash          Hash of the sent message\n     */\n    function sendBaseMessage(\n        uint32 destination,\n        bytes32 recipient,\n        uint32 optimisticPeriod,\n        uint256 paddedRequest,\n        bytes memory content\n    ) external payable returns (uint32 messageNonce, bytes32 messageHash);\n\n    /**\n     * @notice Send a manager message to the destination domain.\n     * @dev This could only be called by AgentManager, which takes care of encoding the calldata payload.\n     * Note: (msgOrigin, proofMaturity) security args will be added to payload on the destination chain\n     * so that the AgentManager could verify where the Manager Message came from and how mature is the proof.\n     * Note: function is not payable, as no tips are required for sending a manager message.\n     * Will revert if `destination` is equal to contract's local domain.\n     * @param destination           Domain of destination chain\n     * @param optimisticPeriod      Optimistic period for message execution on destination chain\n     * @param payload               Payload for calling AgentManager on destination chain (with extra security args)\n     */\n    function sendManagerMessage(uint32 destination, uint32 optimisticPeriod, bytes memory payload)\n        external\n        returns (uint32 messageNonce, bytes32 messageHash);\n\n    // ════════════════════════════════════════════════ TIPS LOGIC ═════════════════════════════════════════════════════\n\n    /**\n     * @notice Withdraws locked base message tips to the recipient.\n     * @dev Could only be called by a local AgentManager.\n     * @param recipient     Address to withdraw tips to\n     * @param amount        Tips value to withdraw\n     */\n    function withdrawTips(address recipient, uint256 amount) external;\n\n    // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════\n\n    /**\n     * @notice Returns the minimum tips value for sending a message to a given destination.\n     * @dev Using at least `tipsValue` as `msg.value` for `sendBaseMessage()`\n     * will guarantee that the message will be accepted.\n     * @param destination       Domain of destination chain\n     * @param paddedRequest     Padded encoded message execution request on destination chain\n     * @param contentLength     The length of the message content\n     * @return tipsValue        Minimum tips value for a message to be accepted\n     */\n    function getMinimumTipsValue(uint32 destination, uint256 paddedRequest, uint256 contentLength)\n        external\n        view\n        returns (uint256 tipsValue);\n}\n\n// contracts/libs/Errors.sol\n\n// ══════════════════════════════ INVALID CALLER ═══════════════════════════════\n\nerror CallerNotAgentManager();\nerror CallerNotDestination();\nerror CallerNotInbox();\nerror CallerNotSummit();\n\n// ══════════════════════════════ INCORRECT DATA ═══════════════════════════════\n\nerror IncorrectAttestation();\nerror IncorrectAgentDomain();\nerror IncorrectAgentIndex();\nerror IncorrectAgentProof();\nerror IncorrectAgentRoot();\nerror IncorrectDataHash();\nerror IncorrectDestinationDomain();\nerror IncorrectOriginDomain();\nerror IncorrectSnapshotProof();\nerror IncorrectSnapshotRoot();\nerror IncorrectState();\nerror IncorrectStatesAmount();\nerror IncorrectTipsProof();\nerror IncorrectVersionLength();\n\nerror IncorrectNonce();\nerror IncorrectSender();\nerror IncorrectRecipient();\n\nerror FlagOutOfRange();\nerror IndexOutOfRange();\nerror NonceOutOfRange();\n\nerror OutdatedNonce();\n\nerror UnformattedAttestation();\nerror UnformattedAttestationReport();\nerror UnformattedBaseMessage();\nerror UnformattedCallData();\nerror UnformattedCallDataPrefix();\nerror UnformattedMessage();\nerror UnformattedReceipt();\nerror UnformattedReceiptReport();\nerror UnformattedSignature();\nerror UnformattedSnapshot();\nerror UnformattedState();\nerror UnformattedStateReport();\n\n// ═══════════════════════════════ MERKLE TREES ════════════════════════════════\n\nerror LeafNotProven();\nerror MerkleTreeFull();\nerror NotEnoughLeafs();\nerror TreeHeightTooLow();\n\n// ═════════════════════════════ OPTIMISTIC PERIOD ═════════════════════════════\n\nerror BaseClientOptimisticPeriod();\nerror MessageOptimisticPeriod();\nerror SlashAgentOptimisticPeriod();\nerror WithdrawTipsOptimisticPeriod();\nerror ZeroProofMaturity();\n\n// ═══════════════════════════════ AGENT MANAGER ═══════════════════════════════\n\nerror AgentNotGuard();\nerror AgentNotNotary();\n\nerror AgentCantBeAdded();\nerror AgentNotActive();\nerror AgentNotActiveNorUnstaking();\nerror AgentNotFraudulent();\nerror AgentNotUnstaking();\nerror AgentUnknown();\n\nerror AgentRootNotProposed();\nerror AgentRootTimeoutNotOver();\n\nerror NotStuck();\n\nerror DisputeAlreadyResolved();\nerror DisputeNotOpened();\nerror DisputeTimeoutNotOver();\nerror GuardInDispute();\nerror NotaryInDispute();\n\nerror MustBeSynapseDomain();\nerror SynapseDomainForbidden();\n\n// ════════════════════════════════ DESTINATION ════════════════════════════════\n\nerror AlreadyExecuted();\nerror AlreadyFailed();\nerror DuplicatedSnapshotRoot();\nerror IncorrectMagicValue();\nerror GasLimitTooLow();\nerror GasSuppliedTooLow();\n\n// ══════════════════════════════════ ORIGIN ═══════════════════════════════════\n\nerror ContentLengthTooBig();\nerror EthTransferFailed();\nerror InsufficientEthBalance();\n\n// ════════════════════════════════ GAS ORACLE ═════════════════════════════════\n\nerror LocalGasDataNotSet();\nerror RemoteGasDataNotSet();\n\n// ═══════════════════════════════════ TIPS ════════════════════════════════════\n\nerror SummitTipTooHigh();\nerror TipsClaimMoreThanEarned();\nerror TipsClaimZero();\nerror TipsOverflow();\nerror TipsValueTooLow();\n\n// ════════════════════════════════ MEMORY VIEW ════════════════════════════════\n\nerror IndexedTooMuch();\nerror ViewOverrun();\nerror OccupiedMemory();\nerror UnallocatedMemory();\nerror PrecompileOutOfGas();\n\n// ═════════════════════════════════ MULTICALL ═════════════════════════════════\n\nerror MulticallFailed();\n\n// contracts/libs/TypeCasts.sol\n\nlibrary TypeCasts {\n    // alignment preserving cast\n    function addressToBytes32(address addr) internal pure returns (bytes32) {\n        return bytes32(uint256(uint160(addr)));\n    }\n\n    // alignment preserving cast\n    function bytes32ToAddress(bytes32 buf) internal pure returns (address) {\n        return address(uint160(uint256(buf)));\n    }\n}\n\n// contracts/libs/stack/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// contracts/client/MessageRecipient.sol\n\n// ══════════════════════════════ LIBRARY IMPORTS ══════════════════════════════\n\n// ═════════════════════════════ INTERNAL IMPORTS ══════════════════════════════\n\nabstract contract MessageRecipient is IMessageRecipient {\n    struct MessageRequest {\n        uint96 gasDrop;\n        uint64 gasLimit;\n        uint32 version;\n    }\n\n    /// @notice Local chain Origin: used for sending messages\n    address public immutable origin;\n\n    /// @notice Local chain Destination: used for receiving messages\n    address public immutable destination;\n\n    constructor(address origin_, address destination_) {\n        origin = origin_;\n        destination = destination_;\n    }\n\n    /// @inheritdoc IMessageRecipient\n    function receiveBaseMessage(\n        uint32 origin_,\n        uint32 nonce,\n        bytes32 sender,\n        uint256 proofMaturity,\n        uint32 version,\n        bytes memory content\n    ) external payable {\n        if (msg.sender != destination) revert CallerNotDestination();\n        if (nonce == 0) revert IncorrectNonce();\n        if (sender == 0) revert IncorrectSender();\n        if (proofMaturity == 0) revert ZeroProofMaturity();\n        _receiveBaseMessageUnsafe(origin_, nonce, sender, proofMaturity, version, content);\n    }\n\n    /**\n     * @dev Child contracts should implement the logic for receiving a Base Message in an \"unsafe way\".\n     * Following checks HAVE been performed:\n     *  - receiveBaseMessage() was called by Destination (i.e. this is a legit base message).\n     *  - Nonce is not zero.\n     *  - Message sender on origin chain is not a zero address.\n     *  - Proof maturity is not zero.\n     * Following checks HAVE NOT been performed (thus \"unsafe\"):\n     *  - Message sender on origin chain could be anything non-zero at this point.\n     *  - Proof maturity could be anything non-zero at this point.\n     */\n    function _receiveBaseMessageUnsafe(\n        uint32 origin_,\n        uint32 nonce,\n        bytes32 sender,\n        uint256 proofMaturity,\n        uint32 version,\n        bytes memory content\n    ) internal virtual;\n\n    /**\n     * @dev Sends a message to given destination chain. Full `msg.value` is used to pay for the message tips.\n     * `_getMinimumTipsValue()` could be used to calculate the minimum required tips value, and should be also\n     * exposed as a public view function to estimate the tips value before sending a message off-chain.\n     * This function is not exposed in MessageRecipient, as the message encoding is implemented by the child contract.\n     * @param destination_          Domain of the destination chain\n     * @param recipient             Address of the recipient on destination chain\n     * @param optimisticPeriod      Optimistic period for the message\n     * @param tipsValue             Tips to be paid for sending the message\n     * @param request               Message execution request on destination chain\n     * @param content               The message content\n     */\n    function _sendBaseMessage(\n        uint32 destination_,\n        bytes32 recipient,\n        uint32 optimisticPeriod,\n        uint256 tipsValue,\n        MessageRequest memory request,\n        bytes memory content\n    ) internal returns (uint32 messageNonce, bytes32 messageHash) {\n        if (recipient == 0) revert IncorrectRecipient();\n        return InterfaceOrigin(origin).sendBaseMessage{value: tipsValue}(\n            destination_, recipient, optimisticPeriod, _encodeRequest(request), content\n        );\n    }\n\n    /**\n     * @dev Returns the minimum tips value for sending a message to given destination chain.\n     * @param destination_          Domain of the destination chain\n     * @param request               Message execution request on destination chain\n     * @param contentLength         Length of the message content\n     */\n    function _getMinimumTipsValue(uint32 destination_, MessageRequest memory request, uint256 contentLength)\n        internal\n        view\n        returns (uint256 tipsValue)\n    {\n        return InterfaceOrigin(origin).getMinimumTipsValue(destination_, _encodeRequest(request), contentLength);\n    }\n\n    /**\n     * @dev Encodes a message execution request into format that Origin contract is using.\n     * @param request               Message execution request on destination chain\n     * @return paddedRequest        Encoded request\n     */\n    function _encodeRequest(MessageRequest memory request) internal pure returns (uint256 paddedRequest) {\n        return Request.unwrap(RequestLib.encodeRequest(request.gasDrop, request.gasLimit, request.version));\n    }\n}\n\n// contracts/client/TestClient.sol\n\n// ══════════════════════════════ LIBRARY IMPORTS ══════════════════════════════\n\n// ═════════════════════════════ INTERNAL IMPORTS ══════════════════════════════\n\ncontract TestClient is MessageRecipient {\n    event MessageReceived(\n        uint32 origin, uint32 nonce, bytes32 sender, uint256 proofMaturity, uint32 version, bytes content\n    );\n\n    event MessageSent(uint32 destination, uint32 nonce, bytes32 sender, bytes32 recipient, bytes content);\n\n    // solhint-disable-next-line no-empty-blocks\n    constructor(address origin_, address destination_) MessageRecipient(origin_, destination_) {}\n\n    function sendMessage(\n        uint32 destination_,\n        address recipientAddress,\n        uint32 optimisticPeriod,\n        uint64 gasLimit,\n        uint32 version,\n        bytes memory content\n    ) external payable {\n        bytes32 recipient = TypeCasts.addressToBytes32(recipientAddress);\n        MessageRequest memory request = MessageRequest({gasDrop: 0, gasLimit: gasLimit, version: version});\n        (uint32 nonce,) = _sendBaseMessage({\n            destination_: destination_,\n            recipient: recipient,\n            optimisticPeriod: optimisticPeriod,\n            tipsValue: msg.value,\n            request: request,\n            content: content\n        });\n        emit MessageSent(destination_, nonce, TypeCasts.addressToBytes32(address(this)), recipient, content);\n    }\n\n    /// @inheritdoc MessageRecipient\n    function _receiveBaseMessageUnsafe(\n        uint32 origin_,\n        uint32 nonce,\n        bytes32 sender,\n        uint256 proofMaturity,\n        uint32 version,\n        bytes memory content\n    ) internal override {\n        emit MessageReceived(origin_, nonce, sender, proofMaturity, version, content);\n    }\n}\n","language":"Solidity","languageVersion":"0.8.17","compilerVersion":"0.8.17","compilerOptions":"--combined-json bin,bin-runtime,srcmap,srcmap-runtime,abi,userdoc,devdoc,metadata,hashes --optimize --optimize-runs 10000 --allow-paths ., ./, ../","srcMap":"","srcMapRuntime":"","abiDefinition":[{"inputs":[{"internalType":"uint32","name":"origin","type":"uint32"},{"internalType":"uint32","name":"nonce","type":"uint32"},{"internalType":"bytes32","name":"sender","type":"bytes32"},{"internalType":"uint256","name":"proofMaturity","type":"uint256"},{"internalType":"uint32","name":"version","type":"uint32"},{"internalType":"bytes","name":"content","type":"bytes"}],"name":"receiveBaseMessage","outputs":[],"stateMutability":"payable","type":"function"}],"userDoc":{"kind":"user","methods":{"receiveBaseMessage(uint32,uint32,bytes32,uint256,uint32,bytes)":{"notice":"Message recipient needs to implement this function in order to receive cross-chain messages."}},"version":1},"developerDoc":{"kind":"dev","methods":{"receiveBaseMessage(uint32,uint32,bytes32,uint256,uint32,bytes)":{"details":"Message recipient needs to ensure that merkle proof for the message is at least as old as the optimistic period that the recipient is using. Note: as this point it is checked that the \"message optimistic period\" has passed, however the period value itself could be anything, and thus could differ from the one that the recipient would like to enforce.","params":{"content":"Raw bytes content of message","nonce":"Message nonce on the origin domain","origin":"Domain where message originated","proofMaturity":"Message's merkle proof age in seconds","sender":"Sender address on origin chain","version":"Message version specified by sender"}}},"version":1},"metadata":"{\"compiler\":{\"version\":\"0.8.17+commit.8df45f5f\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"uint32\",\"name\":\"origin\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"nonce\",\"type\":\"uint32\"},{\"internalType\":\"bytes32\",\"name\":\"sender\",\"type\":\"bytes32\"},{\"internalType\":\"uint256\",\"name\":\"proofMaturity\",\"type\":\"uint256\"},{\"internalType\":\"uint32\",\"name\":\"version\",\"type\":\"uint32\"},{\"internalType\":\"bytes\",\"name\":\"content\",\"type\":\"bytes\"}],\"name\":\"receiveBaseMessage\",\"outputs\":[],\"stateMutability\":\"payable\",\"type\":\"function\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{\"receiveBaseMessage(uint32,uint32,bytes32,uint256,uint32,bytes)\":{\"details\":\"Message recipient needs to ensure that merkle proof for the message is at least as old as the optimistic period that the recipient is using. Note: as this point it is checked that the \\\"message optimistic period\\\" has passed, however the period value itself could be anything, and thus could differ from the one that the recipient would like to enforce.\",\"params\":{\"content\":\"Raw bytes content of message\",\"nonce\":\"Message nonce on the origin domain\",\"origin\":\"Domain where message originated\",\"proofMaturity\":\"Message's merkle proof age in seconds\",\"sender\":\"Sender address on origin chain\",\"version\":\"Message version specified by sender\"}}},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{\"receiveBaseMessage(uint32,uint32,bytes32,uint256,uint32,bytes)\":{\"notice\":\"Message recipient needs to implement this function in order to receive cross-chain messages.\"}},\"version\":1}},\"settings\":{\"compilationTarget\":{\"solidity/TestClient.sol\":\"IMessageRecipient\"},\"evmVersion\":\"london\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\"},\"optimizer\":{\"enabled\":true,\"runs\":10000},\"remappings\":[]},\"sources\":{\"solidity/TestClient.sol\":{\"keccak256\":\"0x0559f7adcbbadc7e14f6d1a8909db6085e58daebca746390c188879460d4fb90\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://dfac7d1d9b1255e057dc37b120623dd3edb15a776ce793b81955ab51c6f59ba1\",\"dweb:/ipfs/Qmd7j2CjYA91DTqJMMmnTt4Y9wvDdhVH7Bgt4MFBPdY3rS\"]}},\"version\":1}"},"hashes":{"receiveBaseMessage(uint32,uint32,bytes32,uint256,uint32,bytes)":"032f287e"}},"solidity/TestClient.sol:InterfaceOrigin":{"code":"0x","runtime-code":"0x","info":{"source":"// SPDX-License-Identifier: MIT\npragma solidity =0.8.17;\n\n// contracts/interfaces/IMessageRecipient.sol\n\ninterface IMessageRecipient {\n    /**\n     * @notice Message recipient needs to implement this function in order to\n     * receive cross-chain messages.\n     * @dev Message recipient needs to ensure that merkle proof for the message\n     * is at least as old as the optimistic period that the recipient is using.\n     * Note: as this point it is checked that the \"message optimistic period\" has passed,\n     * however the period value itself could be anything, and thus could differ from the one\n     * that the recipient would like to enforce.\n     * @param origin            Domain where message originated\n     * @param nonce             Message nonce on the origin domain\n     * @param sender            Sender address on origin chain\n     * @param proofMaturity     Message's merkle proof age in seconds\n     * @param version           Message version specified by sender\n     * @param content           Raw bytes content of message\n     */\n    function receiveBaseMessage(\n        uint32 origin,\n        uint32 nonce,\n        bytes32 sender,\n        uint256 proofMaturity,\n        uint32 version,\n        bytes memory content\n    ) external payable;\n}\n\n// contracts/interfaces/InterfaceOrigin.sol\n\ninterface InterfaceOrigin {\n    // ═══════════════════════════════════════════════ SEND MESSAGES ═══════════════════════════════════════════════════\n\n    /**\n     * @notice Send a message to the recipient located on destination domain.\n     * @dev Recipient has to conform to IMessageRecipient interface, otherwise message won't be delivered.\n     * Will revert if any of these is true:\n     * - `destination` is equal to contract's local domain\n     * - `content` length is greater than `MAX_CONTENT_BYTES`\n     * - `msg.value` is lower than value of minimum tips for the given message\n     * @param destination           Domain of destination chain\n     * @param recipient             Address of recipient on destination chain as bytes32\n     * @param optimisticPeriod      Optimistic period for message execution on destination chain\n     * @param paddedRequest         Padded encoded message execution request on destination chain\n     * @param content               Raw bytes content of message\n     * @return messageNonce         Nonce of the sent message\n     * @return messageHash          Hash of the sent message\n     */\n    function sendBaseMessage(\n        uint32 destination,\n        bytes32 recipient,\n        uint32 optimisticPeriod,\n        uint256 paddedRequest,\n        bytes memory content\n    ) external payable returns (uint32 messageNonce, bytes32 messageHash);\n\n    /**\n     * @notice Send a manager message to the destination domain.\n     * @dev This could only be called by AgentManager, which takes care of encoding the calldata payload.\n     * Note: (msgOrigin, proofMaturity) security args will be added to payload on the destination chain\n     * so that the AgentManager could verify where the Manager Message came from and how mature is the proof.\n     * Note: function is not payable, as no tips are required for sending a manager message.\n     * Will revert if `destination` is equal to contract's local domain.\n     * @param destination           Domain of destination chain\n     * @param optimisticPeriod      Optimistic period for message execution on destination chain\n     * @param payload               Payload for calling AgentManager on destination chain (with extra security args)\n     */\n    function sendManagerMessage(uint32 destination, uint32 optimisticPeriod, bytes memory payload)\n        external\n        returns (uint32 messageNonce, bytes32 messageHash);\n\n    // ════════════════════════════════════════════════ TIPS LOGIC ═════════════════════════════════════════════════════\n\n    /**\n     * @notice Withdraws locked base message tips to the recipient.\n     * @dev Could only be called by a local AgentManager.\n     * @param recipient     Address to withdraw tips to\n     * @param amount        Tips value to withdraw\n     */\n    function withdrawTips(address recipient, uint256 amount) external;\n\n    // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════\n\n    /**\n     * @notice Returns the minimum tips value for sending a message to a given destination.\n     * @dev Using at least `tipsValue` as `msg.value` for `sendBaseMessage()`\n     * will guarantee that the message will be accepted.\n     * @param destination       Domain of destination chain\n     * @param paddedRequest     Padded encoded message execution request on destination chain\n     * @param contentLength     The length of the message content\n     * @return tipsValue        Minimum tips value for a message to be accepted\n     */\n    function getMinimumTipsValue(uint32 destination, uint256 paddedRequest, uint256 contentLength)\n        external\n        view\n        returns (uint256 tipsValue);\n}\n\n// contracts/libs/Errors.sol\n\n// ══════════════════════════════ INVALID CALLER ═══════════════════════════════\n\nerror CallerNotAgentManager();\nerror CallerNotDestination();\nerror CallerNotInbox();\nerror CallerNotSummit();\n\n// ══════════════════════════════ INCORRECT DATA ═══════════════════════════════\n\nerror IncorrectAttestation();\nerror IncorrectAgentDomain();\nerror IncorrectAgentIndex();\nerror IncorrectAgentProof();\nerror IncorrectAgentRoot();\nerror IncorrectDataHash();\nerror IncorrectDestinationDomain();\nerror IncorrectOriginDomain();\nerror IncorrectSnapshotProof();\nerror IncorrectSnapshotRoot();\nerror IncorrectState();\nerror IncorrectStatesAmount();\nerror IncorrectTipsProof();\nerror IncorrectVersionLength();\n\nerror IncorrectNonce();\nerror IncorrectSender();\nerror IncorrectRecipient();\n\nerror FlagOutOfRange();\nerror IndexOutOfRange();\nerror NonceOutOfRange();\n\nerror OutdatedNonce();\n\nerror UnformattedAttestation();\nerror UnformattedAttestationReport();\nerror UnformattedBaseMessage();\nerror UnformattedCallData();\nerror UnformattedCallDataPrefix();\nerror UnformattedMessage();\nerror UnformattedReceipt();\nerror UnformattedReceiptReport();\nerror UnformattedSignature();\nerror UnformattedSnapshot();\nerror UnformattedState();\nerror UnformattedStateReport();\n\n// ═══════════════════════════════ MERKLE TREES ════════════════════════════════\n\nerror LeafNotProven();\nerror MerkleTreeFull();\nerror NotEnoughLeafs();\nerror TreeHeightTooLow();\n\n// ═════════════════════════════ OPTIMISTIC PERIOD ═════════════════════════════\n\nerror BaseClientOptimisticPeriod();\nerror MessageOptimisticPeriod();\nerror SlashAgentOptimisticPeriod();\nerror WithdrawTipsOptimisticPeriod();\nerror ZeroProofMaturity();\n\n// ═══════════════════════════════ AGENT MANAGER ═══════════════════════════════\n\nerror AgentNotGuard();\nerror AgentNotNotary();\n\nerror AgentCantBeAdded();\nerror AgentNotActive();\nerror AgentNotActiveNorUnstaking();\nerror AgentNotFraudulent();\nerror AgentNotUnstaking();\nerror AgentUnknown();\n\nerror AgentRootNotProposed();\nerror AgentRootTimeoutNotOver();\n\nerror NotStuck();\n\nerror DisputeAlreadyResolved();\nerror DisputeNotOpened();\nerror DisputeTimeoutNotOver();\nerror GuardInDispute();\nerror NotaryInDispute();\n\nerror MustBeSynapseDomain();\nerror SynapseDomainForbidden();\n\n// ════════════════════════════════ DESTINATION ════════════════════════════════\n\nerror AlreadyExecuted();\nerror AlreadyFailed();\nerror DuplicatedSnapshotRoot();\nerror IncorrectMagicValue();\nerror GasLimitTooLow();\nerror GasSuppliedTooLow();\n\n// ══════════════════════════════════ ORIGIN ═══════════════════════════════════\n\nerror ContentLengthTooBig();\nerror EthTransferFailed();\nerror InsufficientEthBalance();\n\n// ════════════════════════════════ GAS ORACLE ═════════════════════════════════\n\nerror LocalGasDataNotSet();\nerror RemoteGasDataNotSet();\n\n// ═══════════════════════════════════ TIPS ════════════════════════════════════\n\nerror SummitTipTooHigh();\nerror TipsClaimMoreThanEarned();\nerror TipsClaimZero();\nerror TipsOverflow();\nerror TipsValueTooLow();\n\n// ════════════════════════════════ MEMORY VIEW ════════════════════════════════\n\nerror IndexedTooMuch();\nerror ViewOverrun();\nerror OccupiedMemory();\nerror UnallocatedMemory();\nerror PrecompileOutOfGas();\n\n// ═════════════════════════════════ MULTICALL ═════════════════════════════════\n\nerror MulticallFailed();\n\n// contracts/libs/TypeCasts.sol\n\nlibrary TypeCasts {\n    // alignment preserving cast\n    function addressToBytes32(address addr) internal pure returns (bytes32) {\n        return bytes32(uint256(uint160(addr)));\n    }\n\n    // alignment preserving cast\n    function bytes32ToAddress(bytes32 buf) internal pure returns (address) {\n        return address(uint160(uint256(buf)));\n    }\n}\n\n// contracts/libs/stack/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// contracts/client/MessageRecipient.sol\n\n// ══════════════════════════════ LIBRARY IMPORTS ══════════════════════════════\n\n// ═════════════════════════════ INTERNAL IMPORTS ══════════════════════════════\n\nabstract contract MessageRecipient is IMessageRecipient {\n    struct MessageRequest {\n        uint96 gasDrop;\n        uint64 gasLimit;\n        uint32 version;\n    }\n\n    /// @notice Local chain Origin: used for sending messages\n    address public immutable origin;\n\n    /// @notice Local chain Destination: used for receiving messages\n    address public immutable destination;\n\n    constructor(address origin_, address destination_) {\n        origin = origin_;\n        destination = destination_;\n    }\n\n    /// @inheritdoc IMessageRecipient\n    function receiveBaseMessage(\n        uint32 origin_,\n        uint32 nonce,\n        bytes32 sender,\n        uint256 proofMaturity,\n        uint32 version,\n        bytes memory content\n    ) external payable {\n        if (msg.sender != destination) revert CallerNotDestination();\n        if (nonce == 0) revert IncorrectNonce();\n        if (sender == 0) revert IncorrectSender();\n        if (proofMaturity == 0) revert ZeroProofMaturity();\n        _receiveBaseMessageUnsafe(origin_, nonce, sender, proofMaturity, version, content);\n    }\n\n    /**\n     * @dev Child contracts should implement the logic for receiving a Base Message in an \"unsafe way\".\n     * Following checks HAVE been performed:\n     *  - receiveBaseMessage() was called by Destination (i.e. this is a legit base message).\n     *  - Nonce is not zero.\n     *  - Message sender on origin chain is not a zero address.\n     *  - Proof maturity is not zero.\n     * Following checks HAVE NOT been performed (thus \"unsafe\"):\n     *  - Message sender on origin chain could be anything non-zero at this point.\n     *  - Proof maturity could be anything non-zero at this point.\n     */\n    function _receiveBaseMessageUnsafe(\n        uint32 origin_,\n        uint32 nonce,\n        bytes32 sender,\n        uint256 proofMaturity,\n        uint32 version,\n        bytes memory content\n    ) internal virtual;\n\n    /**\n     * @dev Sends a message to given destination chain. Full `msg.value` is used to pay for the message tips.\n     * `_getMinimumTipsValue()` could be used to calculate the minimum required tips value, and should be also\n     * exposed as a public view function to estimate the tips value before sending a message off-chain.\n     * This function is not exposed in MessageRecipient, as the message encoding is implemented by the child contract.\n     * @param destination_          Domain of the destination chain\n     * @param recipient             Address of the recipient on destination chain\n     * @param optimisticPeriod      Optimistic period for the message\n     * @param tipsValue             Tips to be paid for sending the message\n     * @param request               Message execution request on destination chain\n     * @param content               The message content\n     */\n    function _sendBaseMessage(\n        uint32 destination_,\n        bytes32 recipient,\n        uint32 optimisticPeriod,\n        uint256 tipsValue,\n        MessageRequest memory request,\n        bytes memory content\n    ) internal returns (uint32 messageNonce, bytes32 messageHash) {\n        if (recipient == 0) revert IncorrectRecipient();\n        return InterfaceOrigin(origin).sendBaseMessage{value: tipsValue}(\n            destination_, recipient, optimisticPeriod, _encodeRequest(request), content\n        );\n    }\n\n    /**\n     * @dev Returns the minimum tips value for sending a message to given destination chain.\n     * @param destination_          Domain of the destination chain\n     * @param request               Message execution request on destination chain\n     * @param contentLength         Length of the message content\n     */\n    function _getMinimumTipsValue(uint32 destination_, MessageRequest memory request, uint256 contentLength)\n        internal\n        view\n        returns (uint256 tipsValue)\n    {\n        return InterfaceOrigin(origin).getMinimumTipsValue(destination_, _encodeRequest(request), contentLength);\n    }\n\n    /**\n     * @dev Encodes a message execution request into format that Origin contract is using.\n     * @param request               Message execution request on destination chain\n     * @return paddedRequest        Encoded request\n     */\n    function _encodeRequest(MessageRequest memory request) internal pure returns (uint256 paddedRequest) {\n        return Request.unwrap(RequestLib.encodeRequest(request.gasDrop, request.gasLimit, request.version));\n    }\n}\n\n// contracts/client/TestClient.sol\n\n// ══════════════════════════════ LIBRARY IMPORTS ══════════════════════════════\n\n// ═════════════════════════════ INTERNAL IMPORTS ══════════════════════════════\n\ncontract TestClient is MessageRecipient {\n    event MessageReceived(\n        uint32 origin, uint32 nonce, bytes32 sender, uint256 proofMaturity, uint32 version, bytes content\n    );\n\n    event MessageSent(uint32 destination, uint32 nonce, bytes32 sender, bytes32 recipient, bytes content);\n\n    // solhint-disable-next-line no-empty-blocks\n    constructor(address origin_, address destination_) MessageRecipient(origin_, destination_) {}\n\n    function sendMessage(\n        uint32 destination_,\n        address recipientAddress,\n        uint32 optimisticPeriod,\n        uint64 gasLimit,\n        uint32 version,\n        bytes memory content\n    ) external payable {\n        bytes32 recipient = TypeCasts.addressToBytes32(recipientAddress);\n        MessageRequest memory request = MessageRequest({gasDrop: 0, gasLimit: gasLimit, version: version});\n        (uint32 nonce,) = _sendBaseMessage({\n            destination_: destination_,\n            recipient: recipient,\n            optimisticPeriod: optimisticPeriod,\n            tipsValue: msg.value,\n            request: request,\n            content: content\n        });\n        emit MessageSent(destination_, nonce, TypeCasts.addressToBytes32(address(this)), recipient, content);\n    }\n\n    /// @inheritdoc MessageRecipient\n    function _receiveBaseMessageUnsafe(\n        uint32 origin_,\n        uint32 nonce,\n        bytes32 sender,\n        uint256 proofMaturity,\n        uint32 version,\n        bytes memory content\n    ) internal override {\n        emit MessageReceived(origin_, nonce, sender, proofMaturity, version, content);\n    }\n}\n","language":"Solidity","languageVersion":"0.8.17","compilerVersion":"0.8.17","compilerOptions":"--combined-json bin,bin-runtime,srcmap,srcmap-runtime,abi,userdoc,devdoc,metadata,hashes --optimize --optimize-runs 10000 --allow-paths ., ./, ../","srcMap":"","srcMapRuntime":"","abiDefinition":[{"inputs":[{"internalType":"uint32","name":"destination","type":"uint32"},{"internalType":"uint256","name":"paddedRequest","type":"uint256"},{"internalType":"uint256","name":"contentLength","type":"uint256"}],"name":"getMinimumTipsValue","outputs":[{"internalType":"uint256","name":"tipsValue","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint32","name":"destination","type":"uint32"},{"internalType":"bytes32","name":"recipient","type":"bytes32"},{"internalType":"uint32","name":"optimisticPeriod","type":"uint32"},{"internalType":"uint256","name":"paddedRequest","type":"uint256"},{"internalType":"bytes","name":"content","type":"bytes"}],"name":"sendBaseMessage","outputs":[{"internalType":"uint32","name":"messageNonce","type":"uint32"},{"internalType":"bytes32","name":"messageHash","type":"bytes32"}],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"uint32","name":"destination","type":"uint32"},{"internalType":"uint32","name":"optimisticPeriod","type":"uint32"},{"internalType":"bytes","name":"payload","type":"bytes"}],"name":"sendManagerMessage","outputs":[{"internalType":"uint32","name":"messageNonce","type":"uint32"},{"internalType":"bytes32","name":"messageHash","type":"bytes32"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"recipient","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"withdrawTips","outputs":[],"stateMutability":"nonpayable","type":"function"}],"userDoc":{"kind":"user","methods":{"getMinimumTipsValue(uint32,uint256,uint256)":{"notice":"Returns the minimum tips value for sending a message to a given destination."},"sendBaseMessage(uint32,bytes32,uint32,uint256,bytes)":{"notice":"Send a message to the recipient located on destination domain."},"sendManagerMessage(uint32,uint32,bytes)":{"notice":"Send a manager message to the destination domain."},"withdrawTips(address,uint256)":{"notice":"Withdraws locked base message tips to the recipient."}},"version":1},"developerDoc":{"kind":"dev","methods":{"getMinimumTipsValue(uint32,uint256,uint256)":{"details":"Using at least `tipsValue` as `msg.value` for `sendBaseMessage()` will guarantee that the message will be accepted.","params":{"contentLength":"The length of the message content","destination":"Domain of destination chain","paddedRequest":"Padded encoded message execution request on destination chain"},"returns":{"tipsValue":"       Minimum tips value for a message to be accepted"}},"sendBaseMessage(uint32,bytes32,uint32,uint256,bytes)":{"details":"Recipient has to conform to IMessageRecipient interface, otherwise message won't be delivered. Will revert if any of these is true: - `destination` is equal to contract's local domain - `content` length is greater than `MAX_CONTENT_BYTES` - `msg.value` is lower than value of minimum tips for the given message","params":{"content":"Raw bytes content of message","destination":"Domain of destination chain","optimisticPeriod":"Optimistic period for message execution on destination chain","paddedRequest":"Padded encoded message execution request on destination chain","recipient":"Address of recipient on destination chain as bytes32"},"returns":{"messageHash":"         Hash of the sent message","messageNonce":"        Nonce of the sent message"}},"sendManagerMessage(uint32,uint32,bytes)":{"details":"This could only be called by AgentManager, which takes care of encoding the calldata payload. Note: (msgOrigin, proofMaturity) security args will be added to payload on the destination chain so that the AgentManager could verify where the Manager Message came from and how mature is the proof. Note: function is not payable, as no tips are required for sending a manager message. Will revert if `destination` is equal to contract's local domain.","params":{"destination":"Domain of destination chain","optimisticPeriod":"Optimistic period for message execution on destination chain","payload":"Payload for calling AgentManager on destination chain (with extra security args)"}},"withdrawTips(address,uint256)":{"details":"Could only be called by a local AgentManager.","params":{"amount":"Tips value to withdraw","recipient":"Address to withdraw tips to"}}},"version":1},"metadata":"{\"compiler\":{\"version\":\"0.8.17+commit.8df45f5f\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"uint32\",\"name\":\"destination\",\"type\":\"uint32\"},{\"internalType\":\"uint256\",\"name\":\"paddedRequest\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"contentLength\",\"type\":\"uint256\"}],\"name\":\"getMinimumTipsValue\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"tipsValue\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint32\",\"name\":\"destination\",\"type\":\"uint32\"},{\"internalType\":\"bytes32\",\"name\":\"recipient\",\"type\":\"bytes32\"},{\"internalType\":\"uint32\",\"name\":\"optimisticPeriod\",\"type\":\"uint32\"},{\"internalType\":\"uint256\",\"name\":\"paddedRequest\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"content\",\"type\":\"bytes\"}],\"name\":\"sendBaseMessage\",\"outputs\":[{\"internalType\":\"uint32\",\"name\":\"messageNonce\",\"type\":\"uint32\"},{\"internalType\":\"bytes32\",\"name\":\"messageHash\",\"type\":\"bytes32\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint32\",\"name\":\"destination\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"optimisticPeriod\",\"type\":\"uint32\"},{\"internalType\":\"bytes\",\"name\":\"payload\",\"type\":\"bytes\"}],\"name\":\"sendManagerMessage\",\"outputs\":[{\"internalType\":\"uint32\",\"name\":\"messageNonce\",\"type\":\"uint32\"},{\"internalType\":\"bytes32\",\"name\":\"messageHash\",\"type\":\"bytes32\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"recipient\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"withdrawTips\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{\"getMinimumTipsValue(uint32,uint256,uint256)\":{\"details\":\"Using at least `tipsValue` as `msg.value` for `sendBaseMessage()` will guarantee that the message will be accepted.\",\"params\":{\"contentLength\":\"The length of the message content\",\"destination\":\"Domain of destination chain\",\"paddedRequest\":\"Padded encoded message execution request on destination chain\"},\"returns\":{\"tipsValue\":\"       Minimum tips value for a message to be accepted\"}},\"sendBaseMessage(uint32,bytes32,uint32,uint256,bytes)\":{\"details\":\"Recipient has to conform to IMessageRecipient interface, otherwise message won't be delivered. Will revert if any of these is true: - `destination` is equal to contract's local domain - `content` length is greater than `MAX_CONTENT_BYTES` - `msg.value` is lower than value of minimum tips for the given message\",\"params\":{\"content\":\"Raw bytes content of message\",\"destination\":\"Domain of destination chain\",\"optimisticPeriod\":\"Optimistic period for message execution on destination chain\",\"paddedRequest\":\"Padded encoded message execution request on destination chain\",\"recipient\":\"Address of recipient on destination chain as bytes32\"},\"returns\":{\"messageHash\":\"         Hash of the sent message\",\"messageNonce\":\"        Nonce of the sent message\"}},\"sendManagerMessage(uint32,uint32,bytes)\":{\"details\":\"This could only be called by AgentManager, which takes care of encoding the calldata payload. Note: (msgOrigin, proofMaturity) security args will be added to payload on the destination chain so that the AgentManager could verify where the Manager Message came from and how mature is the proof. Note: function is not payable, as no tips are required for sending a manager message. Will revert if `destination` is equal to contract's local domain.\",\"params\":{\"destination\":\"Domain of destination chain\",\"optimisticPeriod\":\"Optimistic period for message execution on destination chain\",\"payload\":\"Payload for calling AgentManager on destination chain (with extra security args)\"}},\"withdrawTips(address,uint256)\":{\"details\":\"Could only be called by a local AgentManager.\",\"params\":{\"amount\":\"Tips value to withdraw\",\"recipient\":\"Address to withdraw tips to\"}}},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{\"getMinimumTipsValue(uint32,uint256,uint256)\":{\"notice\":\"Returns the minimum tips value for sending a message to a given destination.\"},\"sendBaseMessage(uint32,bytes32,uint32,uint256,bytes)\":{\"notice\":\"Send a message to the recipient located on destination domain.\"},\"sendManagerMessage(uint32,uint32,bytes)\":{\"notice\":\"Send a manager message to the destination domain.\"},\"withdrawTips(address,uint256)\":{\"notice\":\"Withdraws locked base message tips to the recipient.\"}},\"version\":1}},\"settings\":{\"compilationTarget\":{\"solidity/TestClient.sol\":\"InterfaceOrigin\"},\"evmVersion\":\"london\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\"},\"optimizer\":{\"enabled\":true,\"runs\":10000},\"remappings\":[]},\"sources\":{\"solidity/TestClient.sol\":{\"keccak256\":\"0x0559f7adcbbadc7e14f6d1a8909db6085e58daebca746390c188879460d4fb90\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://dfac7d1d9b1255e057dc37b120623dd3edb15a776ce793b81955ab51c6f59ba1\",\"dweb:/ipfs/Qmd7j2CjYA91DTqJMMmnTt4Y9wvDdhVH7Bgt4MFBPdY3rS\"]}},\"version\":1}"},"hashes":{"getMinimumTipsValue(uint32,uint256,uint256)":"4fc6ad85","sendBaseMessage(uint32,bytes32,uint32,uint256,bytes)":"873661bd","sendManagerMessage(uint32,uint32,bytes)":"a1c702a7","withdrawTips(address,uint256)":"4e04e7a7"}},"solidity/TestClient.sol:MessageRecipient":{"code":"0x","runtime-code":"0x","info":{"source":"// SPDX-License-Identifier: MIT\npragma solidity =0.8.17;\n\n// contracts/interfaces/IMessageRecipient.sol\n\ninterface IMessageRecipient {\n    /**\n     * @notice Message recipient needs to implement this function in order to\n     * receive cross-chain messages.\n     * @dev Message recipient needs to ensure that merkle proof for the message\n     * is at least as old as the optimistic period that the recipient is using.\n     * Note: as this point it is checked that the \"message optimistic period\" has passed,\n     * however the period value itself could be anything, and thus could differ from the one\n     * that the recipient would like to enforce.\n     * @param origin            Domain where message originated\n     * @param nonce             Message nonce on the origin domain\n     * @param sender            Sender address on origin chain\n     * @param proofMaturity     Message's merkle proof age in seconds\n     * @param version           Message version specified by sender\n     * @param content           Raw bytes content of message\n     */\n    function receiveBaseMessage(\n        uint32 origin,\n        uint32 nonce,\n        bytes32 sender,\n        uint256 proofMaturity,\n        uint32 version,\n        bytes memory content\n    ) external payable;\n}\n\n// contracts/interfaces/InterfaceOrigin.sol\n\ninterface InterfaceOrigin {\n    // ═══════════════════════════════════════════════ SEND MESSAGES ═══════════════════════════════════════════════════\n\n    /**\n     * @notice Send a message to the recipient located on destination domain.\n     * @dev Recipient has to conform to IMessageRecipient interface, otherwise message won't be delivered.\n     * Will revert if any of these is true:\n     * - `destination` is equal to contract's local domain\n     * - `content` length is greater than `MAX_CONTENT_BYTES`\n     * - `msg.value` is lower than value of minimum tips for the given message\n     * @param destination           Domain of destination chain\n     * @param recipient             Address of recipient on destination chain as bytes32\n     * @param optimisticPeriod      Optimistic period for message execution on destination chain\n     * @param paddedRequest         Padded encoded message execution request on destination chain\n     * @param content               Raw bytes content of message\n     * @return messageNonce         Nonce of the sent message\n     * @return messageHash          Hash of the sent message\n     */\n    function sendBaseMessage(\n        uint32 destination,\n        bytes32 recipient,\n        uint32 optimisticPeriod,\n        uint256 paddedRequest,\n        bytes memory content\n    ) external payable returns (uint32 messageNonce, bytes32 messageHash);\n\n    /**\n     * @notice Send a manager message to the destination domain.\n     * @dev This could only be called by AgentManager, which takes care of encoding the calldata payload.\n     * Note: (msgOrigin, proofMaturity) security args will be added to payload on the destination chain\n     * so that the AgentManager could verify where the Manager Message came from and how mature is the proof.\n     * Note: function is not payable, as no tips are required for sending a manager message.\n     * Will revert if `destination` is equal to contract's local domain.\n     * @param destination           Domain of destination chain\n     * @param optimisticPeriod      Optimistic period for message execution on destination chain\n     * @param payload               Payload for calling AgentManager on destination chain (with extra security args)\n     */\n    function sendManagerMessage(uint32 destination, uint32 optimisticPeriod, bytes memory payload)\n        external\n        returns (uint32 messageNonce, bytes32 messageHash);\n\n    // ════════════════════════════════════════════════ TIPS LOGIC ═════════════════════════════════════════════════════\n\n    /**\n     * @notice Withdraws locked base message tips to the recipient.\n     * @dev Could only be called by a local AgentManager.\n     * @param recipient     Address to withdraw tips to\n     * @param amount        Tips value to withdraw\n     */\n    function withdrawTips(address recipient, uint256 amount) external;\n\n    // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════\n\n    /**\n     * @notice Returns the minimum tips value for sending a message to a given destination.\n     * @dev Using at least `tipsValue` as `msg.value` for `sendBaseMessage()`\n     * will guarantee that the message will be accepted.\n     * @param destination       Domain of destination chain\n     * @param paddedRequest     Padded encoded message execution request on destination chain\n     * @param contentLength     The length of the message content\n     * @return tipsValue        Minimum tips value for a message to be accepted\n     */\n    function getMinimumTipsValue(uint32 destination, uint256 paddedRequest, uint256 contentLength)\n        external\n        view\n        returns (uint256 tipsValue);\n}\n\n// contracts/libs/Errors.sol\n\n// ══════════════════════════════ INVALID CALLER ═══════════════════════════════\n\nerror CallerNotAgentManager();\nerror CallerNotDestination();\nerror CallerNotInbox();\nerror CallerNotSummit();\n\n// ══════════════════════════════ INCORRECT DATA ═══════════════════════════════\n\nerror IncorrectAttestation();\nerror IncorrectAgentDomain();\nerror IncorrectAgentIndex();\nerror IncorrectAgentProof();\nerror IncorrectAgentRoot();\nerror IncorrectDataHash();\nerror IncorrectDestinationDomain();\nerror IncorrectOriginDomain();\nerror IncorrectSnapshotProof();\nerror IncorrectSnapshotRoot();\nerror IncorrectState();\nerror IncorrectStatesAmount();\nerror IncorrectTipsProof();\nerror IncorrectVersionLength();\n\nerror IncorrectNonce();\nerror IncorrectSender();\nerror IncorrectRecipient();\n\nerror FlagOutOfRange();\nerror IndexOutOfRange();\nerror NonceOutOfRange();\n\nerror OutdatedNonce();\n\nerror UnformattedAttestation();\nerror UnformattedAttestationReport();\nerror UnformattedBaseMessage();\nerror UnformattedCallData();\nerror UnformattedCallDataPrefix();\nerror UnformattedMessage();\nerror UnformattedReceipt();\nerror UnformattedReceiptReport();\nerror UnformattedSignature();\nerror UnformattedSnapshot();\nerror UnformattedState();\nerror UnformattedStateReport();\n\n// ═══════════════════════════════ MERKLE TREES ════════════════════════════════\n\nerror LeafNotProven();\nerror MerkleTreeFull();\nerror NotEnoughLeafs();\nerror TreeHeightTooLow();\n\n// ═════════════════════════════ OPTIMISTIC PERIOD ═════════════════════════════\n\nerror BaseClientOptimisticPeriod();\nerror MessageOptimisticPeriod();\nerror SlashAgentOptimisticPeriod();\nerror WithdrawTipsOptimisticPeriod();\nerror ZeroProofMaturity();\n\n// ═══════════════════════════════ AGENT MANAGER ═══════════════════════════════\n\nerror AgentNotGuard();\nerror AgentNotNotary();\n\nerror AgentCantBeAdded();\nerror AgentNotActive();\nerror AgentNotActiveNorUnstaking();\nerror AgentNotFraudulent();\nerror AgentNotUnstaking();\nerror AgentUnknown();\n\nerror AgentRootNotProposed();\nerror AgentRootTimeoutNotOver();\n\nerror NotStuck();\n\nerror DisputeAlreadyResolved();\nerror DisputeNotOpened();\nerror DisputeTimeoutNotOver();\nerror GuardInDispute();\nerror NotaryInDispute();\n\nerror MustBeSynapseDomain();\nerror SynapseDomainForbidden();\n\n// ════════════════════════════════ DESTINATION ════════════════════════════════\n\nerror AlreadyExecuted();\nerror AlreadyFailed();\nerror DuplicatedSnapshotRoot();\nerror IncorrectMagicValue();\nerror GasLimitTooLow();\nerror GasSuppliedTooLow();\n\n// ══════════════════════════════════ ORIGIN ═══════════════════════════════════\n\nerror ContentLengthTooBig();\nerror EthTransferFailed();\nerror InsufficientEthBalance();\n\n// ════════════════════════════════ GAS ORACLE ═════════════════════════════════\n\nerror LocalGasDataNotSet();\nerror RemoteGasDataNotSet();\n\n// ═══════════════════════════════════ TIPS ════════════════════════════════════\n\nerror SummitTipTooHigh();\nerror TipsClaimMoreThanEarned();\nerror TipsClaimZero();\nerror TipsOverflow();\nerror TipsValueTooLow();\n\n// ════════════════════════════════ MEMORY VIEW ════════════════════════════════\n\nerror IndexedTooMuch();\nerror ViewOverrun();\nerror OccupiedMemory();\nerror UnallocatedMemory();\nerror PrecompileOutOfGas();\n\n// ═════════════════════════════════ MULTICALL ═════════════════════════════════\n\nerror MulticallFailed();\n\n// contracts/libs/TypeCasts.sol\n\nlibrary TypeCasts {\n    // alignment preserving cast\n    function addressToBytes32(address addr) internal pure returns (bytes32) {\n        return bytes32(uint256(uint160(addr)));\n    }\n\n    // alignment preserving cast\n    function bytes32ToAddress(bytes32 buf) internal pure returns (address) {\n        return address(uint160(uint256(buf)));\n    }\n}\n\n// contracts/libs/stack/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// contracts/client/MessageRecipient.sol\n\n// ══════════════════════════════ LIBRARY IMPORTS ══════════════════════════════\n\n// ═════════════════════════════ INTERNAL IMPORTS ══════════════════════════════\n\nabstract contract MessageRecipient is IMessageRecipient {\n    struct MessageRequest {\n        uint96 gasDrop;\n        uint64 gasLimit;\n        uint32 version;\n    }\n\n    /// @notice Local chain Origin: used for sending messages\n    address public immutable origin;\n\n    /// @notice Local chain Destination: used for receiving messages\n    address public immutable destination;\n\n    constructor(address origin_, address destination_) {\n        origin = origin_;\n        destination = destination_;\n    }\n\n    /// @inheritdoc IMessageRecipient\n    function receiveBaseMessage(\n        uint32 origin_,\n        uint32 nonce,\n        bytes32 sender,\n        uint256 proofMaturity,\n        uint32 version,\n        bytes memory content\n    ) external payable {\n        if (msg.sender != destination) revert CallerNotDestination();\n        if (nonce == 0) revert IncorrectNonce();\n        if (sender == 0) revert IncorrectSender();\n        if (proofMaturity == 0) revert ZeroProofMaturity();\n        _receiveBaseMessageUnsafe(origin_, nonce, sender, proofMaturity, version, content);\n    }\n\n    /**\n     * @dev Child contracts should implement the logic for receiving a Base Message in an \"unsafe way\".\n     * Following checks HAVE been performed:\n     *  - receiveBaseMessage() was called by Destination (i.e. this is a legit base message).\n     *  - Nonce is not zero.\n     *  - Message sender on origin chain is not a zero address.\n     *  - Proof maturity is not zero.\n     * Following checks HAVE NOT been performed (thus \"unsafe\"):\n     *  - Message sender on origin chain could be anything non-zero at this point.\n     *  - Proof maturity could be anything non-zero at this point.\n     */\n    function _receiveBaseMessageUnsafe(\n        uint32 origin_,\n        uint32 nonce,\n        bytes32 sender,\n        uint256 proofMaturity,\n        uint32 version,\n        bytes memory content\n    ) internal virtual;\n\n    /**\n     * @dev Sends a message to given destination chain. Full `msg.value` is used to pay for the message tips.\n     * `_getMinimumTipsValue()` could be used to calculate the minimum required tips value, and should be also\n     * exposed as a public view function to estimate the tips value before sending a message off-chain.\n     * This function is not exposed in MessageRecipient, as the message encoding is implemented by the child contract.\n     * @param destination_          Domain of the destination chain\n     * @param recipient             Address of the recipient on destination chain\n     * @param optimisticPeriod      Optimistic period for the message\n     * @param tipsValue             Tips to be paid for sending the message\n     * @param request               Message execution request on destination chain\n     * @param content               The message content\n     */\n    function _sendBaseMessage(\n        uint32 destination_,\n        bytes32 recipient,\n        uint32 optimisticPeriod,\n        uint256 tipsValue,\n        MessageRequest memory request,\n        bytes memory content\n    ) internal returns (uint32 messageNonce, bytes32 messageHash) {\n        if (recipient == 0) revert IncorrectRecipient();\n        return InterfaceOrigin(origin).sendBaseMessage{value: tipsValue}(\n            destination_, recipient, optimisticPeriod, _encodeRequest(request), content\n        );\n    }\n\n    /**\n     * @dev Returns the minimum tips value for sending a message to given destination chain.\n     * @param destination_          Domain of the destination chain\n     * @param request               Message execution request on destination chain\n     * @param contentLength         Length of the message content\n     */\n    function _getMinimumTipsValue(uint32 destination_, MessageRequest memory request, uint256 contentLength)\n        internal\n        view\n        returns (uint256 tipsValue)\n    {\n        return InterfaceOrigin(origin).getMinimumTipsValue(destination_, _encodeRequest(request), contentLength);\n    }\n\n    /**\n     * @dev Encodes a message execution request into format that Origin contract is using.\n     * @param request               Message execution request on destination chain\n     * @return paddedRequest        Encoded request\n     */\n    function _encodeRequest(MessageRequest memory request) internal pure returns (uint256 paddedRequest) {\n        return Request.unwrap(RequestLib.encodeRequest(request.gasDrop, request.gasLimit, request.version));\n    }\n}\n\n// contracts/client/TestClient.sol\n\n// ══════════════════════════════ LIBRARY IMPORTS ══════════════════════════════\n\n// ═════════════════════════════ INTERNAL IMPORTS ══════════════════════════════\n\ncontract TestClient is MessageRecipient {\n    event MessageReceived(\n        uint32 origin, uint32 nonce, bytes32 sender, uint256 proofMaturity, uint32 version, bytes content\n    );\n\n    event MessageSent(uint32 destination, uint32 nonce, bytes32 sender, bytes32 recipient, bytes content);\n\n    // solhint-disable-next-line no-empty-blocks\n    constructor(address origin_, address destination_) MessageRecipient(origin_, destination_) {}\n\n    function sendMessage(\n        uint32 destination_,\n        address recipientAddress,\n        uint32 optimisticPeriod,\n        uint64 gasLimit,\n        uint32 version,\n        bytes memory content\n    ) external payable {\n        bytes32 recipient = TypeCasts.addressToBytes32(recipientAddress);\n        MessageRequest memory request = MessageRequest({gasDrop: 0, gasLimit: gasLimit, version: version});\n        (uint32 nonce,) = _sendBaseMessage({\n            destination_: destination_,\n            recipient: recipient,\n            optimisticPeriod: optimisticPeriod,\n            tipsValue: msg.value,\n            request: request,\n            content: content\n        });\n        emit MessageSent(destination_, nonce, TypeCasts.addressToBytes32(address(this)), recipient, content);\n    }\n\n    /// @inheritdoc MessageRecipient\n    function _receiveBaseMessageUnsafe(\n        uint32 origin_,\n        uint32 nonce,\n        bytes32 sender,\n        uint256 proofMaturity,\n        uint32 version,\n        bytes memory content\n    ) internal override {\n        emit MessageReceived(origin_, nonce, sender, proofMaturity, version, content);\n    }\n}\n","language":"Solidity","languageVersion":"0.8.17","compilerVersion":"0.8.17","compilerOptions":"--combined-json bin,bin-runtime,srcmap,srcmap-runtime,abi,userdoc,devdoc,metadata,hashes --optimize --optimize-runs 10000 --allow-paths ., ./, ../","srcMap":"","srcMapRuntime":"","abiDefinition":[{"inputs":[],"name":"CallerNotDestination","type":"error"},{"inputs":[],"name":"IncorrectNonce","type":"error"},{"inputs":[],"name":"IncorrectSender","type":"error"},{"inputs":[],"name":"ZeroProofMaturity","type":"error"},{"inputs":[],"name":"destination","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"origin","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint32","name":"origin_","type":"uint32"},{"internalType":"uint32","name":"nonce","type":"uint32"},{"internalType":"bytes32","name":"sender","type":"bytes32"},{"internalType":"uint256","name":"proofMaturity","type":"uint256"},{"internalType":"uint32","name":"version","type":"uint32"},{"internalType":"bytes","name":"content","type":"bytes"}],"name":"receiveBaseMessage","outputs":[],"stateMutability":"payable","type":"function"}],"userDoc":{"kind":"user","methods":{"destination()":{"notice":"Local chain Destination: used for receiving messages"},"origin()":{"notice":"Local chain Origin: used for sending messages"},"receiveBaseMessage(uint32,uint32,bytes32,uint256,uint32,bytes)":{"notice":"Message recipient needs to implement this function in order to receive cross-chain messages."}},"version":1},"developerDoc":{"kind":"dev","methods":{"receiveBaseMessage(uint32,uint32,bytes32,uint256,uint32,bytes)":{"details":"Message recipient needs to ensure that merkle proof for the message is at least as old as the optimistic period that the recipient is using. Note: as this point it is checked that the \"message optimistic period\" has passed, however the period value itself could be anything, and thus could differ from the one that the recipient would like to enforce.","params":{"content":"Raw bytes content of message","nonce":"Message nonce on the origin domain","origin":"Domain where message originated","proofMaturity":"Message's merkle proof age in seconds","sender":"Sender address on origin chain","version":"Message version specified by sender"}}},"version":1},"metadata":"{\"compiler\":{\"version\":\"0.8.17+commit.8df45f5f\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[],\"name\":\"CallerNotDestination\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"IncorrectNonce\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"IncorrectSender\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ZeroProofMaturity\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"destination\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"origin\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint32\",\"name\":\"origin_\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"nonce\",\"type\":\"uint32\"},{\"internalType\":\"bytes32\",\"name\":\"sender\",\"type\":\"bytes32\"},{\"internalType\":\"uint256\",\"name\":\"proofMaturity\",\"type\":\"uint256\"},{\"internalType\":\"uint32\",\"name\":\"version\",\"type\":\"uint32\"},{\"internalType\":\"bytes\",\"name\":\"content\",\"type\":\"bytes\"}],\"name\":\"receiveBaseMessage\",\"outputs\":[],\"stateMutability\":\"payable\",\"type\":\"function\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{\"receiveBaseMessage(uint32,uint32,bytes32,uint256,uint32,bytes)\":{\"details\":\"Message recipient needs to ensure that merkle proof for the message is at least as old as the optimistic period that the recipient is using. Note: as this point it is checked that the \\\"message optimistic period\\\" has passed, however the period value itself could be anything, and thus could differ from the one that the recipient would like to enforce.\",\"params\":{\"content\":\"Raw bytes content of message\",\"nonce\":\"Message nonce on the origin domain\",\"origin\":\"Domain where message originated\",\"proofMaturity\":\"Message's merkle proof age in seconds\",\"sender\":\"Sender address on origin chain\",\"version\":\"Message version specified by sender\"}}},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{\"destination()\":{\"notice\":\"Local chain Destination: used for receiving messages\"},\"origin()\":{\"notice\":\"Local chain Origin: used for sending messages\"},\"receiveBaseMessage(uint32,uint32,bytes32,uint256,uint32,bytes)\":{\"notice\":\"Message recipient needs to implement this function in order to receive cross-chain messages.\"}},\"version\":1}},\"settings\":{\"compilationTarget\":{\"solidity/TestClient.sol\":\"MessageRecipient\"},\"evmVersion\":\"london\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\"},\"optimizer\":{\"enabled\":true,\"runs\":10000},\"remappings\":[]},\"sources\":{\"solidity/TestClient.sol\":{\"keccak256\":\"0x0559f7adcbbadc7e14f6d1a8909db6085e58daebca746390c188879460d4fb90\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://dfac7d1d9b1255e057dc37b120623dd3edb15a776ce793b81955ab51c6f59ba1\",\"dweb:/ipfs/Qmd7j2CjYA91DTqJMMmnTt4Y9wvDdhVH7Bgt4MFBPdY3rS\"]}},\"version\":1}"},"hashes":{"destination()":"b269681d","origin()":"938b5f32","receiveBaseMessage(uint32,uint32,bytes32,uint256,uint32,bytes)":"032f287e"}},"solidity/TestClient.sol:RequestLib":{"code":"0x60566037600b82828239805160001a607314602a57634e487b7160e01b600052600060045260246000fd5b30600052607381538281f3fe73000000000000000000000000000000000000000030146080604052600080fdfea2646970667358221220c60c8cd9ab756bce728a88c2f3934c224ceb8abce19e55989b63516a2d4e9f1964736f6c63430008110033","runtime-code":"0x73000000000000000000000000000000000000000030146080604052600080fdfea2646970667358221220c60c8cd9ab756bce728a88c2f3934c224ceb8abce19e55989b63516a2d4e9f1964736f6c63430008110033","info":{"source":"// SPDX-License-Identifier: MIT\npragma solidity =0.8.17;\n\n// contracts/interfaces/IMessageRecipient.sol\n\ninterface IMessageRecipient {\n    /**\n     * @notice Message recipient needs to implement this function in order to\n     * receive cross-chain messages.\n     * @dev Message recipient needs to ensure that merkle proof for the message\n     * is at least as old as the optimistic period that the recipient is using.\n     * Note: as this point it is checked that the \"message optimistic period\" has passed,\n     * however the period value itself could be anything, and thus could differ from the one\n     * that the recipient would like to enforce.\n     * @param origin            Domain where message originated\n     * @param nonce             Message nonce on the origin domain\n     * @param sender            Sender address on origin chain\n     * @param proofMaturity     Message's merkle proof age in seconds\n     * @param version           Message version specified by sender\n     * @param content           Raw bytes content of message\n     */\n    function receiveBaseMessage(\n        uint32 origin,\n        uint32 nonce,\n        bytes32 sender,\n        uint256 proofMaturity,\n        uint32 version,\n        bytes memory content\n    ) external payable;\n}\n\n// contracts/interfaces/InterfaceOrigin.sol\n\ninterface InterfaceOrigin {\n    // ═══════════════════════════════════════════════ SEND MESSAGES ═══════════════════════════════════════════════════\n\n    /**\n     * @notice Send a message to the recipient located on destination domain.\n     * @dev Recipient has to conform to IMessageRecipient interface, otherwise message won't be delivered.\n     * Will revert if any of these is true:\n     * - `destination` is equal to contract's local domain\n     * - `content` length is greater than `MAX_CONTENT_BYTES`\n     * - `msg.value` is lower than value of minimum tips for the given message\n     * @param destination           Domain of destination chain\n     * @param recipient             Address of recipient on destination chain as bytes32\n     * @param optimisticPeriod      Optimistic period for message execution on destination chain\n     * @param paddedRequest         Padded encoded message execution request on destination chain\n     * @param content               Raw bytes content of message\n     * @return messageNonce         Nonce of the sent message\n     * @return messageHash          Hash of the sent message\n     */\n    function sendBaseMessage(\n        uint32 destination,\n        bytes32 recipient,\n        uint32 optimisticPeriod,\n        uint256 paddedRequest,\n        bytes memory content\n    ) external payable returns (uint32 messageNonce, bytes32 messageHash);\n\n    /**\n     * @notice Send a manager message to the destination domain.\n     * @dev This could only be called by AgentManager, which takes care of encoding the calldata payload.\n     * Note: (msgOrigin, proofMaturity) security args will be added to payload on the destination chain\n     * so that the AgentManager could verify where the Manager Message came from and how mature is the proof.\n     * Note: function is not payable, as no tips are required for sending a manager message.\n     * Will revert if `destination` is equal to contract's local domain.\n     * @param destination           Domain of destination chain\n     * @param optimisticPeriod      Optimistic period for message execution on destination chain\n     * @param payload               Payload for calling AgentManager on destination chain (with extra security args)\n     */\n    function sendManagerMessage(uint32 destination, uint32 optimisticPeriod, bytes memory payload)\n        external\n        returns (uint32 messageNonce, bytes32 messageHash);\n\n    // ════════════════════════════════════════════════ TIPS LOGIC ═════════════════════════════════════════════════════\n\n    /**\n     * @notice Withdraws locked base message tips to the recipient.\n     * @dev Could only be called by a local AgentManager.\n     * @param recipient     Address to withdraw tips to\n     * @param amount        Tips value to withdraw\n     */\n    function withdrawTips(address recipient, uint256 amount) external;\n\n    // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════\n\n    /**\n     * @notice Returns the minimum tips value for sending a message to a given destination.\n     * @dev Using at least `tipsValue` as `msg.value` for `sendBaseMessage()`\n     * will guarantee that the message will be accepted.\n     * @param destination       Domain of destination chain\n     * @param paddedRequest     Padded encoded message execution request on destination chain\n     * @param contentLength     The length of the message content\n     * @return tipsValue        Minimum tips value for a message to be accepted\n     */\n    function getMinimumTipsValue(uint32 destination, uint256 paddedRequest, uint256 contentLength)\n        external\n        view\n        returns (uint256 tipsValue);\n}\n\n// contracts/libs/Errors.sol\n\n// ══════════════════════════════ INVALID CALLER ═══════════════════════════════\n\nerror CallerNotAgentManager();\nerror CallerNotDestination();\nerror CallerNotInbox();\nerror CallerNotSummit();\n\n// ══════════════════════════════ INCORRECT DATA ═══════════════════════════════\n\nerror IncorrectAttestation();\nerror IncorrectAgentDomain();\nerror IncorrectAgentIndex();\nerror IncorrectAgentProof();\nerror IncorrectAgentRoot();\nerror IncorrectDataHash();\nerror IncorrectDestinationDomain();\nerror IncorrectOriginDomain();\nerror IncorrectSnapshotProof();\nerror IncorrectSnapshotRoot();\nerror IncorrectState();\nerror IncorrectStatesAmount();\nerror IncorrectTipsProof();\nerror IncorrectVersionLength();\n\nerror IncorrectNonce();\nerror IncorrectSender();\nerror IncorrectRecipient();\n\nerror FlagOutOfRange();\nerror IndexOutOfRange();\nerror NonceOutOfRange();\n\nerror OutdatedNonce();\n\nerror UnformattedAttestation();\nerror UnformattedAttestationReport();\nerror UnformattedBaseMessage();\nerror UnformattedCallData();\nerror UnformattedCallDataPrefix();\nerror UnformattedMessage();\nerror UnformattedReceipt();\nerror UnformattedReceiptReport();\nerror UnformattedSignature();\nerror UnformattedSnapshot();\nerror UnformattedState();\nerror UnformattedStateReport();\n\n// ═══════════════════════════════ MERKLE TREES ════════════════════════════════\n\nerror LeafNotProven();\nerror MerkleTreeFull();\nerror NotEnoughLeafs();\nerror TreeHeightTooLow();\n\n// ═════════════════════════════ OPTIMISTIC PERIOD ═════════════════════════════\n\nerror BaseClientOptimisticPeriod();\nerror MessageOptimisticPeriod();\nerror SlashAgentOptimisticPeriod();\nerror WithdrawTipsOptimisticPeriod();\nerror ZeroProofMaturity();\n\n// ═══════════════════════════════ AGENT MANAGER ═══════════════════════════════\n\nerror AgentNotGuard();\nerror AgentNotNotary();\n\nerror AgentCantBeAdded();\nerror AgentNotActive();\nerror AgentNotActiveNorUnstaking();\nerror AgentNotFraudulent();\nerror AgentNotUnstaking();\nerror AgentUnknown();\n\nerror AgentRootNotProposed();\nerror AgentRootTimeoutNotOver();\n\nerror NotStuck();\n\nerror DisputeAlreadyResolved();\nerror DisputeNotOpened();\nerror DisputeTimeoutNotOver();\nerror GuardInDispute();\nerror NotaryInDispute();\n\nerror MustBeSynapseDomain();\nerror SynapseDomainForbidden();\n\n// ════════════════════════════════ DESTINATION ════════════════════════════════\n\nerror AlreadyExecuted();\nerror AlreadyFailed();\nerror DuplicatedSnapshotRoot();\nerror IncorrectMagicValue();\nerror GasLimitTooLow();\nerror GasSuppliedTooLow();\n\n// ══════════════════════════════════ ORIGIN ═══════════════════════════════════\n\nerror ContentLengthTooBig();\nerror EthTransferFailed();\nerror InsufficientEthBalance();\n\n// ════════════════════════════════ GAS ORACLE ═════════════════════════════════\n\nerror LocalGasDataNotSet();\nerror RemoteGasDataNotSet();\n\n// ═══════════════════════════════════ TIPS ════════════════════════════════════\n\nerror SummitTipTooHigh();\nerror TipsClaimMoreThanEarned();\nerror TipsClaimZero();\nerror TipsOverflow();\nerror TipsValueTooLow();\n\n// ════════════════════════════════ MEMORY VIEW ════════════════════════════════\n\nerror IndexedTooMuch();\nerror ViewOverrun();\nerror OccupiedMemory();\nerror UnallocatedMemory();\nerror PrecompileOutOfGas();\n\n// ═════════════════════════════════ MULTICALL ═════════════════════════════════\n\nerror MulticallFailed();\n\n// contracts/libs/TypeCasts.sol\n\nlibrary TypeCasts {\n    // alignment preserving cast\n    function addressToBytes32(address addr) internal pure returns (bytes32) {\n        return bytes32(uint256(uint160(addr)));\n    }\n\n    // alignment preserving cast\n    function bytes32ToAddress(bytes32 buf) internal pure returns (address) {\n        return address(uint160(uint256(buf)));\n    }\n}\n\n// contracts/libs/stack/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// contracts/client/MessageRecipient.sol\n\n// ══════════════════════════════ LIBRARY IMPORTS ══════════════════════════════\n\n// ═════════════════════════════ INTERNAL IMPORTS ══════════════════════════════\n\nabstract contract MessageRecipient is IMessageRecipient {\n    struct MessageRequest {\n        uint96 gasDrop;\n        uint64 gasLimit;\n        uint32 version;\n    }\n\n    /// @notice Local chain Origin: used for sending messages\n    address public immutable origin;\n\n    /// @notice Local chain Destination: used for receiving messages\n    address public immutable destination;\n\n    constructor(address origin_, address destination_) {\n        origin = origin_;\n        destination = destination_;\n    }\n\n    /// @inheritdoc IMessageRecipient\n    function receiveBaseMessage(\n        uint32 origin_,\n        uint32 nonce,\n        bytes32 sender,\n        uint256 proofMaturity,\n        uint32 version,\n        bytes memory content\n    ) external payable {\n        if (msg.sender != destination) revert CallerNotDestination();\n        if (nonce == 0) revert IncorrectNonce();\n        if (sender == 0) revert IncorrectSender();\n        if (proofMaturity == 0) revert ZeroProofMaturity();\n        _receiveBaseMessageUnsafe(origin_, nonce, sender, proofMaturity, version, content);\n    }\n\n    /**\n     * @dev Child contracts should implement the logic for receiving a Base Message in an \"unsafe way\".\n     * Following checks HAVE been performed:\n     *  - receiveBaseMessage() was called by Destination (i.e. this is a legit base message).\n     *  - Nonce is not zero.\n     *  - Message sender on origin chain is not a zero address.\n     *  - Proof maturity is not zero.\n     * Following checks HAVE NOT been performed (thus \"unsafe\"):\n     *  - Message sender on origin chain could be anything non-zero at this point.\n     *  - Proof maturity could be anything non-zero at this point.\n     */\n    function _receiveBaseMessageUnsafe(\n        uint32 origin_,\n        uint32 nonce,\n        bytes32 sender,\n        uint256 proofMaturity,\n        uint32 version,\n        bytes memory content\n    ) internal virtual;\n\n    /**\n     * @dev Sends a message to given destination chain. Full `msg.value` is used to pay for the message tips.\n     * `_getMinimumTipsValue()` could be used to calculate the minimum required tips value, and should be also\n     * exposed as a public view function to estimate the tips value before sending a message off-chain.\n     * This function is not exposed in MessageRecipient, as the message encoding is implemented by the child contract.\n     * @param destination_          Domain of the destination chain\n     * @param recipient             Address of the recipient on destination chain\n     * @param optimisticPeriod      Optimistic period for the message\n     * @param tipsValue             Tips to be paid for sending the message\n     * @param request               Message execution request on destination chain\n     * @param content               The message content\n     */\n    function _sendBaseMessage(\n        uint32 destination_,\n        bytes32 recipient,\n        uint32 optimisticPeriod,\n        uint256 tipsValue,\n        MessageRequest memory request,\n        bytes memory content\n    ) internal returns (uint32 messageNonce, bytes32 messageHash) {\n        if (recipient == 0) revert IncorrectRecipient();\n        return InterfaceOrigin(origin).sendBaseMessage{value: tipsValue}(\n            destination_, recipient, optimisticPeriod, _encodeRequest(request), content\n        );\n    }\n\n    /**\n     * @dev Returns the minimum tips value for sending a message to given destination chain.\n     * @param destination_          Domain of the destination chain\n     * @param request               Message execution request on destination chain\n     * @param contentLength         Length of the message content\n     */\n    function _getMinimumTipsValue(uint32 destination_, MessageRequest memory request, uint256 contentLength)\n        internal\n        view\n        returns (uint256 tipsValue)\n    {\n        return InterfaceOrigin(origin).getMinimumTipsValue(destination_, _encodeRequest(request), contentLength);\n    }\n\n    /**\n     * @dev Encodes a message execution request into format that Origin contract is using.\n     * @param request               Message execution request on destination chain\n     * @return paddedRequest        Encoded request\n     */\n    function _encodeRequest(MessageRequest memory request) internal pure returns (uint256 paddedRequest) {\n        return Request.unwrap(RequestLib.encodeRequest(request.gasDrop, request.gasLimit, request.version));\n    }\n}\n\n// contracts/client/TestClient.sol\n\n// ══════════════════════════════ LIBRARY IMPORTS ══════════════════════════════\n\n// ═════════════════════════════ INTERNAL IMPORTS ══════════════════════════════\n\ncontract TestClient is MessageRecipient {\n    event MessageReceived(\n        uint32 origin, uint32 nonce, bytes32 sender, uint256 proofMaturity, uint32 version, bytes content\n    );\n\n    event MessageSent(uint32 destination, uint32 nonce, bytes32 sender, bytes32 recipient, bytes content);\n\n    // solhint-disable-next-line no-empty-blocks\n    constructor(address origin_, address destination_) MessageRecipient(origin_, destination_) {}\n\n    function sendMessage(\n        uint32 destination_,\n        address recipientAddress,\n        uint32 optimisticPeriod,\n        uint64 gasLimit,\n        uint32 version,\n        bytes memory content\n    ) external payable {\n        bytes32 recipient = TypeCasts.addressToBytes32(recipientAddress);\n        MessageRequest memory request = MessageRequest({gasDrop: 0, gasLimit: gasLimit, version: version});\n        (uint32 nonce,) = _sendBaseMessage({\n            destination_: destination_,\n            recipient: recipient,\n            optimisticPeriod: optimisticPeriod,\n            tipsValue: msg.value,\n            request: request,\n            content: content\n        });\n        emit MessageSent(destination_, nonce, TypeCasts.addressToBytes32(address(this)), recipient, content);\n    }\n\n    /// @inheritdoc MessageRecipient\n    function _receiveBaseMessageUnsafe(\n        uint32 origin_,\n        uint32 nonce,\n        bytes32 sender,\n        uint256 proofMaturity,\n        uint32 version,\n        bytes memory content\n    ) internal override {\n        emit MessageReceived(origin_, nonce, sender, proofMaturity, version, content);\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":"11875:2478:0:-:0;;;;;;;;;;;;;;;-1:-1:-1;;;11875:2478:0;;;;;;;;;;;;;;;;;","srcMapRuntime":"11875: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/TestClient.sol\":\"RequestLib\"},\"evmVersion\":\"london\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\"},\"optimizer\":{\"enabled\":true,\"runs\":10000},\"remappings\":[]},\"sources\":{\"solidity/TestClient.sol\":{\"keccak256\":\"0x0559f7adcbbadc7e14f6d1a8909db6085e58daebca746390c188879460d4fb90\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://dfac7d1d9b1255e057dc37b120623dd3edb15a776ce793b81955ab51c6f59ba1\",\"dweb:/ipfs/Qmd7j2CjYA91DTqJMMmnTt4Y9wvDdhVH7Bgt4MFBPdY3rS\"]}},\"version\":1}"},"hashes":{}},"solidity/TestClient.sol:TestClient":{"code":"0x60c060405234801561001057600080fd5b506040516108ff3803806108ff83398101604081905261002f91610062565b6001600160a01b039182166080521660a052610095565b80516001600160a01b038116811461005d57600080fd5b919050565b6000806040838503121561007557600080fd5b61007e83610046565b915061008c60208401610046565b90509250929050565b60805160a0516108396100c66000396000818160db0152610115015260008181607e015261035e01526108396000f3fe60806040526004361061003f5760003560e01c8063032f287e146100445780636d82c66514610059578063938b5f321461006c578063b269681d146100c9575b600080fd5b61005761005236600461057c565b6100fd565b005b610057610067366004610603565b610237565b34801561007857600080fd5b506100a07f000000000000000000000000000000000000000000000000000000000000000081565b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200160405180910390f35b3480156100d557600080fd5b506100a07f000000000000000000000000000000000000000000000000000000000000000081565b3373ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000161461016c576040517f6efcc49f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8463ffffffff166000036101ac576040517f674d8d8800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008490036101e7576040517f7d1c29f300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b82600003610221576040517fdce28ace00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61022f8686868686866102d7565b505050505050565b60408051606081018252600080825267ffffffffffffffff8616602083015263ffffffff85169282019290925273ffffffffffffffffffffffffffffffffffffffff87169161028a898489348689610320565b5090507ff17c656698e3361e14b0a2402b83112a3d8ffcc011ce6bae5e8368685d14327689823086886040516102c4959493929190610717565b60405180910390a1505050505050505050565b7f3f9b1e40d9a4eda9d0f907e5149157e0ba489ee09f73d9c99a533462f3232ee386868686868660405161031096959493929190610757565b60405180910390a1505050505050565b60008086810361035c576040517f519bdea700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1663873661bd868a8a8a6103a58a610417565b896040518763ffffffff1660e01b81526004016103c69594939291906107a0565b604080518083038185885af11580156103e3573d6000803e3d6000fd5b50505050506040513d601f19601f8201168201806040525081019061040891906107d5565b91509150965096945050505050565b600061046d82600001518360200151846040015177ffffffffffffffffffffffff000000000000000000000000606084901b166bffffffffffffffff00000000602084901b161763ffffffff8216179392505050565b77ffffffffffffffffffffffffffffffffffffffffffffffff1692915050565b63ffffffff8116811461049f57600080fd5b50565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b600082601f8301126104e257600080fd5b813567ffffffffffffffff808211156104fd576104fd6104a2565b604051601f83017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f01168101908282118183101715610543576105436104a2565b8160405283815286602085880101111561055c57600080fd5b836020870160208301376000602085830101528094505050505092915050565b60008060008060008060c0878903121561059557600080fd5b86356105a08161048d565b955060208701356105b08161048d565b9450604087013593506060870135925060808701356105ce8161048d565b915060a087013567ffffffffffffffff8111156105ea57600080fd5b6105f689828a016104d1565b9150509295509295509295565b60008060008060008060c0878903121561061c57600080fd5b86356106278161048d565b9550602087013573ffffffffffffffffffffffffffffffffffffffff8116811461065057600080fd5b945060408701356106608161048d565b9350606087013567ffffffffffffffff808216821461067e57600080fd5b9093506080880135906106908261048d565b90925060a088013590808211156106a657600080fd5b506105f689828a016104d1565b6000815180845260005b818110156106d9576020818501810151868301820152016106bd565b5060006020828601015260207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f83011685010191505092915050565b600063ffffffff808816835280871660208401525084604083015283606083015260a0608083015261074c60a08301846106b3565b979650505050505050565b600063ffffffff8089168352808816602084015286604084015285606084015280851660808401525060c060a083015261079460c08301846106b3565b98975050505050505050565b600063ffffffff808816835286602084015280861660408401525083606083015260a0608083015261074c60a08301846106b3565b600080604083850312156107e857600080fd5b82516107f38161048d565b602093909301519294929350505056fea26469706673582212202fcc1eedc27cc33c3ce313c53b6a387067a611455562feedacdad08ed0dce6d864736f6c63430008110033","runtime-code":"0x60806040526004361061003f5760003560e01c8063032f287e146100445780636d82c66514610059578063938b5f321461006c578063b269681d146100c9575b600080fd5b61005761005236600461057c565b6100fd565b005b610057610067366004610603565b610237565b34801561007857600080fd5b506100a07f000000000000000000000000000000000000000000000000000000000000000081565b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200160405180910390f35b3480156100d557600080fd5b506100a07f000000000000000000000000000000000000000000000000000000000000000081565b3373ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000161461016c576040517f6efcc49f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8463ffffffff166000036101ac576040517f674d8d8800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008490036101e7576040517f7d1c29f300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b82600003610221576040517fdce28ace00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61022f8686868686866102d7565b505050505050565b60408051606081018252600080825267ffffffffffffffff8616602083015263ffffffff85169282019290925273ffffffffffffffffffffffffffffffffffffffff87169161028a898489348689610320565b5090507ff17c656698e3361e14b0a2402b83112a3d8ffcc011ce6bae5e8368685d14327689823086886040516102c4959493929190610717565b60405180910390a1505050505050505050565b7f3f9b1e40d9a4eda9d0f907e5149157e0ba489ee09f73d9c99a533462f3232ee386868686868660405161031096959493929190610757565b60405180910390a1505050505050565b60008086810361035c576040517f519bdea700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1663873661bd868a8a8a6103a58a610417565b896040518763ffffffff1660e01b81526004016103c69594939291906107a0565b604080518083038185885af11580156103e3573d6000803e3d6000fd5b50505050506040513d601f19601f8201168201806040525081019061040891906107d5565b91509150965096945050505050565b600061046d82600001518360200151846040015177ffffffffffffffffffffffff000000000000000000000000606084901b166bffffffffffffffff00000000602084901b161763ffffffff8216179392505050565b77ffffffffffffffffffffffffffffffffffffffffffffffff1692915050565b63ffffffff8116811461049f57600080fd5b50565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b600082601f8301126104e257600080fd5b813567ffffffffffffffff808211156104fd576104fd6104a2565b604051601f83017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f01168101908282118183101715610543576105436104a2565b8160405283815286602085880101111561055c57600080fd5b836020870160208301376000602085830101528094505050505092915050565b60008060008060008060c0878903121561059557600080fd5b86356105a08161048d565b955060208701356105b08161048d565b9450604087013593506060870135925060808701356105ce8161048d565b915060a087013567ffffffffffffffff8111156105ea57600080fd5b6105f689828a016104d1565b9150509295509295509295565b60008060008060008060c0878903121561061c57600080fd5b86356106278161048d565b9550602087013573ffffffffffffffffffffffffffffffffffffffff8116811461065057600080fd5b945060408701356106608161048d565b9350606087013567ffffffffffffffff808216821461067e57600080fd5b9093506080880135906106908261048d565b90925060a088013590808211156106a657600080fd5b506105f689828a016104d1565b6000815180845260005b818110156106d9576020818501810151868301820152016106bd565b5060006020828601015260207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f83011685010191505092915050565b600063ffffffff808816835280871660208401525084604083015283606083015260a0608083015261074c60a08301846106b3565b979650505050505050565b600063ffffffff8089168352808816602084015286604084015285606084015280851660808401525060c060a083015261079460c08301846106b3565b98975050505050505050565b600063ffffffff808816835286602084015280861660408401525083606083015260a0608083015261074c60a08301846106b3565b600080604083850312156107e857600080fd5b82516107f38161048d565b602093909301519294929350505056fea26469706673582212202fcc1eedc27cc33c3ce313c53b6a387067a611455562feedacdad08ed0dce6d864736f6c63430008110033","info":{"source":"// SPDX-License-Identifier: MIT\npragma solidity =0.8.17;\n\n// contracts/interfaces/IMessageRecipient.sol\n\ninterface IMessageRecipient {\n    /**\n     * @notice Message recipient needs to implement this function in order to\n     * receive cross-chain messages.\n     * @dev Message recipient needs to ensure that merkle proof for the message\n     * is at least as old as the optimistic period that the recipient is using.\n     * Note: as this point it is checked that the \"message optimistic period\" has passed,\n     * however the period value itself could be anything, and thus could differ from the one\n     * that the recipient would like to enforce.\n     * @param origin            Domain where message originated\n     * @param nonce             Message nonce on the origin domain\n     * @param sender            Sender address on origin chain\n     * @param proofMaturity     Message's merkle proof age in seconds\n     * @param version           Message version specified by sender\n     * @param content           Raw bytes content of message\n     */\n    function receiveBaseMessage(\n        uint32 origin,\n        uint32 nonce,\n        bytes32 sender,\n        uint256 proofMaturity,\n        uint32 version,\n        bytes memory content\n    ) external payable;\n}\n\n// contracts/interfaces/InterfaceOrigin.sol\n\ninterface InterfaceOrigin {\n    // ═══════════════════════════════════════════════ SEND MESSAGES ═══════════════════════════════════════════════════\n\n    /**\n     * @notice Send a message to the recipient located on destination domain.\n     * @dev Recipient has to conform to IMessageRecipient interface, otherwise message won't be delivered.\n     * Will revert if any of these is true:\n     * - `destination` is equal to contract's local domain\n     * - `content` length is greater than `MAX_CONTENT_BYTES`\n     * - `msg.value` is lower than value of minimum tips for the given message\n     * @param destination           Domain of destination chain\n     * @param recipient             Address of recipient on destination chain as bytes32\n     * @param optimisticPeriod      Optimistic period for message execution on destination chain\n     * @param paddedRequest         Padded encoded message execution request on destination chain\n     * @param content               Raw bytes content of message\n     * @return messageNonce         Nonce of the sent message\n     * @return messageHash          Hash of the sent message\n     */\n    function sendBaseMessage(\n        uint32 destination,\n        bytes32 recipient,\n        uint32 optimisticPeriod,\n        uint256 paddedRequest,\n        bytes memory content\n    ) external payable returns (uint32 messageNonce, bytes32 messageHash);\n\n    /**\n     * @notice Send a manager message to the destination domain.\n     * @dev This could only be called by AgentManager, which takes care of encoding the calldata payload.\n     * Note: (msgOrigin, proofMaturity) security args will be added to payload on the destination chain\n     * so that the AgentManager could verify where the Manager Message came from and how mature is the proof.\n     * Note: function is not payable, as no tips are required for sending a manager message.\n     * Will revert if `destination` is equal to contract's local domain.\n     * @param destination           Domain of destination chain\n     * @param optimisticPeriod      Optimistic period for message execution on destination chain\n     * @param payload               Payload for calling AgentManager on destination chain (with extra security args)\n     */\n    function sendManagerMessage(uint32 destination, uint32 optimisticPeriod, bytes memory payload)\n        external\n        returns (uint32 messageNonce, bytes32 messageHash);\n\n    // ════════════════════════════════════════════════ TIPS LOGIC ═════════════════════════════════════════════════════\n\n    /**\n     * @notice Withdraws locked base message tips to the recipient.\n     * @dev Could only be called by a local AgentManager.\n     * @param recipient     Address to withdraw tips to\n     * @param amount        Tips value to withdraw\n     */\n    function withdrawTips(address recipient, uint256 amount) external;\n\n    // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════\n\n    /**\n     * @notice Returns the minimum tips value for sending a message to a given destination.\n     * @dev Using at least `tipsValue` as `msg.value` for `sendBaseMessage()`\n     * will guarantee that the message will be accepted.\n     * @param destination       Domain of destination chain\n     * @param paddedRequest     Padded encoded message execution request on destination chain\n     * @param contentLength     The length of the message content\n     * @return tipsValue        Minimum tips value for a message to be accepted\n     */\n    function getMinimumTipsValue(uint32 destination, uint256 paddedRequest, uint256 contentLength)\n        external\n        view\n        returns (uint256 tipsValue);\n}\n\n// contracts/libs/Errors.sol\n\n// ══════════════════════════════ INVALID CALLER ═══════════════════════════════\n\nerror CallerNotAgentManager();\nerror CallerNotDestination();\nerror CallerNotInbox();\nerror CallerNotSummit();\n\n// ══════════════════════════════ INCORRECT DATA ═══════════════════════════════\n\nerror IncorrectAttestation();\nerror IncorrectAgentDomain();\nerror IncorrectAgentIndex();\nerror IncorrectAgentProof();\nerror IncorrectAgentRoot();\nerror IncorrectDataHash();\nerror IncorrectDestinationDomain();\nerror IncorrectOriginDomain();\nerror IncorrectSnapshotProof();\nerror IncorrectSnapshotRoot();\nerror IncorrectState();\nerror IncorrectStatesAmount();\nerror IncorrectTipsProof();\nerror IncorrectVersionLength();\n\nerror IncorrectNonce();\nerror IncorrectSender();\nerror IncorrectRecipient();\n\nerror FlagOutOfRange();\nerror IndexOutOfRange();\nerror NonceOutOfRange();\n\nerror OutdatedNonce();\n\nerror UnformattedAttestation();\nerror UnformattedAttestationReport();\nerror UnformattedBaseMessage();\nerror UnformattedCallData();\nerror UnformattedCallDataPrefix();\nerror UnformattedMessage();\nerror UnformattedReceipt();\nerror UnformattedReceiptReport();\nerror UnformattedSignature();\nerror UnformattedSnapshot();\nerror UnformattedState();\nerror UnformattedStateReport();\n\n// ═══════════════════════════════ MERKLE TREES ════════════════════════════════\n\nerror LeafNotProven();\nerror MerkleTreeFull();\nerror NotEnoughLeafs();\nerror TreeHeightTooLow();\n\n// ═════════════════════════════ OPTIMISTIC PERIOD ═════════════════════════════\n\nerror BaseClientOptimisticPeriod();\nerror MessageOptimisticPeriod();\nerror SlashAgentOptimisticPeriod();\nerror WithdrawTipsOptimisticPeriod();\nerror ZeroProofMaturity();\n\n// ═══════════════════════════════ AGENT MANAGER ═══════════════════════════════\n\nerror AgentNotGuard();\nerror AgentNotNotary();\n\nerror AgentCantBeAdded();\nerror AgentNotActive();\nerror AgentNotActiveNorUnstaking();\nerror AgentNotFraudulent();\nerror AgentNotUnstaking();\nerror AgentUnknown();\n\nerror AgentRootNotProposed();\nerror AgentRootTimeoutNotOver();\n\nerror NotStuck();\n\nerror DisputeAlreadyResolved();\nerror DisputeNotOpened();\nerror DisputeTimeoutNotOver();\nerror GuardInDispute();\nerror NotaryInDispute();\n\nerror MustBeSynapseDomain();\nerror SynapseDomainForbidden();\n\n// ════════════════════════════════ DESTINATION ════════════════════════════════\n\nerror AlreadyExecuted();\nerror AlreadyFailed();\nerror DuplicatedSnapshotRoot();\nerror IncorrectMagicValue();\nerror GasLimitTooLow();\nerror GasSuppliedTooLow();\n\n// ══════════════════════════════════ ORIGIN ═══════════════════════════════════\n\nerror ContentLengthTooBig();\nerror EthTransferFailed();\nerror InsufficientEthBalance();\n\n// ════════════════════════════════ GAS ORACLE ═════════════════════════════════\n\nerror LocalGasDataNotSet();\nerror RemoteGasDataNotSet();\n\n// ═══════════════════════════════════ TIPS ════════════════════════════════════\n\nerror SummitTipTooHigh();\nerror TipsClaimMoreThanEarned();\nerror TipsClaimZero();\nerror TipsOverflow();\nerror TipsValueTooLow();\n\n// ════════════════════════════════ MEMORY VIEW ════════════════════════════════\n\nerror IndexedTooMuch();\nerror ViewOverrun();\nerror OccupiedMemory();\nerror UnallocatedMemory();\nerror PrecompileOutOfGas();\n\n// ═════════════════════════════════ MULTICALL ═════════════════════════════════\n\nerror MulticallFailed();\n\n// contracts/libs/TypeCasts.sol\n\nlibrary TypeCasts {\n    // alignment preserving cast\n    function addressToBytes32(address addr) internal pure returns (bytes32) {\n        return bytes32(uint256(uint160(addr)));\n    }\n\n    // alignment preserving cast\n    function bytes32ToAddress(bytes32 buf) internal pure returns (address) {\n        return address(uint160(uint256(buf)));\n    }\n}\n\n// contracts/libs/stack/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// contracts/client/MessageRecipient.sol\n\n// ══════════════════════════════ LIBRARY IMPORTS ══════════════════════════════\n\n// ═════════════════════════════ INTERNAL IMPORTS ══════════════════════════════\n\nabstract contract MessageRecipient is IMessageRecipient {\n    struct MessageRequest {\n        uint96 gasDrop;\n        uint64 gasLimit;\n        uint32 version;\n    }\n\n    /// @notice Local chain Origin: used for sending messages\n    address public immutable origin;\n\n    /// @notice Local chain Destination: used for receiving messages\n    address public immutable destination;\n\n    constructor(address origin_, address destination_) {\n        origin = origin_;\n        destination = destination_;\n    }\n\n    /// @inheritdoc IMessageRecipient\n    function receiveBaseMessage(\n        uint32 origin_,\n        uint32 nonce,\n        bytes32 sender,\n        uint256 proofMaturity,\n        uint32 version,\n        bytes memory content\n    ) external payable {\n        if (msg.sender != destination) revert CallerNotDestination();\n        if (nonce == 0) revert IncorrectNonce();\n        if (sender == 0) revert IncorrectSender();\n        if (proofMaturity == 0) revert ZeroProofMaturity();\n        _receiveBaseMessageUnsafe(origin_, nonce, sender, proofMaturity, version, content);\n    }\n\n    /**\n     * @dev Child contracts should implement the logic for receiving a Base Message in an \"unsafe way\".\n     * Following checks HAVE been performed:\n     *  - receiveBaseMessage() was called by Destination (i.e. this is a legit base message).\n     *  - Nonce is not zero.\n     *  - Message sender on origin chain is not a zero address.\n     *  - Proof maturity is not zero.\n     * Following checks HAVE NOT been performed (thus \"unsafe\"):\n     *  - Message sender on origin chain could be anything non-zero at this point.\n     *  - Proof maturity could be anything non-zero at this point.\n     */\n    function _receiveBaseMessageUnsafe(\n        uint32 origin_,\n        uint32 nonce,\n        bytes32 sender,\n        uint256 proofMaturity,\n        uint32 version,\n        bytes memory content\n    ) internal virtual;\n\n    /**\n     * @dev Sends a message to given destination chain. Full `msg.value` is used to pay for the message tips.\n     * `_getMinimumTipsValue()` could be used to calculate the minimum required tips value, and should be also\n     * exposed as a public view function to estimate the tips value before sending a message off-chain.\n     * This function is not exposed in MessageRecipient, as the message encoding is implemented by the child contract.\n     * @param destination_          Domain of the destination chain\n     * @param recipient             Address of the recipient on destination chain\n     * @param optimisticPeriod      Optimistic period for the message\n     * @param tipsValue             Tips to be paid for sending the message\n     * @param request               Message execution request on destination chain\n     * @param content               The message content\n     */\n    function _sendBaseMessage(\n        uint32 destination_,\n        bytes32 recipient,\n        uint32 optimisticPeriod,\n        uint256 tipsValue,\n        MessageRequest memory request,\n        bytes memory content\n    ) internal returns (uint32 messageNonce, bytes32 messageHash) {\n        if (recipient == 0) revert IncorrectRecipient();\n        return InterfaceOrigin(origin).sendBaseMessage{value: tipsValue}(\n            destination_, recipient, optimisticPeriod, _encodeRequest(request), content\n        );\n    }\n\n    /**\n     * @dev Returns the minimum tips value for sending a message to given destination chain.\n     * @param destination_          Domain of the destination chain\n     * @param request               Message execution request on destination chain\n     * @param contentLength         Length of the message content\n     */\n    function _getMinimumTipsValue(uint32 destination_, MessageRequest memory request, uint256 contentLength)\n        internal\n        view\n        returns (uint256 tipsValue)\n    {\n        return InterfaceOrigin(origin).getMinimumTipsValue(destination_, _encodeRequest(request), contentLength);\n    }\n\n    /**\n     * @dev Encodes a message execution request into format that Origin contract is using.\n     * @param request               Message execution request on destination chain\n     * @return paddedRequest        Encoded request\n     */\n    function _encodeRequest(MessageRequest memory request) internal pure returns (uint256 paddedRequest) {\n        return Request.unwrap(RequestLib.encodeRequest(request.gasDrop, request.gasLimit, request.version));\n    }\n}\n\n// contracts/client/TestClient.sol\n\n// ══════════════════════════════ LIBRARY IMPORTS ══════════════════════════════\n\n// ═════════════════════════════ INTERNAL IMPORTS ══════════════════════════════\n\ncontract TestClient is MessageRecipient {\n    event MessageReceived(\n        uint32 origin, uint32 nonce, bytes32 sender, uint256 proofMaturity, uint32 version, bytes content\n    );\n\n    event MessageSent(uint32 destination, uint32 nonce, bytes32 sender, bytes32 recipient, bytes content);\n\n    // solhint-disable-next-line no-empty-blocks\n    constructor(address origin_, address destination_) MessageRecipient(origin_, destination_) {}\n\n    function sendMessage(\n        uint32 destination_,\n        address recipientAddress,\n        uint32 optimisticPeriod,\n        uint64 gasLimit,\n        uint32 version,\n        bytes memory content\n    ) external payable {\n        bytes32 recipient = TypeCasts.addressToBytes32(recipientAddress);\n        MessageRequest memory request = MessageRequest({gasDrop: 0, gasLimit: gasLimit, version: version});\n        (uint32 nonce,) = _sendBaseMessage({\n            destination_: destination_,\n            recipient: recipient,\n            optimisticPeriod: optimisticPeriod,\n            tipsValue: msg.value,\n            request: request,\n            content: content\n        });\n        emit MessageSent(destination_, nonce, TypeCasts.addressToBytes32(address(this)), recipient, content);\n    }\n\n    /// @inheritdoc MessageRecipient\n    function _receiveBaseMessageUnsafe(\n        uint32 origin_,\n        uint32 nonce,\n        bytes32 sender,\n        uint256 proofMaturity,\n        uint32 version,\n        bytes memory content\n    ) internal override {\n        emit MessageReceived(origin_, nonce, sender, proofMaturity, version, content);\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":"19654:1586:0:-:0;;;19998:93;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1;;;;;15242:16:0;;;;;15268:26;;;19654:1586;;14:177:1;93:13;;-1:-1:-1;;;;;135:31:1;;125:42;;115:70;;181:1;178;171:12;115:70;14:177;;;:::o;196:293::-;275:6;283;336:2;324:9;315:7;311:23;307:32;304:52;;;352:1;349;342:12;304:52;375:40;405:9;375:40;:::i;:::-;365:50;;434:49;479:2;468:9;464:18;434:49;:::i;:::-;424:59;;196:293;;;;;:::o;:::-;19654:1586:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;","srcMapRuntime":"19654:1586:0:-:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;15345:535;;;;;;:::i;:::-;;:::i;:::-;;20097:790;;;;;;:::i;:::-;;:::i;15031:31::-;;;;;;;;;;;;;;;;;;3291:42:1;3279:55;;;3261:74;;3249:2;3234:18;15031:31:0;;;;;;;15138:36;;;;;;;;;;;;;;;15345:535;15565:10;:25;15579:11;15565:25;;15561:60;;15599:22;;;;;;;;;;;;;;15561:60;15635:5;:10;;15644:1;15635:10;15631:39;;15654:16;;;;;;;;;;;;;;15631:39;15694:1;15684:11;;;15680:41;;15704:17;;;;;;;;;;;;;;15680:41;15735:13;15752:1;15735:18;15731:50;;15762:19;;;;;;;;;;;;;;15731:50;15791:82;15817:7;15826:5;15833:6;15841:13;15856:7;15865;15791:25;:82::i;:::-;15345:535;;;;;;:::o;20097:790::-;20432:66;;;;;;;;20326:17;20432:66;;;;;;;;;;;;;;;;;;;;10565:22;;;;20526:244;20571:12;10565:22;20649:16;20690:9;20432:66;20752:7;20526:16;:244::i;:::-;-1:-1:-1;20508:262:0;-1:-1:-1;20785:95:0;20797:12;20508:262;20853:4;20861:9;20872:7;20785:95;;;;;;;;;;:::i;:::-;;;;;;;;20316:571;;;20097:790;;;;;;:::o;20930:308::-;21159:72;21175:7;21184:5;21191:6;21199:13;21214:7;21223;21159:72;;;;;;;;;;;:::i;:::-;;;;;;;;20930:308;;;;;;:::o;17605:514::-;17840:19;;17896:14;;;17892:47;;17919:20;;;;;;;;;;;;;;17892:47;17972:6;17956:39;;;18003:9;18027:12;18041:9;18052:16;18070:23;18085:7;18070:14;:23::i;:::-;18095:7;17956:156;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;17949:163;;;;17605:514;;;;;;;;;:::o;18995:217::-;19073:21;19128:76;19153:7;:15;;;19170:7;:16;;;19188:7;:15;;;12632:35;11996:6;12632:35;;;;12670:37;12106:5;12670:37;;;;12632:75;:86;;;;12442:284;;;;;;19128:76;19106:99;;;18995:217;-1:-1:-1;;18995:217:0:o;14:121:1:-;99:10;92:5;88:22;81:5;78:33;68:61;;125:1;122;115:12;68:61;14:121;:::o;140:184::-;192:77;189:1;182:88;289:4;286:1;279:15;313:4;310:1;303:15;329:777;371:5;424:3;417:4;409:6;405:17;401:27;391:55;;442:1;439;432:12;391:55;478:6;465:20;504:18;541:2;537;534:10;531:36;;;547:18;;:::i;:::-;681:2;675:9;743:4;735:13;;586:66;731:22;;;755:2;727:31;723:40;711:53;;;779:18;;;799:22;;;776:46;773:72;;;825:18;;:::i;:::-;865:10;861:2;854:22;900:2;892:6;885:18;946:3;939:4;934:2;926:6;922:15;918:26;915:35;912:55;;;963:1;960;953:12;912:55;1027:2;1020:4;1012:6;1008:17;1001:4;993:6;989:17;976:54;1074:1;1067:4;1062:2;1054:6;1050:15;1046:26;1039:37;1094:6;1085:15;;;;;;329:777;;;;:::o;1111:870::-;1221:6;1229;1237;1245;1253;1261;1314:3;1302:9;1293:7;1289:23;1285:33;1282:53;;;1331:1;1328;1321:12;1282:53;1370:9;1357:23;1389:30;1413:5;1389:30;:::i;:::-;1438:5;-1:-1:-1;1495:2:1;1480:18;;1467:32;1508;1467;1508;:::i;:::-;1559:7;-1:-1:-1;1613:2:1;1598:18;;1585:32;;-1:-1:-1;1664:2:1;1649:18;;1636:32;;-1:-1:-1;1720:3:1;1705:19;;1692:33;1734:32;1692:33;1734:32;:::i;:::-;1785:7;-1:-1:-1;1843:3:1;1828:19;;1815:33;1871:18;1860:30;;1857:50;;;1903:1;1900;1893:12;1857:50;1926:49;1967:7;1958:6;1947:9;1943:22;1926:49;:::i;:::-;1916:59;;;1111:870;;;;;;;;:::o;1986:1124::-;2095:6;2103;2111;2119;2127;2135;2188:3;2176:9;2167:7;2163:23;2159:33;2156:53;;;2205:1;2202;2195:12;2156:53;2244:9;2231:23;2263:30;2287:5;2263:30;:::i;:::-;2312:5;-1:-1:-1;2369:2:1;2354:18;;2341:32;2417:42;2404:56;;2392:69;;2382:97;;2475:1;2472;2465:12;2382:97;2498:7;-1:-1:-1;2557:2:1;2542:18;;2529:32;2570;2529;2570;:::i;:::-;2621:7;-1:-1:-1;2680:2:1;2665:18;;2652:32;2703:18;2752:16;;;2740:29;;2730:57;;2783:1;2780;2773:12;2730:57;2806:7;;-1:-1:-1;2865:3:1;2850:19;;2837:33;;2879:32;2837:33;2879:32;:::i;:::-;2930:7;;-1:-1:-1;2988:3:1;2973:19;;2960:33;;3005:14;;;3002:34;;;3032:1;3029;3022:12;3002:34;;3055:49;3096:7;3087:6;3076:9;3072:22;3055:49;:::i;3346:481::-;3387:3;3425:5;3419:12;3452:6;3447:3;3440:19;3477:1;3487:162;3501:6;3498:1;3495:13;3487:162;;;3563:4;3619:13;;;3615:22;;3609:29;3591:11;;;3587:20;;3580:59;3516:12;3487:162;;;3491:3;3694:1;3687:4;3678:6;3673:3;3669:16;3665:27;3658:38;3816:4;3746:66;3741:2;3733:6;3729:15;3725:88;3720:3;3716:98;3712:109;3705:116;;;3346:481;;;;:::o;3832:547::-;4050:4;4079:10;4128:2;4120:6;4116:15;4105:9;4098:34;4180:2;4172:6;4168:15;4163:2;4152:9;4148:18;4141:43;;4220:6;4215:2;4204:9;4200:18;4193:34;4263:6;4258:2;4247:9;4243:18;4236:34;4307:3;4301;4290:9;4286:19;4279:32;4328:45;4368:3;4357:9;4353:19;4345:6;4328:45;:::i;:::-;4320:53;3832:547;-1:-1:-1;;;;;;;3832:547:1:o;4384:626::-;4628:4;4657:10;4706:2;4698:6;4694:15;4683:9;4676:34;4758:2;4750:6;4746:15;4741:2;4730:9;4726:18;4719:43;4798:6;4793:2;4782:9;4778:18;4771:34;4841:6;4836:2;4825:9;4821:18;4814:34;4897:2;4889:6;4885:15;4879:3;4868:9;4864:19;4857:44;;4938:3;4932;4921:9;4917:19;4910:32;4959:45;4999:3;4988:9;4984:19;4976:6;4959:45;:::i;:::-;4951:53;4384:626;-1:-1:-1;;;;;;;;4384:626:1:o;5015:547::-;5233:4;5262:10;5311:2;5303:6;5299:15;5288:9;5281:34;5351:6;5346:2;5335:9;5331:18;5324:34;5406:2;5398:6;5394:15;5389:2;5378:9;5374:18;5367:43;;5446:6;5441:2;5430:9;5426:18;5419:34;5490:3;5484;5473:9;5469:19;5462:32;5511:45;5551:3;5540:9;5536:19;5528:6;5511:45;:::i;5567:310::-;5645:6;5653;5706:2;5694:9;5685:7;5681:23;5677:32;5674:52;;;5722:1;5719;5712:12;5674:52;5754:9;5748:16;5773:30;5797:5;5773:30;:::i;:::-;5867:2;5852:18;;;;5846:25;5822:5;;5846:25;;-1:-1:-1;;;5567:310:1:o","abiDefinition":[{"inputs":[{"internalType":"address","name":"origin_","type":"address"},{"internalType":"address","name":"destination_","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"CallerNotDestination","type":"error"},{"inputs":[],"name":"IncorrectNonce","type":"error"},{"inputs":[],"name":"IncorrectRecipient","type":"error"},{"inputs":[],"name":"IncorrectSender","type":"error"},{"inputs":[],"name":"ZeroProofMaturity","type":"error"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint32","name":"origin","type":"uint32"},{"indexed":false,"internalType":"uint32","name":"nonce","type":"uint32"},{"indexed":false,"internalType":"bytes32","name":"sender","type":"bytes32"},{"indexed":false,"internalType":"uint256","name":"proofMaturity","type":"uint256"},{"indexed":false,"internalType":"uint32","name":"version","type":"uint32"},{"indexed":false,"internalType":"bytes","name":"content","type":"bytes"}],"name":"MessageReceived","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint32","name":"destination","type":"uint32"},{"indexed":false,"internalType":"uint32","name":"nonce","type":"uint32"},{"indexed":false,"internalType":"bytes32","name":"sender","type":"bytes32"},{"indexed":false,"internalType":"bytes32","name":"recipient","type":"bytes32"},{"indexed":false,"internalType":"bytes","name":"content","type":"bytes"}],"name":"MessageSent","type":"event"},{"inputs":[],"name":"destination","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"origin","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint32","name":"origin_","type":"uint32"},{"internalType":"uint32","name":"nonce","type":"uint32"},{"internalType":"bytes32","name":"sender","type":"bytes32"},{"internalType":"uint256","name":"proofMaturity","type":"uint256"},{"internalType":"uint32","name":"version","type":"uint32"},{"internalType":"bytes","name":"content","type":"bytes"}],"name":"receiveBaseMessage","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"uint32","name":"destination_","type":"uint32"},{"internalType":"address","name":"recipientAddress","type":"address"},{"internalType":"uint32","name":"optimisticPeriod","type":"uint32"},{"internalType":"uint64","name":"gasLimit","type":"uint64"},{"internalType":"uint32","name":"version","type":"uint32"},{"internalType":"bytes","name":"content","type":"bytes"}],"name":"sendMessage","outputs":[],"stateMutability":"payable","type":"function"}],"userDoc":{"kind":"user","methods":{"destination()":{"notice":"Local chain Destination: used for receiving messages"},"origin()":{"notice":"Local chain Origin: used for sending messages"},"receiveBaseMessage(uint32,uint32,bytes32,uint256,uint32,bytes)":{"notice":"Message recipient needs to implement this function in order to receive cross-chain messages."}},"version":1},"developerDoc":{"kind":"dev","methods":{"receiveBaseMessage(uint32,uint32,bytes32,uint256,uint32,bytes)":{"details":"Message recipient needs to ensure that merkle proof for the message is at least as old as the optimistic period that the recipient is using. Note: as this point it is checked that the \"message optimistic period\" has passed, however the period value itself could be anything, and thus could differ from the one that the recipient would like to enforce.","params":{"content":"Raw bytes content of message","nonce":"Message nonce on the origin domain","origin":"Domain where message originated","proofMaturity":"Message's merkle proof age in seconds","sender":"Sender address on origin chain","version":"Message version specified by sender"}}},"version":1},"metadata":"{\"compiler\":{\"version\":\"0.8.17+commit.8df45f5f\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"origin_\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"destination_\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[],\"name\":\"CallerNotDestination\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"IncorrectNonce\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"IncorrectRecipient\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"IncorrectSender\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ZeroProofMaturity\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint32\",\"name\":\"origin\",\"type\":\"uint32\"},{\"indexed\":false,\"internalType\":\"uint32\",\"name\":\"nonce\",\"type\":\"uint32\"},{\"indexed\":false,\"internalType\":\"bytes32\",\"name\":\"sender\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"proofMaturity\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint32\",\"name\":\"version\",\"type\":\"uint32\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"content\",\"type\":\"bytes\"}],\"name\":\"MessageReceived\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint32\",\"name\":\"destination\",\"type\":\"uint32\"},{\"indexed\":false,\"internalType\":\"uint32\",\"name\":\"nonce\",\"type\":\"uint32\"},{\"indexed\":false,\"internalType\":\"bytes32\",\"name\":\"sender\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"bytes32\",\"name\":\"recipient\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"content\",\"type\":\"bytes\"}],\"name\":\"MessageSent\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"destination\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"origin\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint32\",\"name\":\"origin_\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"nonce\",\"type\":\"uint32\"},{\"internalType\":\"bytes32\",\"name\":\"sender\",\"type\":\"bytes32\"},{\"internalType\":\"uint256\",\"name\":\"proofMaturity\",\"type\":\"uint256\"},{\"internalType\":\"uint32\",\"name\":\"version\",\"type\":\"uint32\"},{\"internalType\":\"bytes\",\"name\":\"content\",\"type\":\"bytes\"}],\"name\":\"receiveBaseMessage\",\"outputs\":[],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint32\",\"name\":\"destination_\",\"type\":\"uint32\"},{\"internalType\":\"address\",\"name\":\"recipientAddress\",\"type\":\"address\"},{\"internalType\":\"uint32\",\"name\":\"optimisticPeriod\",\"type\":\"uint32\"},{\"internalType\":\"uint64\",\"name\":\"gasLimit\",\"type\":\"uint64\"},{\"internalType\":\"uint32\",\"name\":\"version\",\"type\":\"uint32\"},{\"internalType\":\"bytes\",\"name\":\"content\",\"type\":\"bytes\"}],\"name\":\"sendMessage\",\"outputs\":[],\"stateMutability\":\"payable\",\"type\":\"function\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{\"receiveBaseMessage(uint32,uint32,bytes32,uint256,uint32,bytes)\":{\"details\":\"Message recipient needs to ensure that merkle proof for the message is at least as old as the optimistic period that the recipient is using. Note: as this point it is checked that the \\\"message optimistic period\\\" has passed, however the period value itself could be anything, and thus could differ from the one that the recipient would like to enforce.\",\"params\":{\"content\":\"Raw bytes content of message\",\"nonce\":\"Message nonce on the origin domain\",\"origin\":\"Domain where message originated\",\"proofMaturity\":\"Message's merkle proof age in seconds\",\"sender\":\"Sender address on origin chain\",\"version\":\"Message version specified by sender\"}}},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{\"destination()\":{\"notice\":\"Local chain Destination: used for receiving messages\"},\"origin()\":{\"notice\":\"Local chain Origin: used for sending messages\"},\"receiveBaseMessage(uint32,uint32,bytes32,uint256,uint32,bytes)\":{\"notice\":\"Message recipient needs to implement this function in order to receive cross-chain messages.\"}},\"version\":1}},\"settings\":{\"compilationTarget\":{\"solidity/TestClient.sol\":\"TestClient\"},\"evmVersion\":\"london\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\"},\"optimizer\":{\"enabled\":true,\"runs\":10000},\"remappings\":[]},\"sources\":{\"solidity/TestClient.sol\":{\"keccak256\":\"0x0559f7adcbbadc7e14f6d1a8909db6085e58daebca746390c188879460d4fb90\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://dfac7d1d9b1255e057dc37b120623dd3edb15a776ce793b81955ab51c6f59ba1\",\"dweb:/ipfs/Qmd7j2CjYA91DTqJMMmnTt4Y9wvDdhVH7Bgt4MFBPdY3rS\"]}},\"version\":1}"},"hashes":{"destination()":"b269681d","origin()":"938b5f32","receiveBaseMessage(uint32,uint32,bytes32,uint256,uint32,bytes)":"032f287e","sendMessage(uint32,address,uint32,uint64,uint32,bytes)":"6d82c665"}},"solidity/TestClient.sol:TypeCasts":{"code":"0x60566037600b82828239805160001a607314602a57634e487b7160e01b600052600060045260246000fd5b30600052607381538281f3fe73000000000000000000000000000000000000000030146080604052600080fdfea2646970667358221220f262c6946df0f7c3aac362cb84a229938d3d049173ca72d0be653181895a457164736f6c63430008110033","runtime-code":"0x73000000000000000000000000000000000000000030146080604052600080fdfea2646970667358221220f262c6946df0f7c3aac362cb84a229938d3d049173ca72d0be653181895a457164736f6c63430008110033","info":{"source":"// SPDX-License-Identifier: MIT\npragma solidity =0.8.17;\n\n// contracts/interfaces/IMessageRecipient.sol\n\ninterface IMessageRecipient {\n    /**\n     * @notice Message recipient needs to implement this function in order to\n     * receive cross-chain messages.\n     * @dev Message recipient needs to ensure that merkle proof for the message\n     * is at least as old as the optimistic period that the recipient is using.\n     * Note: as this point it is checked that the \"message optimistic period\" has passed,\n     * however the period value itself could be anything, and thus could differ from the one\n     * that the recipient would like to enforce.\n     * @param origin            Domain where message originated\n     * @param nonce             Message nonce on the origin domain\n     * @param sender            Sender address on origin chain\n     * @param proofMaturity     Message's merkle proof age in seconds\n     * @param version           Message version specified by sender\n     * @param content           Raw bytes content of message\n     */\n    function receiveBaseMessage(\n        uint32 origin,\n        uint32 nonce,\n        bytes32 sender,\n        uint256 proofMaturity,\n        uint32 version,\n        bytes memory content\n    ) external payable;\n}\n\n// contracts/interfaces/InterfaceOrigin.sol\n\ninterface InterfaceOrigin {\n    // ═══════════════════════════════════════════════ SEND MESSAGES ═══════════════════════════════════════════════════\n\n    /**\n     * @notice Send a message to the recipient located on destination domain.\n     * @dev Recipient has to conform to IMessageRecipient interface, otherwise message won't be delivered.\n     * Will revert if any of these is true:\n     * - `destination` is equal to contract's local domain\n     * - `content` length is greater than `MAX_CONTENT_BYTES`\n     * - `msg.value` is lower than value of minimum tips for the given message\n     * @param destination           Domain of destination chain\n     * @param recipient             Address of recipient on destination chain as bytes32\n     * @param optimisticPeriod      Optimistic period for message execution on destination chain\n     * @param paddedRequest         Padded encoded message execution request on destination chain\n     * @param content               Raw bytes content of message\n     * @return messageNonce         Nonce of the sent message\n     * @return messageHash          Hash of the sent message\n     */\n    function sendBaseMessage(\n        uint32 destination,\n        bytes32 recipient,\n        uint32 optimisticPeriod,\n        uint256 paddedRequest,\n        bytes memory content\n    ) external payable returns (uint32 messageNonce, bytes32 messageHash);\n\n    /**\n     * @notice Send a manager message to the destination domain.\n     * @dev This could only be called by AgentManager, which takes care of encoding the calldata payload.\n     * Note: (msgOrigin, proofMaturity) security args will be added to payload on the destination chain\n     * so that the AgentManager could verify where the Manager Message came from and how mature is the proof.\n     * Note: function is not payable, as no tips are required for sending a manager message.\n     * Will revert if `destination` is equal to contract's local domain.\n     * @param destination           Domain of destination chain\n     * @param optimisticPeriod      Optimistic period for message execution on destination chain\n     * @param payload               Payload for calling AgentManager on destination chain (with extra security args)\n     */\n    function sendManagerMessage(uint32 destination, uint32 optimisticPeriod, bytes memory payload)\n        external\n        returns (uint32 messageNonce, bytes32 messageHash);\n\n    // ════════════════════════════════════════════════ TIPS LOGIC ═════════════════════════════════════════════════════\n\n    /**\n     * @notice Withdraws locked base message tips to the recipient.\n     * @dev Could only be called by a local AgentManager.\n     * @param recipient     Address to withdraw tips to\n     * @param amount        Tips value to withdraw\n     */\n    function withdrawTips(address recipient, uint256 amount) external;\n\n    // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════\n\n    /**\n     * @notice Returns the minimum tips value for sending a message to a given destination.\n     * @dev Using at least `tipsValue` as `msg.value` for `sendBaseMessage()`\n     * will guarantee that the message will be accepted.\n     * @param destination       Domain of destination chain\n     * @param paddedRequest     Padded encoded message execution request on destination chain\n     * @param contentLength     The length of the message content\n     * @return tipsValue        Minimum tips value for a message to be accepted\n     */\n    function getMinimumTipsValue(uint32 destination, uint256 paddedRequest, uint256 contentLength)\n        external\n        view\n        returns (uint256 tipsValue);\n}\n\n// contracts/libs/Errors.sol\n\n// ══════════════════════════════ INVALID CALLER ═══════════════════════════════\n\nerror CallerNotAgentManager();\nerror CallerNotDestination();\nerror CallerNotInbox();\nerror CallerNotSummit();\n\n// ══════════════════════════════ INCORRECT DATA ═══════════════════════════════\n\nerror IncorrectAttestation();\nerror IncorrectAgentDomain();\nerror IncorrectAgentIndex();\nerror IncorrectAgentProof();\nerror IncorrectAgentRoot();\nerror IncorrectDataHash();\nerror IncorrectDestinationDomain();\nerror IncorrectOriginDomain();\nerror IncorrectSnapshotProof();\nerror IncorrectSnapshotRoot();\nerror IncorrectState();\nerror IncorrectStatesAmount();\nerror IncorrectTipsProof();\nerror IncorrectVersionLength();\n\nerror IncorrectNonce();\nerror IncorrectSender();\nerror IncorrectRecipient();\n\nerror FlagOutOfRange();\nerror IndexOutOfRange();\nerror NonceOutOfRange();\n\nerror OutdatedNonce();\n\nerror UnformattedAttestation();\nerror UnformattedAttestationReport();\nerror UnformattedBaseMessage();\nerror UnformattedCallData();\nerror UnformattedCallDataPrefix();\nerror UnformattedMessage();\nerror UnformattedReceipt();\nerror UnformattedReceiptReport();\nerror UnformattedSignature();\nerror UnformattedSnapshot();\nerror UnformattedState();\nerror UnformattedStateReport();\n\n// ═══════════════════════════════ MERKLE TREES ════════════════════════════════\n\nerror LeafNotProven();\nerror MerkleTreeFull();\nerror NotEnoughLeafs();\nerror TreeHeightTooLow();\n\n// ═════════════════════════════ OPTIMISTIC PERIOD ═════════════════════════════\n\nerror BaseClientOptimisticPeriod();\nerror MessageOptimisticPeriod();\nerror SlashAgentOptimisticPeriod();\nerror WithdrawTipsOptimisticPeriod();\nerror ZeroProofMaturity();\n\n// ═══════════════════════════════ AGENT MANAGER ═══════════════════════════════\n\nerror AgentNotGuard();\nerror AgentNotNotary();\n\nerror AgentCantBeAdded();\nerror AgentNotActive();\nerror AgentNotActiveNorUnstaking();\nerror AgentNotFraudulent();\nerror AgentNotUnstaking();\nerror AgentUnknown();\n\nerror AgentRootNotProposed();\nerror AgentRootTimeoutNotOver();\n\nerror NotStuck();\n\nerror DisputeAlreadyResolved();\nerror DisputeNotOpened();\nerror DisputeTimeoutNotOver();\nerror GuardInDispute();\nerror NotaryInDispute();\n\nerror MustBeSynapseDomain();\nerror SynapseDomainForbidden();\n\n// ════════════════════════════════ DESTINATION ════════════════════════════════\n\nerror AlreadyExecuted();\nerror AlreadyFailed();\nerror DuplicatedSnapshotRoot();\nerror IncorrectMagicValue();\nerror GasLimitTooLow();\nerror GasSuppliedTooLow();\n\n// ══════════════════════════════════ ORIGIN ═══════════════════════════════════\n\nerror ContentLengthTooBig();\nerror EthTransferFailed();\nerror InsufficientEthBalance();\n\n// ════════════════════════════════ GAS ORACLE ═════════════════════════════════\n\nerror LocalGasDataNotSet();\nerror RemoteGasDataNotSet();\n\n// ═══════════════════════════════════ TIPS ════════════════════════════════════\n\nerror SummitTipTooHigh();\nerror TipsClaimMoreThanEarned();\nerror TipsClaimZero();\nerror TipsOverflow();\nerror TipsValueTooLow();\n\n// ════════════════════════════════ MEMORY VIEW ════════════════════════════════\n\nerror IndexedTooMuch();\nerror ViewOverrun();\nerror OccupiedMemory();\nerror UnallocatedMemory();\nerror PrecompileOutOfGas();\n\n// ═════════════════════════════════ MULTICALL ═════════════════════════════════\n\nerror MulticallFailed();\n\n// contracts/libs/TypeCasts.sol\n\nlibrary TypeCasts {\n    // alignment preserving cast\n    function addressToBytes32(address addr) internal pure returns (bytes32) {\n        return bytes32(uint256(uint160(addr)));\n    }\n\n    // alignment preserving cast\n    function bytes32ToAddress(bytes32 buf) internal pure returns (address) {\n        return address(uint160(uint256(buf)));\n    }\n}\n\n// contracts/libs/stack/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// contracts/client/MessageRecipient.sol\n\n// ══════════════════════════════ LIBRARY IMPORTS ══════════════════════════════\n\n// ═════════════════════════════ INTERNAL IMPORTS ══════════════════════════════\n\nabstract contract MessageRecipient is IMessageRecipient {\n    struct MessageRequest {\n        uint96 gasDrop;\n        uint64 gasLimit;\n        uint32 version;\n    }\n\n    /// @notice Local chain Origin: used for sending messages\n    address public immutable origin;\n\n    /// @notice Local chain Destination: used for receiving messages\n    address public immutable destination;\n\n    constructor(address origin_, address destination_) {\n        origin = origin_;\n        destination = destination_;\n    }\n\n    /// @inheritdoc IMessageRecipient\n    function receiveBaseMessage(\n        uint32 origin_,\n        uint32 nonce,\n        bytes32 sender,\n        uint256 proofMaturity,\n        uint32 version,\n        bytes memory content\n    ) external payable {\n        if (msg.sender != destination) revert CallerNotDestination();\n        if (nonce == 0) revert IncorrectNonce();\n        if (sender == 0) revert IncorrectSender();\n        if (proofMaturity == 0) revert ZeroProofMaturity();\n        _receiveBaseMessageUnsafe(origin_, nonce, sender, proofMaturity, version, content);\n    }\n\n    /**\n     * @dev Child contracts should implement the logic for receiving a Base Message in an \"unsafe way\".\n     * Following checks HAVE been performed:\n     *  - receiveBaseMessage() was called by Destination (i.e. this is a legit base message).\n     *  - Nonce is not zero.\n     *  - Message sender on origin chain is not a zero address.\n     *  - Proof maturity is not zero.\n     * Following checks HAVE NOT been performed (thus \"unsafe\"):\n     *  - Message sender on origin chain could be anything non-zero at this point.\n     *  - Proof maturity could be anything non-zero at this point.\n     */\n    function _receiveBaseMessageUnsafe(\n        uint32 origin_,\n        uint32 nonce,\n        bytes32 sender,\n        uint256 proofMaturity,\n        uint32 version,\n        bytes memory content\n    ) internal virtual;\n\n    /**\n     * @dev Sends a message to given destination chain. Full `msg.value` is used to pay for the message tips.\n     * `_getMinimumTipsValue()` could be used to calculate the minimum required tips value, and should be also\n     * exposed as a public view function to estimate the tips value before sending a message off-chain.\n     * This function is not exposed in MessageRecipient, as the message encoding is implemented by the child contract.\n     * @param destination_          Domain of the destination chain\n     * @param recipient             Address of the recipient on destination chain\n     * @param optimisticPeriod      Optimistic period for the message\n     * @param tipsValue             Tips to be paid for sending the message\n     * @param request               Message execution request on destination chain\n     * @param content               The message content\n     */\n    function _sendBaseMessage(\n        uint32 destination_,\n        bytes32 recipient,\n        uint32 optimisticPeriod,\n        uint256 tipsValue,\n        MessageRequest memory request,\n        bytes memory content\n    ) internal returns (uint32 messageNonce, bytes32 messageHash) {\n        if (recipient == 0) revert IncorrectRecipient();\n        return InterfaceOrigin(origin).sendBaseMessage{value: tipsValue}(\n            destination_, recipient, optimisticPeriod, _encodeRequest(request), content\n        );\n    }\n\n    /**\n     * @dev Returns the minimum tips value for sending a message to given destination chain.\n     * @param destination_          Domain of the destination chain\n     * @param request               Message execution request on destination chain\n     * @param contentLength         Length of the message content\n     */\n    function _getMinimumTipsValue(uint32 destination_, MessageRequest memory request, uint256 contentLength)\n        internal\n        view\n        returns (uint256 tipsValue)\n    {\n        return InterfaceOrigin(origin).getMinimumTipsValue(destination_, _encodeRequest(request), contentLength);\n    }\n\n    /**\n     * @dev Encodes a message execution request into format that Origin contract is using.\n     * @param request               Message execution request on destination chain\n     * @return paddedRequest        Encoded request\n     */\n    function _encodeRequest(MessageRequest memory request) internal pure returns (uint256 paddedRequest) {\n        return Request.unwrap(RequestLib.encodeRequest(request.gasDrop, request.gasLimit, request.version));\n    }\n}\n\n// contracts/client/TestClient.sol\n\n// ══════════════════════════════ LIBRARY IMPORTS ══════════════════════════════\n\n// ═════════════════════════════ INTERNAL IMPORTS ══════════════════════════════\n\ncontract TestClient is MessageRecipient {\n    event MessageReceived(\n        uint32 origin, uint32 nonce, bytes32 sender, uint256 proofMaturity, uint32 version, bytes content\n    );\n\n    event MessageSent(uint32 destination, uint32 nonce, bytes32 sender, bytes32 recipient, bytes content);\n\n    // solhint-disable-next-line no-empty-blocks\n    constructor(address origin_, address destination_) MessageRecipient(origin_, destination_) {}\n\n    function sendMessage(\n        uint32 destination_,\n        address recipientAddress,\n        uint32 optimisticPeriod,\n        uint64 gasLimit,\n        uint32 version,\n        bytes memory content\n    ) external payable {\n        bytes32 recipient = TypeCasts.addressToBytes32(recipientAddress);\n        MessageRequest memory request = MessageRequest({gasDrop: 0, gasLimit: gasLimit, version: version});\n        (uint32 nonce,) = _sendBaseMessage({\n            destination_: destination_,\n            recipient: recipient,\n            optimisticPeriod: optimisticPeriod,\n            tipsValue: msg.value,\n            request: request,\n            content: content\n        });\n        emit MessageSent(destination_, nonce, TypeCasts.addressToBytes32(address(this)), recipient, content);\n    }\n\n    /// @inheritdoc MessageRecipient\n    function _receiveBaseMessageUnsafe(\n        uint32 origin_,\n        uint32 nonce,\n        bytes32 sender,\n        uint256 proofMaturity,\n        uint32 version,\n        bytes memory content\n    ) internal override {\n        emit MessageReceived(origin_, nonce, sender, proofMaturity, version, content);\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":"10411:350:0:-:0;;;;;;;;;;;;;;;-1:-1:-1;;;10411:350:0;;;;;;;;;;;;;;;;;","srcMapRuntime":"10411:350:0:-:0;;;;;;;;","abiDefinition":[],"userDoc":{"kind":"user","methods":{},"version":1},"developerDoc":{"kind":"dev","methods":{},"version":1},"metadata":"{\"compiler\":{\"version\":\"0.8.17+commit.8df45f5f\"},\"language\":\"Solidity\",\"output\":{\"abi\":[],\"devdoc\":{\"kind\":\"dev\",\"methods\":{},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"solidity/TestClient.sol\":\"TypeCasts\"},\"evmVersion\":\"london\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\"},\"optimizer\":{\"enabled\":true,\"runs\":10000},\"remappings\":[]},\"sources\":{\"solidity/TestClient.sol\":{\"keccak256\":\"0x0559f7adcbbadc7e14f6d1a8909db6085e58daebca746390c188879460d4fb90\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://dfac7d1d9b1255e057dc37b120623dd3edb15a776ce793b81955ab51c6f59ba1\",\"dweb:/ipfs/Qmd7j2CjYA91DTqJMMmnTt4Y9wvDdhVH7Bgt4MFBPdY3rS\"]}},\"version\":1}"},"hashes":{}}}