creation_sourcecode: {{
    "language": "Solidity",
    "sources": {
      "src/NttManager/NttManager.sol": {
        "content": "// SPDX-License-Identifier: Apache 2\npragma solidity >=0.8.8 <0.9.0;\n\nimport \"openzeppelin-contracts/contracts/token/ERC20/IERC20.sol\";\nimport \"openzeppelin-contracts/contracts/token/ERC20/utils/SafeERC20.sol\";\nimport \"openzeppelin-contracts/contracts/token/ERC20/extensions/ERC20Burnable.sol\";\nimport \"wormhole-solidity-sdk/Utils.sol\";\nimport \"wormhole-solidity-sdk/libraries/BytesParsing.sol\";\n\nimport \"../libraries/RateLimiter.sol\";\n\nimport \"../interfaces/INttManager.sol\";\nimport \"../interfaces/INttToken.sol\";\nimport \"../interfaces/ITransceiver.sol\";\n\nimport {ManagerBase} from \"./ManagerBase.sol\";\n\n/// @title NttManager\n/// @author Wormhole Project Contributors.\n/// @notice The NttManager contract is responsible for managing the token\n///         and associated transceivers.\n///\n/// @dev Each NttManager contract is associated with a single token but\n///      can be responsible for multiple transceivers.\n///\n/// @dev When transferring tokens, the NttManager contract will either\n///      lock the tokens or burn them, depending on the mode.\n///\n/// @dev To initiate a transfer, the user calls the transfer function with:\n///  - the amount\n///  - the recipient chain\n///  - the recipient address\n///  - the refund address: the address to which refunds are issued for any unused gas\n///    for attestations on a given transfer. If the gas limit is configured\n///    to be too high, users will be refunded the difference.\n///  - (optional) a flag to indicate whether the transfer should be queued\n///    if the rate limit is exceeded\ncontract NttManager is INttManager, RateLimiter, ManagerBase {\n    using BytesParsing for bytes;\n    using SafeERC20 for IERC20;\n    using TrimmedAmountLib for uint256;\n    using TrimmedAmountLib for TrimmedAmount;\n\n    string public constant NTT_MANAGER_VERSION = \"1.0.0\";\n\n    // =============== Setup =================================================================\n\n    constructor(\n        address _token,\n        Mode _mode,\n        uint16 _chainId,\n        uint64 _rateLimitDuration,\n        bool _skipRateLimiting\n    ) RateLimiter(_rateLimitDuration, _skipRateLimiting) ManagerBase(_token, _mode, _chainId) {}\n\n    function __NttManager_init() internal onlyInitializing {\n        // check if the owner is the deployer of this contract\n        if (msg.sender != deployer) {\n            revert UnexpectedDeployer(deployer, msg.sender);\n        }\n        if (msg.value != 0) {\n            revert UnexpectedMsgValue();\n        }\n        __PausedOwnable_init(msg.sender, msg.sender);\n        __ReentrancyGuard_init();\n        _setOutboundLimit(TrimmedAmountLib.max(tokenDecimals()));\n    }\n\n    function _initialize() internal virtual override {\n        __NttManager_init();\n        _checkThresholdInvariants();\n        _checkTransceiversInvariants();\n    }\n\n    // =============== Storage ==============================================================\n\n    bytes32 private constant PEERS_SLOT = bytes32(uint256(keccak256(\"ntt.peers\")) - 1);\n\n    // =============== Storage Getters/Setters ==============================================\n\n    function _getPeersStorage()\n        internal\n        pure\n        returns (mapping(uint16 => NttManagerPeer) storage $)\n    {\n        uint256 slot = uint256(PEERS_SLOT);\n        assembly (\"memory-safe\") {\n            $.slot := slot\n        }\n    }\n\n    // =============== Public Getters ========================================================\n\n    /// @inheritdoc INttManager\n    function getPeer(uint16 chainId_) external view returns (NttManagerPeer memory) {\n        return _getPeersStorage()[chainId_];\n    }\n\n    // =============== Admin ==============================================================\n\n    /// @inheritdoc INttManager\n    function setPeer(\n        uint16 peerChainId,\n        bytes32 peerContract,\n        uint8 decimals,\n        uint256 inboundLimit\n    ) public onlyOwner {\n        if (peerChainId == 0) {\n            revert InvalidPeerChainIdZero();\n        }\n        if (peerContract == bytes32(0)) {\n            revert InvalidPeerZeroAddress();\n        }\n        if (decimals == 0) {\n            revert InvalidPeerDecimals();\n        }\n        if (peerChainId == chainId) {\n            revert InvalidPeerSameChainId();\n        }\n\n        NttManagerPeer memory oldPeer = _getPeersStorage()[peerChainId];\n\n        _getPeersStorage()[peerChainId].peerAddress = peerContract;\n        _getPeersStorage()[peerChainId].tokenDecimals = decimals;\n\n        uint8 toDecimals = tokenDecimals();\n        _setInboundLimit(inboundLimit.trim(toDecimals, toDecimals), peerChainId);\n\n        emit PeerUpdated(\n            peerChainId, oldPeer.peerAddress, oldPeer.tokenDecimals, peerContract, decimals\n        );\n    }\n\n    /// @inheritdoc INttManager\n    function setOutboundLimit(uint256 limit) external onlyOwner {\n        uint8 toDecimals = tokenDecimals();\n        _setOutboundLimit(limit.trim(toDecimals, toDecimals));\n    }\n\n    /// @inheritdoc INttManager\n    function setInboundLimit(uint256 limit, uint16 chainId_) external onlyOwner {\n        uint8 toDecimals = tokenDecimals();\n        _setInboundLimit(limit.trim(toDecimals, toDecimals), chainId_);\n    }\n\n    /// ============== Invariants =============================================\n\n    /// @dev When we add new immutables, this function should be updated\n    function _checkImmutables() internal view override {\n        super._checkImmutables();\n        assert(this.rateLimitDuration() == rateLimitDuration);\n    }\n\n    // ==================== External Interface ===============================================\n\n    /// @inheritdoc INttManager\n    function transfer(\n        uint256 amount,\n        uint16 recipientChain,\n        bytes32 recipient\n    ) external payable nonReentrant whenNotPaused returns (uint64) {\n        return\n            _transferEntryPoint(amount, recipientChain, recipient, recipient, false, new bytes(1));\n    }\n\n    /// @inheritdoc INttManager\n    function transfer(\n        uint256 amount,\n        uint16 recipientChain,\n        bytes32 recipient,\n        bytes32 refundAddress,\n        bool shouldQueue,\n        bytes memory transceiverInstructions\n    ) external payable nonReentrant whenNotPaused returns (uint64) {\n        return _transferEntryPoint(\n            amount, recipientChain, recipient, refundAddress, shouldQueue, transceiverInstructions\n        );\n    }\n\n    /// @inheritdoc INttManager\n    function attestationReceived(\n        uint16 sourceChainId,\n        bytes32 sourceNttManagerAddress,\n        TransceiverStructs.NttManagerMessage memory payload\n    ) external onlyTransceiver whenNotPaused {\n        _verifyPeer(sourceChainId, sourceNttManagerAddress);\n\n        // Compute manager message digest and record transceiver attestation.\n        bytes32 nttManagerMessageHash = _recordTransceiverAttestation(sourceChainId, payload);\n\n        if (isMessageApproved(nttManagerMessageHash)) {\n            executeMsg(sourceChainId, sourceNttManagerAddress, payload);\n        }\n    }\n\n    /// @inheritdoc INttManager\n    function executeMsg(\n        uint16 sourceChainId,\n        bytes32 sourceNttManagerAddress,\n        TransceiverStructs.NttManagerMessage memory message\n    ) public whenNotPaused {\n        (bytes32 digest, bool alreadyExecuted) =\n            _isMessageExecuted(sourceChainId, sourceNttManagerAddress, message);\n\n        if (alreadyExecuted) {\n            return;\n        }\n\n        TransceiverStructs.NativeTokenTransfer memory nativeTokenTransfer =\n            TransceiverStructs.parseNativeTokenTransfer(message.payload);\n\n        // verify that the destination chain is valid\n        if (nativeTokenTransfer.toChain != chainId) {\n            revert InvalidTargetChain(nativeTokenTransfer.toChain, chainId);\n        }\n        uint8 toDecimals = tokenDecimals();\n        TrimmedAmount nativeTransferAmount =\n            (nativeTokenTransfer.amount.untrim(toDecimals)).trim(toDecimals, toDecimals);\n\n        address transferRecipient = fromWormholeFormat(nativeTokenTransfer.to);\n\n        {\n            // Check inbound rate limits\n            bool isRateLimited = _isInboundAmountRateLimited(nativeTransferAmount, sourceChainId);\n            if (isRateLimited) {\n                // queue up the transfer\n                _enqueueInboundTransfer(digest, nativeTransferAmount, transferRecipient);\n\n                // end execution early\n                return;\n            }\n        }\n\n        // consume the amount for the inbound rate limit\n        _consumeInboundAmount(nativeTransferAmount, sourceChainId);\n        // When receiving a transfer, we refill the outbound rate limit\n        // by the same amount (we call this \"backflow\")\n        _backfillOutboundAmount(nativeTransferAmount);\n\n        _mintOrUnlockToRecipient(digest, transferRecipient, nativeTransferAmount, false);\n    }\n\n    /// @inheritdoc INttManager\n    function completeInboundQueuedTransfer(bytes32 digest) external nonReentrant whenNotPaused {\n        // find the message in the queue\n        InboundQueuedTransfer memory queuedTransfer = getInboundQueuedTransfer(digest);\n        if (queuedTransfer.txTimestamp == 0) {\n            revert InboundQueuedTransferNotFound(digest);\n        }\n\n        // check that > RATE_LIMIT_DURATION has elapsed\n        if (block.timestamp - queuedTransfer.txTimestamp < rateLimitDuration) {\n            revert InboundQueuedTransferStillQueued(digest, queuedTransfer.txTimestamp);\n        }\n\n        // remove transfer from the queue\n        delete _getInboundQueueStorage()[digest];\n\n        // run it through the mint/unlock logic\n        _mintOrUnlockToRecipient(digest, queuedTransfer.recipient, queuedTransfer.amount, false);\n    }\n\n    /// @inheritdoc INttManager\n    function completeOutboundQueuedTransfer(uint64 messageSequence)\n        external\n        payable\n        nonReentrant\n        whenNotPaused\n        returns (uint64)\n    {\n        // find the message in the queue\n        OutboundQueuedTransfer memory queuedTransfer = _getOutboundQueueStorage()[messageSequence];\n        if (queuedTransfer.txTimestamp == 0) {\n            revert OutboundQueuedTransferNotFound(messageSequence);\n        }\n\n        // check that > RATE_LIMIT_DURATION has elapsed\n        if (block.timestamp - queuedTransfer.txTimestamp < rateLimitDuration) {\n            revert OutboundQueuedTransferStillQueued(messageSequence, queuedTransfer.txTimestamp);\n        }\n\n        // remove transfer from the queue\n        delete _getOutboundQueueStorage()[messageSequence];\n\n        // run it through the transfer logic and skip the rate limit\n        return _transfer(\n            messageSequence,\n            queuedTransfer.amount,\n            queuedTransfer.recipientChain,\n            queuedTransfer.recipient,\n            queuedTransfer.refundAddress,\n            queuedTransfer.sender,\n            queuedTransfer.transceiverInstructions\n        );\n    }\n\n    /// @inheritdoc INttManager\n    function cancelOutboundQueuedTransfer(uint64 messageSequence)\n        external\n        nonReentrant\n        whenNotPaused\n    {\n        // find the message in the queue\n        OutboundQueuedTransfer memory queuedTransfer = _getOutboundQueueStorage()[messageSequence];\n        if (queuedTransfer.txTimestamp == 0) {\n            revert OutboundQueuedTransferNotFound(messageSequence);\n        }\n\n        // check msg.sender initiated the transfer\n        if (queuedTransfer.sender != msg.sender) {\n            revert CancellerNotSender(msg.sender, queuedTransfer.sender);\n        }\n\n        // remove transfer from the queue\n        delete _getOutboundQueueStorage()[messageSequence];\n\n        // return the queued funds to the sender\n        _mintOrUnlockToRecipient(\n            bytes32(uint256(messageSequence)), msg.sender, queuedTransfer.amount, true\n        );\n    }\n\n    // ==================== Internal Business Logic =========================================\n\n    function _transferEntryPoint(\n        uint256 amount,\n        uint16 recipientChain,\n        bytes32 recipient,\n        bytes32 refundAddress,\n        bool shouldQueue,\n        bytes memory transceiverInstructions\n    ) internal returns (uint64) {\n        if (amount == 0) {\n            revert ZeroAmount();\n        }\n\n        if (recipient == bytes32(0)) {\n            revert InvalidRecipient();\n        }\n\n        if (refundAddress == bytes32(0)) {\n            revert InvalidRefundAddress();\n        }\n\n        {\n            // Lock/burn tokens before checking rate limits\n            // use transferFrom to pull tokens from the user and lock them\n            // query own token balance before transfer\n            uint256 balanceBefore = _getTokenBalanceOf(token, address(this));\n\n            // transfer tokens\n            IERC20(token).safeTransferFrom(msg.sender, address(this), amount);\n\n            // query own token balance after transfer\n            uint256 balanceAfter = _getTokenBalanceOf(token, address(this));\n\n            // correct amount for potential transfer fees\n            amount = balanceAfter - balanceBefore;\n            if (mode == Mode.BURNING) {\n                {\n                    // NOTE: We don't account for burn fees in this code path.\n                    // We verify that the user's change in balance is equal to the amount that's burned.\n                    // Accounting for burn fees can be non-trivial, since there\n                    // is no standard way to account for the fee if the fee amount\n                    // is taken out of the burn amount.\n                    // For example, if there's a fee of 1 which is taken out of the\n                    // amount, then burning 20 tokens would result in a transfer of only 19 tokens.\n                    // However, the difference in the user's balance would only show 20.\n                    // Since there is no standard way to query for burn fee amounts with burnable tokens,\n                    // and NTT would be used on a per-token basis, implementing this functionality\n                    // is left to integrating projects who may need to account for burn fees on their tokens.\n                    ERC20Burnable(token).burn(amount);\n\n                    // tokens held by the contract after the operation should be the same as before\n                    uint256 balanceAfterBurn = _getTokenBalanceOf(token, address(this));\n                    if (balanceBefore != balanceAfterBurn) {\n                        revert BurnAmountDifferentThanBalanceDiff(balanceBefore, balanceAfterBurn);\n                    }\n                }\n            }\n        }\n\n        // trim amount after burning to ensure transfer amount matches (amount - fee)\n        TrimmedAmount trimmedAmount = _trimTransferAmount(amount, recipientChain);\n        TrimmedAmount internalAmount = trimmedAmount.shift(tokenDecimals());\n\n        // get the sequence for this transfer\n        uint64 sequence = _useMessageSequence();\n\n        {\n            // now check rate limits\n            bool isAmountRateLimited = _isOutboundAmountRateLimited(internalAmount);\n            if (!shouldQueue && isAmountRateLimited) {\n                revert NotEnoughCapacity(getCurrentOutboundCapacity(), amount);\n            }\n            if (shouldQueue && isAmountRateLimited) {\n                // verify chain has not forked\n                checkFork(evmChainId);\n\n                // emit an event to notify the user that the transfer is rate limited\n                emit OutboundTransferRateLimited(\n                    msg.sender, sequence, amount, getCurrentOutboundCapacity()\n                );\n\n                // queue up and return\n                _enqueueOutboundTransfer(\n                    sequence,\n                    trimmedAmount,\n                    recipientChain,\n                    recipient,\n                    refundAddress,\n                    msg.sender,\n                    transceiverInstructions\n                );\n\n                // refund price quote back to sender\n                _refundToSender(msg.value);\n\n                // return the sequence in the queue\n                return sequence;\n            }\n        }\n\n        // otherwise, consume the outbound amount\n        _consumeOutboundAmount(internalAmount);\n        // When sending a transfer, we refill the inbound rate limit for\n        // that chain by the same amount (we call this \"backflow\")\n        _backfillInboundAmount(internalAmount, recipientChain);\n\n        return _transfer(\n            sequence,\n            trimmedAmount,\n            recipientChain,\n            recipient,\n            refundAddress,\n            msg.sender,\n            transceiverInstructions\n        );\n    }\n\n    function _transfer(\n        uint64 sequence,\n        TrimmedAmount amount,\n        uint16 recipientChain,\n        bytes32 recipient,\n        bytes32 refundAddress,\n        address sender,\n        bytes memory transceiverInstructions\n    ) internal returns (uint64 msgSequence) {\n        // verify chain has not forked\n        checkFork(evmChainId);\n\n        (\n            address[] memory enabledTransceivers,\n            TransceiverStructs.TransceiverInstruction[] memory instructions,\n            uint256[] memory priceQuotes,\n            uint256 totalPriceQuote\n        ) = _prepareForTransfer(recipientChain, transceiverInstructions);\n\n        // push it on the stack again to avoid a stack too deep error\n        uint64 seq = sequence;\n\n        TransceiverStructs.NativeTokenTransfer memory ntt = TransceiverStructs.NativeTokenTransfer(\n            amount, toWormholeFormat(token), recipient, recipientChain\n        );\n\n        // construct the NttManagerMessage payload\n        bytes memory encodedNttManagerPayload = TransceiverStructs.encodeNttManagerMessage(\n            TransceiverStructs.NttManagerMessage(\n                bytes32(uint256(seq)),\n                toWormholeFormat(sender),\n                TransceiverStructs.encodeNativeTokenTransfer(ntt)\n            )\n        );\n\n        // push onto the stack again to avoid stack too deep error\n        uint16 destinationChain = recipientChain;\n\n        // send the message\n        _sendMessageToTransceivers(\n            recipientChain,\n            refundAddress,\n            _getPeersStorage()[destinationChain].peerAddress,\n            priceQuotes,\n            instructions,\n            enabledTransceivers,\n            encodedNttManagerPayload\n        );\n\n        // push it on the stack again to avoid a stack too deep error\n        TrimmedAmount amt = amount;\n\n        emit TransferSent(\n            recipient,\n            refundAddress,\n            amt.untrim(tokenDecimals()),\n            totalPriceQuote,\n            destinationChain,\n            seq\n        );\n\n        // return the sequence number\n        return seq;\n    }\n\n    function _mintOrUnlockToRecipient(\n        bytes32 digest,\n        address recipient,\n        TrimmedAmount amount,\n        bool cancelled\n    ) internal {\n        // verify chain has not forked\n        checkFork(evmChainId);\n\n        // calculate proper amount of tokens to unlock/mint to recipient\n        // untrim the amount\n        uint256 untrimmedAmount = amount.untrim(tokenDecimals());\n\n        if (cancelled) {\n            emit OutboundTransferCancelled(uint256(digest), recipient, untrimmedAmount);\n        } else {\n            emit TransferRedeemed(digest);\n        }\n\n        if (mode == Mode.LOCKING) {\n            // unlock tokens to the specified recipient\n            IERC20(token).safeTransfer(recipient, untrimmedAmount);\n        } else if (mode == Mode.BURNING) {\n            // mint tokens to the specified recipient\n            INttToken(token).mint(recipient, untrimmedAmount);\n        } else {\n            revert InvalidMode(uint8(mode));\n        }\n    }\n\n    function tokenDecimals() public view override(INttManager, RateLimiter) returns (uint8) {\n        (bool success, bytes memory queriedDecimals) =\n            token.staticcall(abi.encodeWithSignature(\"decimals()\"));\n\n        if (!success) {\n            revert StaticcallFailed();\n        }\n\n        return abi.decode(queriedDecimals, (uint8));\n    }\n\n    // ==================== Internal Helpers ===============================================\n\n    /// @dev Verify that the peer address saved for `sourceChainId` matches the `peerAddress`.\n    function _verifyPeer(uint16 sourceChainId, bytes32 peerAddress) internal view {\n        if (_getPeersStorage()[sourceChainId].peerAddress != peerAddress) {\n            revert InvalidPeer(sourceChainId, peerAddress);\n        }\n    }\n\n    function _trimTransferAmount(\n        uint256 amount,\n        uint16 toChain\n    ) internal view returns (TrimmedAmount) {\n        uint8 toDecimals = _getPeersStorage()[toChain].tokenDecimals;\n\n        if (toDecimals == 0) {\n            revert InvalidPeerDecimals();\n        }\n\n        TrimmedAmount trimmedAmount;\n        {\n            uint8 fromDecimals = tokenDecimals();\n            trimmedAmount = amount.trim(fromDecimals, toDecimals);\n            // don't deposit dust that can not be bridged due to the decimal shift\n            uint256 newAmount = trimmedAmount.untrim(fromDecimals);\n            if (amount != newAmount) {\n                revert TransferAmountHasDust(amount, amount - newAmount);\n            }\n        }\n\n        return trimmedAmount;\n    }\n\n    function _getTokenBalanceOf(\n        address tokenAddr,\n        address accountAddr\n    ) internal view returns (uint256) {\n        (bool success, bytes memory queriedBalance) =\n            tokenAddr.staticcall(abi.encodeWithSelector(IERC20.balanceOf.selector, accountAddr));\n\n        if (!success) {\n            revert StaticcallFailed();\n        }\n\n        return abi.decode(queriedBalance, (uint256));\n    }\n}\n"
      },
      "lib/openzeppelin-contracts/contracts/token/ERC20/IERC20.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC20/IERC20.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Interface of the ERC20 standard as defined in the EIP.\n */\ninterface IERC20 {\n    /**\n     * @dev Emitted when `value` tokens are moved from one account (`from`) to\n     * another (`to`).\n     *\n     * Note that `value` may be zero.\n     */\n    event Transfer(address indexed from, address indexed to, uint256 value);\n\n    /**\n     * @dev Emitted when the allowance of a `spender` for an `owner` is set by\n     * a call to {approve}. `value` is the new allowance.\n     */\n    event Approval(address indexed owner, address indexed spender, uint256 value);\n\n    /**\n     * @dev Returns the amount of tokens in existence.\n     */\n    function totalSupply() external view returns (uint256);\n\n    /**\n     * @dev Returns the amount of tokens owned by `account`.\n     */\n    function balanceOf(address account) external view returns (uint256);\n\n    /**\n     * @dev Moves `amount` tokens from the caller's account to `to`.\n     *\n     * Returns a boolean value indicating whether the operation succeeded.\n     *\n     * Emits a {Transfer} event.\n     */\n    function transfer(address to, uint256 amount) external returns (bool);\n\n    /**\n     * @dev Returns the remaining number of tokens that `spender` will be\n     * allowed to spend on behalf of `owner` through {transferFrom}. This is\n     * zero by default.\n     *\n     * This value changes when {approve} or {transferFrom} are called.\n     */\n    function allowance(address owner, address spender) external view returns (uint256);\n\n    /**\n     * @dev Sets `amount` as the allowance of `spender` over the caller's tokens.\n     *\n     * Returns a boolean value indicating whether the operation succeeded.\n     *\n     * IMPORTANT: Beware that changing an allowance with this method brings the risk\n     * that someone may use both the old and the new allowance by unfortunate\n     * transaction ordering. One possible solution to mitigate this race\n     * condition is to first reduce the spender's allowance to 0 and set the\n     * desired value afterwards:\n     * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729\n     *\n     * Emits an {Approval} event.\n     */\n    function approve(address spender, uint256 amount) external returns (bool);\n\n    /**\n     * @dev Moves `amount` tokens from `from` to `to` using the\n     * allowance mechanism. `amount` is then deducted from the caller's\n     * allowance.\n     *\n     * Returns a boolean value indicating whether the operation succeeded.\n     *\n     * Emits a {Transfer} event.\n     */\n    function transferFrom(\n        address from,\n        address to,\n        uint256 amount\n    ) external returns (bool);\n}\n"
      },
      "lib/openzeppelin-contracts/contracts/token/ERC20/utils/SafeERC20.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (token/ERC20/utils/SafeERC20.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../IERC20.sol\";\nimport \"../extensions/draft-IERC20Permit.sol\";\nimport \"../../../utils/Address.sol\";\n\n/**\n * @title SafeERC20\n * @dev Wrappers around ERC20 operations that throw on failure (when the token\n * contract returns false). Tokens that return no value (and instead revert or\n * throw on failure) are also supported, non-reverting calls are assumed to be\n * successful.\n * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract,\n * which allows you to call the safe operations as `token.safeTransfer(...)`, etc.\n */\nlibrary SafeERC20 {\n    using Address for address;\n\n    function safeTransfer(\n        IERC20 token,\n        address to,\n        uint256 value\n    ) internal {\n        _callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value));\n    }\n\n    function safeTransferFrom(\n        IERC20 token,\n        address from,\n        address to,\n        uint256 value\n    ) internal {\n        _callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value));\n    }\n\n    /**\n     * @dev Deprecated. This function has issues similar to the ones found in\n     * {IERC20-approve}, and its usage is discouraged.\n     *\n     * Whenever possible, use {safeIncreaseAllowance} and\n     * {safeDecreaseAllowance} instead.\n     */\n    function safeApprove(\n        IERC20 token,\n        address spender,\n        uint256 value\n    ) internal {\n        // safeApprove should only be called when setting an initial allowance,\n        // or when resetting it to zero. To increase and decrease it, use\n        // 'safeIncreaseAllowance' and 'safeDecreaseAllowance'\n        require(\n            (value == 0) || (token.allowance(address(this), spender) == 0),\n            \"SafeERC20: approve from non-zero to non-zero allowance\"\n        );\n        _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value));\n    }\n\n    function safeIncreaseAllowance(\n        IERC20 token,\n        address spender,\n        uint256 value\n    ) internal {\n        uint256 newAllowance = token.allowance(address(this), spender) + value;\n        _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));\n    }\n\n    function safeDecreaseAllowance(\n        IERC20 token,\n        address spender,\n        uint256 value\n    ) internal {\n        unchecked {\n            uint256 oldAllowance = token.allowance(address(this), spender);\n            require(oldAllowance >= value, \"SafeERC20: decreased allowance below zero\");\n            uint256 newAllowance = oldAllowance - value;\n            _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));\n        }\n    }\n\n    function safePermit(\n        IERC20Permit token,\n        address owner,\n        address spender,\n        uint256 value,\n        uint256 deadline,\n        uint8 v,\n        bytes32 r,\n        bytes32 s\n    ) internal {\n        uint256 nonceBefore = token.nonces(owner);\n        token.permit(owner, spender, value, deadline, v, r, s);\n        uint256 nonceAfter = token.nonces(owner);\n        require(nonceAfter == nonceBefore + 1, \"SafeERC20: permit did not succeed\");\n    }\n\n    /**\n     * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement\n     * on the return value: the return value is optional (but if data is returned, it must not be false).\n     * @param token The token targeted by the call.\n     * @param data The call data (encoded using abi.encode or one of its variants).\n     */\n    function _callOptionalReturn(IERC20 token, bytes memory data) private {\n        // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since\n        // we're implementing it ourselves. We use {Address-functionCall} to perform this call, which verifies that\n        // the target address contains contract code and also asserts for success in the low-level call.\n\n        bytes memory returndata = address(token).functionCall(data, \"SafeERC20: low-level call failed\");\n        if (returndata.length > 0) {\n            // Return data is optional\n            require(abi.decode(returndata, (bool)), \"SafeERC20: ERC20 operation did not succeed\");\n        }\n    }\n}\n"
      },
      "lib/openzeppelin-contracts/contracts/token/ERC20/extensions/ERC20Burnable.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.5.0) (token/ERC20/extensions/ERC20Burnable.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../ERC20.sol\";\nimport \"../../../utils/Context.sol\";\n\n/**\n * @dev Extension of {ERC20} that allows token holders to destroy both their own\n * tokens and those that they have an allowance for, in a way that can be\n * recognized off-chain (via event analysis).\n */\nabstract contract ERC20Burnable is Context, ERC20 {\n    /**\n     * @dev Destroys `amount` tokens from the caller.\n     *\n     * See {ERC20-_burn}.\n     */\n    function burn(uint256 amount) public virtual {\n        _burn(_msgSender(), amount);\n    }\n\n    /**\n     * @dev Destroys `amount` tokens from `account`, deducting from the caller's\n     * allowance.\n     *\n     * See {ERC20-_burn} and {ERC20-allowance}.\n     *\n     * Requirements:\n     *\n     * - the caller must have allowance for ``accounts``'s tokens of at least\n     * `amount`.\n     */\n    function burnFrom(address account, uint256 amount) public virtual {\n        _spendAllowance(account, _msgSender(), amount);\n        _burn(account, amount);\n    }\n}\n"
      },
      "lib/wormhole-solidity-sdk/src/Utils.sol": {
        "content": "\n// SPDX-License-Identifier: Apache 2\npragma solidity ^0.8.13;\n\nimport \"./interfaces/IWormholeRelayer.sol\";\n\nfunction toWormholeFormat(address addr) pure returns (bytes32) {\n    return bytes32(uint256(uint160(addr)));\n}\n\nfunction fromWormholeFormat(bytes32 whFormatAddress) pure returns (address) {\n    if (uint256(whFormatAddress) >> 160 != 0) {\n        revert NotAnEvmAddress(whFormatAddress);\n    }\n    return address(uint160(uint256(whFormatAddress)));\n}\n"
      },
      "lib/wormhole-solidity-sdk/src/libraries/BytesParsing.sol": {
        "content": "// SPDX-License-Identifier: Apache 2\npragma solidity ^0.8.13;\n\nlibrary BytesParsing {\n  uint256 private constant freeMemoryPtr = 0x40;\n  uint256 private constant wordSize = 32;\n\n  error OutOfBounds(uint256 offset, uint256 length);\n  error LengthMismatch(uint256 encodedLength, uint256 expectedLength);\n  error InvalidBoolVal(uint8 val);\n\n  function checkBound(uint offset, uint length) internal pure {\n    if (offset > length)\n      revert OutOfBounds(offset, length);\n  }\n\n  function checkLength(bytes memory encoded, uint256 expected) internal pure {\n    if (encoded.length != expected)\n      revert LengthMismatch(encoded.length, expected);\n  }\n\n  function sliceUnchecked(\n    bytes memory encoded,\n    uint offset,\n    uint length\n  ) internal pure returns (bytes memory ret, uint nextOffset) {\n    //bail early for degenerate case\n    if (length == 0)\n      return (new bytes(0), offset);\n\n    assembly (\"memory-safe\") {\n      nextOffset := add(offset, length)\n      ret := mload(freeMemoryPtr)\n\n      //Explanation on how we copy data here:\n      //  The bytes type has the following layout in memory:\n      //    [length: 32 bytes, data: length bytes]\n      //  So if we allocate `bytes memory foo = new bytes(1);` then `foo` will be a pointer to 33\n      //    bytes where the first 32 bytes contain the length and the last byte is the actual data.\n      //  Since mload always loads 32 bytes of memory at once, we use our shift variable to align\n      //    our reads so that our last read lines up exactly with the last 32 bytes of `encoded`.\n      //  However this also means that if the length of `encoded` is not a multiple of 32 bytes, our\n      //    first read will necessarily partly contain bytes from `encoded`'s 32 length bytes that\n      //    will be written into the length part of our `ret` slice.\n      //  We remedy this issue by writing the length of our `ret` slice at the end, thus\n      //    overwritting those garbage bytes.\n      let shift := and(length, 31) //equivalent to `mod(length, 32)` but 2 gas cheaper\n      if iszero(shift) {\n        shift := wordSize\n      }\n\n      let dest := add(ret, shift)\n      let end := add(dest, length)\n      for {\n        let src := add(add(encoded, shift), offset)\n      } lt(dest, end) {\n        src := add(src, wordSize)\n        dest := add(dest, wordSize)\n      } {\n        mstore(dest, mload(src))\n      }\n\n      mstore(ret, length)\n      //When compiling with --via-ir then normally allocated memory (i.e. via new) will have 32 byte\n      //  memory alignment and so we enforce the same memory alignment here.\n      mstore(freeMemoryPtr, and(add(dest, 31), not(31)))\n    }\n  }\n\n  function slice(\n    bytes memory encoded,\n    uint offset,\n    uint length\n  ) internal pure returns (bytes memory ret, uint nextOffset) {\n    (ret, nextOffset) = sliceUnchecked(encoded, offset, length);\n    checkBound(nextOffset, encoded.length);\n  }\n\n  function asAddressUnchecked(\n    bytes memory encoded,\n    uint offset\n  ) internal pure returns (address, uint) {\n    (uint160 ret, uint nextOffset) = asUint160Unchecked(encoded, offset);\n    return (address(ret), nextOffset);\n  }\n\n  function asAddress(\n    bytes memory encoded,\n    uint offset\n  ) internal pure returns (address ret, uint nextOffset) {\n    (ret, nextOffset) = asAddressUnchecked(encoded, offset);\n    checkBound(nextOffset, encoded.length);\n  }\n\n  function asBoolUnchecked(\n    bytes memory encoded,\n    uint offset\n  ) internal pure returns (bool, uint) {\n    (uint8 val, uint nextOffset) = asUint8Unchecked(encoded, offset);\n    if (val & 0xfe != 0)\n      revert InvalidBoolVal(val);\n\n    uint cleanedVal = uint(val);\n    bool ret;\n    //skip 2x iszero opcode\n    assembly (\"memory-safe\") {\n      ret := cleanedVal\n    }\n    return (ret, nextOffset);\n  }\n\n  function asBool(\n    bytes memory encoded,\n    uint offset\n  ) internal pure returns (bool ret, uint nextOffset) {\n    (ret, nextOffset) = asBoolUnchecked(encoded, offset);\n    checkBound(nextOffset, encoded.length);\n  }\n\n/* -------------------------------------------------------------------------------------------------\nRemaining library code below was auto-generated by via the following js/node code:\n\nfor (let bytes = 1; bytes <= 32; ++bytes) {\n  const bits = bytes*8;\n  console.log(\n`function asUint${bits}Unchecked(\n  bytes memory encoded,\n  uint offset\n) internal pure returns (uint${bits} ret, uint nextOffset) {\n  assembly (\"memory-safe\") {\n    nextOffset := add(offset, ${bytes})\n    ret := mload(add(encoded, nextOffset))\n  }\n  return (ret, nextOffset);\n}\n\nfunction asUint${bits}(\n  bytes memory encoded,\n  uint offset\n) internal pure returns (uint${bits} ret, uint nextOffset) {\n  (ret, nextOffset) = asUint${bits}Unchecked(encoded, offset);\n  checkBound(nextOffset, encoded.length);\n}\n\nfunction asBytes${bytes}Unchecked(\n  bytes memory encoded,\n  uint offset\n) internal pure returns (bytes${bytes}, uint) {\n  (uint${bits} ret, uint nextOffset) = asUint${bits}Unchecked(encoded, offset);\n  return (bytes${bytes}(ret), nextOffset);\n}\n\nfunction asBytes${bytes}(\n  bytes memory encoded,\n  uint offset\n) internal pure returns (bytes${bytes}, uint) {\n  (uint${bits} ret, uint nextOffset) = asUint${bits}(encoded, offset);\n  return (bytes${bytes}(ret), nextOffset);\n}\n`\n  );\n}\n------------------------------------------------------------------------------------------------- */\n\n  function asUint8Unchecked(\n    bytes memory encoded,\n    uint offset\n  ) internal pure returns (uint8 ret, uint nextOffset) {\n    assembly (\"memory-safe\") {\n      nextOffset := add(offset, 1)\n      ret := mload(add(encoded, nextOffset))\n    }\n    return (ret, nextOffset);\n  }\n\n  function asUint8(\n    bytes memory encoded,\n    uint offset\n  ) internal pure returns (uint8 ret, uint nextOffset) {\n    (ret, nextOffset) = asUint8Unchecked(encoded, offset);\n    checkBound(nextOffset, encoded.length);\n  }\n\n  function asBytes1Unchecked(\n    bytes memory encoded,\n    uint offset\n  ) internal pure returns (bytes1, uint) {\n    (uint8 ret, uint nextOffset) = asUint8Unchecked(encoded, offset);\n    return (bytes1(ret), nextOffset);\n  }\n\n  function asBytes1(\n    bytes memory encoded,\n    uint offset\n  ) internal pure returns (bytes1, uint) {\n    (uint8 ret, uint nextOffset) = asUint8(encoded, offset);\n    return (bytes1(ret), nextOffset);\n  }\n\n  function asUint16Unchecked(\n    bytes memory encoded,\n    uint offset\n  ) internal pure returns (uint16 ret, uint nextOffset) {\n    assembly (\"memory-safe\") {\n      nextOffset := add(offset, 2)\n      ret := mload(add(encoded, nextOffset))\n    }\n    return (ret, nextOffset);\n  }\n\n  function asUint16(\n    bytes memory encoded,\n    uint offset\n  ) internal pure returns (uint16 ret, uint nextOffset) {\n    (ret, nextOffset) = asUint16Unchecked(encoded, offset);\n    checkBound(nextOffset, encoded.length);\n  }\n\n  function asBytes2Unchecked(\n    bytes memory encoded,\n    uint offset\n  ) internal pure returns (bytes2, uint) {\n    (uint16 ret, uint nextOffset) = asUint16Unchecked(encoded, offset);\n    return (bytes2(ret), nextOffset);\n  }\n\n  function asBytes2(\n    bytes memory encoded,\n    uint offset\n  ) internal pure returns (bytes2, uint) {\n    (uint16 ret, uint nextOffset) = asUint16(encoded, offset);\n    return (bytes2(ret), nextOffset);\n  }\n\n  function asUint24Unchecked(\n    bytes memory encoded,\n    uint offset\n  ) internal pure returns (uint24 ret, uint nextOffset) {\n    assembly (\"memory-safe\") {\n      nextOffset := add(offset, 3)\n      ret := mload(add(encoded, nextOffset))\n    }\n    return (ret, nextOffset);\n  }\n\n  function asUint24(\n    bytes memory encoded,\n    uint offset\n  ) internal pure returns (uint24 ret, uint nextOffset) {\n    (ret, nextOffset) = asUint24Unchecked(encoded, offset);\n    checkBound(nextOffset, encoded.length);\n  }\n\n  function asBytes3Unchecked(\n    bytes memory encoded,\n    uint offset\n  ) internal pure returns (bytes3, uint) {\n    (uint24 ret, uint nextOffset) = asUint24Unchecked(encoded, offset);\n    return (bytes3(ret), nextOffset);\n  }\n\n  function asBytes3(\n    bytes memory encoded,\n    uint offset\n  ) internal pure returns (bytes3, uint) {\n    (uint24 ret, uint nextOffset) = asUint24(encoded, offset);\n    return (bytes3(ret), nextOffset);\n  }\n\n  function asUint32Unchecked(\n    bytes memory encoded,\n    uint offset\n  ) internal pure returns (uint32 ret, uint nextOffset) {\n    assembly (\"memory-safe\") {\n      nextOffset := add(offset, 4)\n      ret := mload(add(encoded, nextOffset))\n    }\n    return (ret, nextOffset);\n  }\n\n  function asUint32(\n    bytes memory encoded,\n    uint offset\n  ) internal pure returns (uint32 ret, uint nextOffset) {\n    (ret, nextOffset) = asUint32Unchecked(encoded, offset);\n    checkBound(nextOffset, encoded.length);\n  }\n\n  function asBytes4Unchecked(\n    bytes memory encoded,\n    uint offset\n  ) internal pure returns (bytes4, uint) {\n    (uint32 ret, uint nextOffset) = asUint32Unchecked(encoded, offset);\n    return (bytes4(ret), nextOffset);\n  }\n\n  function asBytes4(\n    bytes memory encoded,\n    uint offset\n  ) internal pure returns (bytes4, uint) {\n    (uint32 ret, uint nextOffset) = asUint32(encoded, offset);\n    return (bytes4(ret), nextOffset);\n  }\n\n  function asUint40Unchecked(\n    bytes memory encoded,\n    uint offset\n  ) internal pure returns (uint40 ret, uint nextOffset) {\n    assembly (\"memory-safe\") {\n      nextOffset := add(offset, 5)\n      ret := mload(add(encoded, nextOffset))\n    }\n    return (ret, nextOffset);\n  }\n\n  function asUint40(\n    bytes memory encoded,\n    uint offset\n  ) internal pure returns (uint40 ret, uint nextOffset) {\n    (ret, nextOffset) = asUint40Unchecked(encoded, offset);\n    checkBound(nextOffset, encoded.length);\n  }\n\n  function asBytes5Unchecked(\n    bytes memory encoded,\n    uint offset\n  ) internal pure returns (bytes5, uint) {\n    (uint40 ret, uint nextOffset) = asUint40Unchecked(encoded, offset);\n    return (bytes5(ret), nextOffset);\n  }\n\n  function asBytes5(\n    bytes memory encoded,\n    uint offset\n  ) internal pure returns (bytes5, uint) {\n    (uint40 ret, uint nextOffset) = asUint40(encoded, offset);\n    return (bytes5(ret), nextOffset);\n  }\n\n  function asUint48Unchecked(\n    bytes memory encoded,\n    uint offset\n  ) internal pure returns (uint48 ret, uint nextOffset) {\n    assembly (\"memory-safe\") {\n      nextOffset := add(offset, 6)\n      ret := mload(add(encoded, nextOffset))\n    }\n    return (ret, nextOffset);\n  }\n\n  function asUint48(\n    bytes memory encoded,\n    uint offset\n  ) internal pure returns (uint48 ret, uint nextOffset) {\n    (ret, nextOffset) = asUint48Unchecked(encoded, offset);\n    checkBound(nextOffset, encoded.length);\n  }\n\n  function asBytes6Unchecked(\n    bytes memory encoded,\n    uint offset\n  ) internal pure returns (bytes6, uint) {\n    (uint48 ret, uint nextOffset) = asUint48Unchecked(encoded, offset);\n    return (bytes6(ret), nextOffset);\n  }\n\n  function asBytes6(\n    bytes memory encoded,\n    uint offset\n  ) internal pure returns (bytes6, uint) {\n    (uint48 ret, uint nextOffset) = asUint48(encoded, offset);\n    return (bytes6(ret), nextOffset);\n  }\n\n  function asUint56Unchecked(\n    bytes memory encoded,\n    uint offset\n  ) internal pure returns (uint56 ret, uint nextOffset) {\n    assembly (\"memory-safe\") {\n      nextOffset := add(offset, 7)\n      ret := mload(add(encoded, nextOffset))\n    }\n    return (ret, nextOffset);\n  }\n\n  function asUint56(\n    bytes memory encoded,\n    uint offset\n  ) internal pure returns (uint56 ret, uint nextOffset) {\n    (ret, nextOffset) = asUint56Unchecked(encoded, offset);\n    checkBound(nextOffset, encoded.length);\n  }\n\n  function asBytes7Unchecked(\n    bytes memory encoded,\n    uint offset\n  ) internal pure returns (bytes7, uint) {\n    (uint56 ret, uint nextOffset) = asUint56Unchecked(encoded, offset);\n    return (bytes7(ret), nextOffset);\n  }\n\n  function asBytes7(\n    bytes memory encoded,\n    uint offset\n  ) internal pure returns (bytes7, uint) {\n    (uint56 ret, uint nextOffset) = asUint56(encoded, offset);\n    return (bytes7(ret), nextOffset);\n  }\n\n  function asUint64Unchecked(\n    bytes memory encoded,\n    uint offset\n  ) internal pure returns (uint64 ret, uint nextOffset) {\n    assembly (\"memory-safe\") {\n      nextOffset := add(offset, 8)\n      ret := mload(add(encoded, nextOffset))\n    }\n    return (ret, nextOffset);\n  }\n\n  function asUint64(\n    bytes memory encoded,\n    uint offset\n  ) internal pure returns (uint64 ret, uint nextOffset) {\n    (ret, nextOffset) = asUint64Unchecked(encoded, offset);\n    checkBound(nextOffset, encoded.length);\n  }\n\n  function asBytes8Unchecked(\n    bytes memory encoded,\n    uint offset\n  ) internal pure returns (bytes8, uint) {\n    (uint64 ret, uint nextOffset) = asUint64Unchecked(encoded, offset);\n    return (bytes8(ret), nextOffset);\n  }\n\n  function asBytes8(\n    bytes memory encoded,\n    uint offset\n  ) internal pure returns (bytes8, uint) {\n    (uint64 ret, uint nextOffset) = asUint64(encoded, offset);\n    return (bytes8(ret), nextOffset);\n  }\n\n  function asUint72Unchecked(\n    bytes memory encoded,\n    uint offset\n  ) internal pure returns (uint72 ret, uint nextOffset) {\n    assembly (\"memory-safe\") {\n      nextOffset := add(offset, 9)\n      ret := mload(add(encoded, nextOffset))\n    }\n    return (ret, nextOffset);\n  }\n\n  function asUint72(\n    bytes memory encoded,\n    uint offset\n  ) internal pure returns (uint72 ret, uint nextOffset) {\n    (ret, nextOffset) = asUint72Unchecked(encoded, offset);\n    checkBound(nextOffset, encoded.length);\n  }\n\n  function asBytes9Unchecked(\n    bytes memory encoded,\n    uint offset\n  ) internal pure returns (bytes9, uint) {\n    (uint72 ret, uint nextOffset) = asUint72Unchecked(encoded, offset);\n    return (bytes9(ret), nextOffset);\n  }\n\n  function asBytes9(\n    bytes memory encoded,\n    uint offset\n  ) internal pure returns (bytes9, uint) {\n    (uint72 ret, uint nextOffset) = asUint72(encoded, offset);\n    return (bytes9(ret), nextOffset);\n  }\n\n  function asUint80Unchecked(\n    bytes memory encoded,\n    uint offset\n  ) internal pure returns (uint80 ret, uint nextOffset) {\n    assembly (\"memory-safe\") {\n      nextOffset := add(offset, 10)\n      ret := mload(add(encoded, nextOffset))\n    }\n    return (ret, nextOffset);\n  }\n\n  function asUint80(\n    bytes memory encoded,\n    uint offset\n  ) internal pure returns (uint80 ret, uint nextOffset) {\n    (ret, nextOffset) = asUint80Unchecked(encoded, offset);\n    checkBound(nextOffset, encoded.length);\n  }\n\n  function asBytes10Unchecked(\n    bytes memory encoded,\n    uint offset\n  ) internal pure returns (bytes10, uint) {\n    (uint80 ret, uint nextOffset) = asUint80Unchecked(encoded, offset);\n    return (bytes10(ret), nextOffset);\n  }\n\n  function asBytes10(\n    bytes memory encoded,\n    uint offset\n  ) internal pure returns (bytes10, uint) {\n    (uint80 ret, uint nextOffset) = asUint80(encoded, offset);\n    return (bytes10(ret), nextOffset);\n  }\n\n  function asUint88Unchecked(\n    bytes memory encoded,\n    uint offset\n  ) internal pure returns (uint88 ret, uint nextOffset) {\n    assembly (\"memory-safe\") {\n      nextOffset := add(offset, 11)\n      ret := mload(add(encoded, nextOffset))\n    }\n    return (ret, nextOffset);\n  }\n\n  function asUint88(\n    bytes memory encoded,\n    uint offset\n  ) internal pure returns (uint88 ret, uint nextOffset) {\n    (ret, nextOffset) = asUint88Unchecked(encoded, offset);\n    checkBound(nextOffset, encoded.length);\n  }\n\n  function asBytes11Unchecked(\n    bytes memory encoded,\n    uint offset\n  ) internal pure returns (bytes11, uint) {\n    (uint88 ret, uint nextOffset) = asUint88Unchecked(encoded, offset);\n    return (bytes11(ret), nextOffset);\n  }\n\n  function asBytes11(\n    bytes memory encoded,\n    uint offset\n  ) internal pure returns (bytes11, uint) {\n    (uint88 ret, uint nextOffset) = asUint88(encoded, offset);\n    return (bytes11(ret), nextOffset);\n  }\n\n  function asUint96Unchecked(\n    bytes memory encoded,\n    uint offset\n  ) internal pure returns (uint96 ret, uint nextOffset) {\n    assembly (\"memory-safe\") {\n      nextOffset := add(offset, 12)\n      ret := mload(add(encoded, nextOffset))\n    }\n    return (ret, nextOffset);\n  }\n\n  function asUint96(\n    bytes memory encoded,\n    uint offset\n  ) internal pure returns (uint96 ret, uint nextOffset) {\n    (ret, nextOffset) = asUint96Unchecked(encoded, offset);\n    checkBound(nextOffset, encoded.length);\n  }\n\n  function asBytes12Unchecked(\n    bytes memory encoded,\n    uint offset\n  ) internal pure returns (bytes12, uint) {\n    (uint96 ret, uint nextOffset) = asUint96Unchecked(encoded, offset);\n    return (bytes12(ret), nextOffset);\n  }\n\n  function asBytes12(\n    bytes memory encoded,\n    uint offset\n  ) internal pure returns (bytes12, uint) {\n    (uint96 ret, uint nextOffset) = asUint96(encoded, offset);\n    return (bytes12(ret), nextOffset);\n  }\n\n  function asUint104Unchecked(\n    bytes memory encoded,\n    uint offset\n  ) internal pure returns (uint104 ret, uint nextOffset) {\n    assembly (\"memory-safe\") {\n      nextOffset := add(offset, 13)\n      ret := mload(add(encoded, nextOffset))\n    }\n    return (ret, nextOffset);\n  }\n\n  function asUint104(\n    bytes memory encoded,\n    uint offset\n  ) internal pure returns (uint104 ret, uint nextOffset) {\n    (ret, nextOffset) = asUint104Unchecked(encoded, offset);\n    checkBound(nextOffset, encoded.length);\n  }\n\n  function asBytes13Unchecked(\n    bytes memory encoded,\n    uint offset\n  ) internal pure returns (bytes13, uint) {\n    (uint104 ret, uint nextOffset) = asUint104Unchecked(encoded, offset);\n    return (bytes13(ret), nextOffset);\n  }\n\n  function asBytes13(\n    bytes memory encoded,\n    uint offset\n  ) internal pure returns (bytes13, uint) {\n    (uint104 ret, uint nextOffset) = asUint104(encoded, offset);\n    return (bytes13(ret), nextOffset);\n  }\n\n  function asUint112Unchecked(\n    bytes memory encoded,\n    uint offset\n  ) internal pure returns (uint112 ret, uint nextOffset) {\n    assembly (\"memory-safe\") {\n      nextOffset := add(offset, 14)\n      ret := mload(add(encoded, nextOffset))\n    }\n    return (ret, nextOffset);\n  }\n\n  function asUint112(\n    bytes memory encoded,\n    uint offset\n  ) internal pure returns (uint112 ret, uint nextOffset) {\n    (ret, nextOffset) = asUint112Unchecked(encoded, offset);\n    checkBound(nextOffset, encoded.length);\n  }\n\n  function asBytes14Unchecked(\n    bytes memory encoded,\n    uint offset\n  ) internal pure returns (bytes14, uint) {\n    (uint112 ret, uint nextOffset) = asUint112Unchecked(encoded, offset);\n    return (bytes14(ret), nextOffset);\n  }\n\n  function asBytes14(\n    bytes memory encoded,\n    uint offset\n  ) internal pure returns (bytes14, uint) {\n    (uint112 ret, uint nextOffset) = asUint112(encoded, offset);\n    return (bytes14(ret), nextOffset);\n  }\n\n  function asUint120Unchecked(\n    bytes memory encoded,\n    uint offset\n  ) internal pure returns (uint120 ret, uint nextOffset) {\n    assembly (\"memory-safe\") {\n      nextOffset := add(offset, 15)\n      ret := mload(add(encoded, nextOffset))\n    }\n    return (ret, nextOffset);\n  }\n\n  function asUint120(\n    bytes memory encoded,\n    uint offset\n  ) internal pure returns (uint120 ret, uint nextOffset) {\n    (ret, nextOffset) = asUint120Unchecked(encoded, offset);\n    checkBound(nextOffset, encoded.length);\n  }\n\n  function asBytes15Unchecked(\n    bytes memory encoded,\n    uint offset\n  ) internal pure returns (bytes15, uint) {\n    (uint120 ret, uint nextOffset) = asUint120Unchecked(encoded, offset);\n    return (bytes15(ret), nextOffset);\n  }\n\n  function asBytes15(\n    bytes memory encoded,\n    uint offset\n  ) internal pure returns (bytes15, uint) {\n    (uint120 ret, uint nextOffset) = asUint120(encoded, offset);\n    return (bytes15(ret), nextOffset);\n  }\n\n  function asUint128Unchecked(\n    bytes memory encoded,\n    uint offset\n  ) internal pure returns (uint128 ret, uint nextOffset) {\n    assembly (\"memory-safe\") {\n      nextOffset := add(offset, 16)\n      ret := mload(add(encoded, nextOffset))\n    }\n    return (ret, nextOffset);\n  }\n\n  function asUint128(\n    bytes memory encoded,\n    uint offset\n  ) internal pure returns (uint128 ret, uint nextOffset) {\n    (ret, nextOffset) = asUint128Unchecked(encoded, offset);\n    checkBound(nextOffset, encoded.length);\n  }\n\n  function asBytes16Unchecked(\n    bytes memory encoded,\n    uint offset\n  ) internal pure returns (bytes16, uint) {\n    (uint128 ret, uint nextOffset) = asUint128Unchecked(encoded, offset);\n    return (bytes16(ret), nextOffset);\n  }\n\n  function asBytes16(\n    bytes memory encoded,\n    uint offset\n  ) internal pure returns (bytes16, uint) {\n    (uint128 ret, uint nextOffset) = asUint128(encoded, offset);\n    return (bytes16(ret), nextOffset);\n  }\n\n  function asUint136Unchecked(\n    bytes memory encoded,\n    uint offset\n  ) internal pure returns (uint136 ret, uint nextOffset) {\n    assembly (\"memory-safe\") {\n      nextOffset := add(offset, 17)\n      ret := mload(add(encoded, nextOffset))\n    }\n    return (ret, nextOffset);\n  }\n\n  function asUint136(\n    bytes memory encoded,\n    uint offset\n  ) internal pure returns (uint136 ret, uint nextOffset) {\n    (ret, nextOffset) = asUint136Unchecked(encoded, offset);\n    checkBound(nextOffset, encoded.length);\n  }\n\n  function asBytes17Unchecked(\n    bytes memory encoded,\n    uint offset\n  ) internal pure returns (bytes17, uint) {\n    (uint136 ret, uint nextOffset) = asUint136Unchecked(encoded, offset);\n    return (bytes17(ret), nextOffset);\n  }\n\n  function asBytes17(\n    bytes memory encoded,\n    uint offset\n  ) internal pure returns (bytes17, uint) {\n    (uint136 ret, uint nextOffset) = asUint136(encoded, offset);\n    return (bytes17(ret), nextOffset);\n  }\n\n  function asUint144Unchecked(\n    bytes memory encoded,\n    uint offset\n  ) internal pure returns (uint144 ret, uint nextOffset) {\n    assembly (\"memory-safe\") {\n      nextOffset := add(offset, 18)\n      ret := mload(add(encoded, nextOffset))\n    }\n    return (ret, nextOffset);\n  }\n\n  function asUint144(\n    bytes memory encoded,\n    uint offset\n  ) internal pure returns (uint144 ret, uint nextOffset) {\n    (ret, nextOffset) = asUint144Unchecked(encoded, offset);\n    checkBound(nextOffset, encoded.length);\n  }\n\n  function asBytes18Unchecked(\n    bytes memory encoded,\n    uint offset\n  ) internal pure returns (bytes18, uint) {\n    (uint144 ret, uint nextOffset) = asUint144Unchecked(encoded, offset);\n    return (bytes18(ret), nextOffset);\n  }\n\n  function asBytes18(\n    bytes memory encoded,\n    uint offset\n  ) internal pure returns (bytes18, uint) {\n    (uint144 ret, uint nextOffset) = asUint144(encoded, offset);\n    return (bytes18(ret), nextOffset);\n  }\n\n  function asUint152Unchecked(\n    bytes memory encoded,\n    uint offset\n  ) internal pure returns (uint152 ret, uint nextOffset) {\n    assembly (\"memory-safe\") {\n      nextOffset := add(offset, 19)\n      ret := mload(add(encoded, nextOffset))\n    }\n    return (ret, nextOffset);\n  }\n\n  function asUint152(\n    bytes memory encoded,\n    uint offset\n  ) internal pure returns (uint152 ret, uint nextOffset) {\n    (ret, nextOffset) = asUint152Unchecked(encoded, offset);\n    checkBound(nextOffset, encoded.length);\n  }\n\n  function asBytes19Unchecked(\n    bytes memory encoded,\n    uint offset\n  ) internal pure returns (bytes19, uint) {\n    (uint152 ret, uint nextOffset) = asUint152Unchecked(encoded, offset);\n    return (bytes19(ret), nextOffset);\n  }\n\n  function asBytes19(\n    bytes memory encoded,\n    uint offset\n  ) internal pure returns (bytes19, uint) {\n    (uint152 ret, uint nextOffset) = asUint152(encoded, offset);\n    return (bytes19(ret), nextOffset);\n  }\n\n  function asUint160Unchecked(\n    bytes memory encoded,\n    uint offset\n  ) internal pure returns (uint160 ret, uint nextOffset) {\n    assembly (\"memory-safe\") {\n      nextOffset := add(offset, 20)\n      ret := mload(add(encoded, nextOffset))\n    }\n    return (ret, nextOffset);\n  }\n\n  function asUint160(\n    bytes memory encoded,\n    uint offset\n  ) internal pure returns (uint160 ret, uint nextOffset) {\n    (ret, nextOffset) = asUint160Unchecked(encoded, offset);\n    checkBound(nextOffset, encoded.length);\n  }\n\n  function asBytes20Unchecked(\n    bytes memory encoded,\n    uint offset\n  ) internal pure returns (bytes20, uint) {\n    (uint160 ret, uint nextOffset) = asUint160Unchecked(encoded, offset);\n    return (bytes20(ret), nextOffset);\n  }\n\n  function asBytes20(\n    bytes memory encoded,\n    uint offset\n  ) internal pure returns (bytes20, uint) {\n    (uint160 ret, uint nextOffset) = asUint160(encoded, offset);\n    return (bytes20(ret), nextOffset);\n  }\n\n  function asUint168Unchecked(\n    bytes memory encoded,\n    uint offset\n  ) internal pure returns (uint168 ret, uint nextOffset) {\n    assembly (\"memory-safe\") {\n      nextOffset := add(offset, 21)\n      ret := mload(add(encoded, nextOffset))\n    }\n    return (ret, nextOffset);\n  }\n\n  function asUint168(\n    bytes memory encoded,\n    uint offset\n  ) internal pure returns (uint168 ret, uint nextOffset) {\n    (ret, nextOffset) = asUint168Unchecked(encoded, offset);\n    checkBound(nextOffset, encoded.length);\n  }\n\n  function asBytes21Unchecked(\n    bytes memory encoded,\n    uint offset\n  ) internal pure returns (bytes21, uint) {\n    (uint168 ret, uint nextOffset) = asUint168Unchecked(encoded, offset);\n    return (bytes21(ret), nextOffset);\n  }\n\n  function asBytes21(\n    bytes memory encoded,\n    uint offset\n  ) internal pure returns (bytes21, uint) {\n    (uint168 ret, uint nextOffset) = asUint168(encoded, offset);\n    return (bytes21(ret), nextOffset);\n  }\n\n  function asUint176Unchecked(\n    bytes memory encoded,\n    uint offset\n  ) internal pure returns (uint176 ret, uint nextOffset) {\n    assembly (\"memory-safe\") {\n      nextOffset := add(offset, 22)\n      ret := mload(add(encoded, nextOffset))\n    }\n    return (ret, nextOffset);\n  }\n\n  function asUint176(\n    bytes memory encoded,\n    uint offset\n  ) internal pure returns (uint176 ret, uint nextOffset) {\n    (ret, nextOffset) = asUint176Unchecked(encoded, offset);\n    checkBound(nextOffset, encoded.length);\n  }\n\n  function asBytes22Unchecked(\n    bytes memory encoded,\n    uint offset\n  ) internal pure returns (bytes22, uint) {\n    (uint176 ret, uint nextOffset) = asUint176Unchecked(encoded, offset);\n    return (bytes22(ret), nextOffset);\n  }\n\n  function asBytes22(\n    bytes memory encoded,\n    uint offset\n  ) internal pure returns (bytes22, uint) {\n    (uint176 ret, uint nextOffset) = asUint176(encoded, offset);\n    return (bytes22(ret), nextOffset);\n  }\n\n  function asUint184Unchecked(\n    bytes memory encoded,\n    uint offset\n  ) internal pure returns (uint184 ret, uint nextOffset) {\n    assembly (\"memory-safe\") {\n      nextOffset := add(offset, 23)\n      ret := mload(add(encoded, nextOffset))\n    }\n    return (ret, nextOffset);\n  }\n\n  function asUint184(\n    bytes memory encoded,\n    uint offset\n  ) internal pure returns (uint184 ret, uint nextOffset) {\n    (ret, nextOffset) = asUint184Unchecked(encoded, offset);\n    checkBound(nextOffset, encoded.length);\n  }\n\n  function asBytes23Unchecked(\n    bytes memory encoded,\n    uint offset\n  ) internal pure returns (bytes23, uint) {\n    (uint184 ret, uint nextOffset) = asUint184Unchecked(encoded, offset);\n    return (bytes23(ret), nextOffset);\n  }\n\n  function asBytes23(\n    bytes memory encoded,\n    uint offset\n  ) internal pure returns (bytes23, uint) {\n    (uint184 ret, uint nextOffset) = asUint184(encoded, offset);\n    return (bytes23(ret), nextOffset);\n  }\n\n  function asUint192Unchecked(\n    bytes memory encoded,\n    uint offset\n  ) internal pure returns (uint192 ret, uint nextOffset) {\n    assembly (\"memory-safe\") {\n      nextOffset := add(offset, 24)\n      ret := mload(add(encoded, nextOffset))\n    }\n    return (ret, nextOffset);\n  }\n\n  function asUint192(\n    bytes memory encoded,\n    uint offset\n  ) internal pure returns (uint192 ret, uint nextOffset) {\n    (ret, nextOffset) = asUint192Unchecked(encoded, offset);\n    checkBound(nextOffset, encoded.length);\n  }\n\n  function asBytes24Unchecked(\n    bytes memory encoded,\n    uint offset\n  ) internal pure returns (bytes24, uint) {\n    (uint192 ret, uint nextOffset) = asUint192Unchecked(encoded, offset);\n    return (bytes24(ret), nextOffset);\n  }\n\n  function asBytes24(\n    bytes memory encoded,\n    uint offset\n  ) internal pure returns (bytes24, uint) {\n    (uint192 ret, uint nextOffset) = asUint192(encoded, offset);\n    return (bytes24(ret), nextOffset);\n  }\n\n  function asUint200Unchecked(\n    bytes memory encoded,\n    uint offset\n  ) internal pure returns (uint200 ret, uint nextOffset) {\n    assembly (\"memory-safe\") {\n      nextOffset := add(offset, 25)\n      ret := mload(add(encoded, nextOffset))\n    }\n    return (ret, nextOffset);\n  }\n\n  function asUint200(\n    bytes memory encoded,\n    uint offset\n  ) internal pure returns (uint200 ret, uint nextOffset) {\n    (ret, nextOffset) = asUint200Unchecked(encoded, offset);\n    checkBound(nextOffset, encoded.length);\n  }\n\n  function asBytes25Unchecked(\n    bytes memory encoded,\n    uint offset\n  ) internal pure returns (bytes25, uint) {\n    (uint200 ret, uint nextOffset) = asUint200Unchecked(encoded, offset);\n    return (bytes25(ret), nextOffset);\n  }\n\n  function asBytes25(\n    bytes memory encoded,\n    uint offset\n  ) internal pure returns (bytes25, uint) {\n    (uint200 ret, uint nextOffset) = asUint200(encoded, offset);\n    return (bytes25(ret), nextOffset);\n  }\n\n  function asUint208Unchecked(\n    bytes memory encoded,\n    uint offset\n  ) internal pure returns (uint208 ret, uint nextOffset) {\n    assembly (\"memory-safe\") {\n      nextOffset := add(offset, 26)\n      ret := mload(add(encoded, nextOffset))\n    }\n    return (ret, nextOffset);\n  }\n\n  function asUint208(\n    bytes memory encoded,\n    uint offset\n  ) internal pure returns (uint208 ret, uint nextOffset) {\n    (ret, nextOffset) = asUint208Unchecked(encoded, offset);\n    checkBound(nextOffset, encoded.length);\n  }\n\n  function asBytes26Unchecked(\n    bytes memory encoded,\n    uint offset\n  ) internal pure returns (bytes26, uint) {\n    (uint208 ret, uint nextOffset) = asUint208Unchecked(encoded, offset);\n    return (bytes26(ret), nextOffset);\n  }\n\n  function asBytes26(\n    bytes memory encoded,\n    uint offset\n  ) internal pure returns (bytes26, uint) {\n    (uint208 ret, uint nextOffset) = asUint208(encoded, offset);\n    return (bytes26(ret), nextOffset);\n  }\n\n  function asUint216Unchecked(\n    bytes memory encoded,\n    uint offset\n  ) internal pure returns (uint216 ret, uint nextOffset) {\n    assembly (\"memory-safe\") {\n      nextOffset := add(offset, 27)\n      ret := mload(add(encoded, nextOffset))\n    }\n    return (ret, nextOffset);\n  }\n\n  function asUint216(\n    bytes memory encoded,\n    uint offset\n  ) internal pure returns (uint216 ret, uint nextOffset) {\n    (ret, nextOffset) = asUint216Unchecked(encoded, offset);\n    checkBound(nextOffset, encoded.length);\n  }\n\n  function asBytes27Unchecked(\n    bytes memory encoded,\n    uint offset\n  ) internal pure returns (bytes27, uint) {\n    (uint216 ret, uint nextOffset) = asUint216Unchecked(encoded, offset);\n    return (bytes27(ret), nextOffset);\n  }\n\n  function asBytes27(\n    bytes memory encoded,\n    uint offset\n  ) internal pure returns (bytes27, uint) {\n    (uint216 ret, uint nextOffset) = asUint216(encoded, offset);\n    return (bytes27(ret), nextOffset);\n  }\n\n  function asUint224Unchecked(\n    bytes memory encoded,\n    uint offset\n  ) internal pure returns (uint224 ret, uint nextOffset) {\n    assembly (\"memory-safe\") {\n      nextOffset := add(offset, 28)\n      ret := mload(add(encoded, nextOffset))\n    }\n    return (ret, nextOffset);\n  }\n\n  function asUint224(\n    bytes memory encoded,\n    uint offset\n  ) internal pure returns (uint224 ret, uint nextOffset) {\n    (ret, nextOffset) = asUint224Unchecked(encoded, offset);\n    checkBound(nextOffset, encoded.length);\n  }\n\n  function asBytes28Unchecked(\n    bytes memory encoded,\n    uint offset\n  ) internal pure returns (bytes28, uint) {\n    (uint224 ret, uint nextOffset) = asUint224Unchecked(encoded, offset);\n    return (bytes28(ret), nextOffset);\n  }\n\n  function asBytes28(\n    bytes memory encoded,\n    uint offset\n  ) internal pure returns (bytes28, uint) {\n    (uint224 ret, uint nextOffset) = asUint224(encoded, offset);\n    return (bytes28(ret), nextOffset);\n  }\n\n  function asUint232Unchecked(\n    bytes memory encoded,\n    uint offset\n  ) internal pure returns (uint232 ret, uint nextOffset) {\n    assembly (\"memory-safe\") {\n      nextOffset := add(offset, 29)\n      ret := mload(add(encoded, nextOffset))\n    }\n    return (ret, nextOffset);\n  }\n\n  function asUint232(\n    bytes memory encoded,\n    uint offset\n  ) internal pure returns (uint232 ret, uint nextOffset) {\n    (ret, nextOffset) = asUint232Unchecked(encoded, offset);\n    checkBound(nextOffset, encoded.length);\n  }\n\n  function asBytes29Unchecked(\n    bytes memory encoded,\n    uint offset\n  ) internal pure returns (bytes29, uint) {\n    (uint232 ret, uint nextOffset) = asUint232Unchecked(encoded, offset);\n    return (bytes29(ret), nextOffset);\n  }\n\n  function asBytes29(\n    bytes memory encoded,\n    uint offset\n  ) internal pure returns (bytes29, uint) {\n    (uint232 ret, uint nextOffset) = asUint232(encoded, offset);\n    return (bytes29(ret), nextOffset);\n  }\n\n  function asUint240Unchecked(\n    bytes memory encoded,\n    uint offset\n  ) internal pure returns (uint240 ret, uint nextOffset) {\n    assembly (\"memory-safe\") {\n      nextOffset := add(offset, 30)\n      ret := mload(add(encoded, nextOffset))\n    }\n    return (ret, nextOffset);\n  }\n\n  function asUint240(\n    bytes memory encoded,\n    uint offset\n  ) internal pure returns (uint240 ret, uint nextOffset) {\n    (ret, nextOffset) = asUint240Unchecked(encoded, offset);\n    checkBound(nextOffset, encoded.length);\n  }\n\n  function asBytes30Unchecked(\n    bytes memory encoded,\n    uint offset\n  ) internal pure returns (bytes30, uint) {\n    (uint240 ret, uint nextOffset) = asUint240Unchecked(encoded, offset);\n    return (bytes30(ret), nextOffset);\n  }\n\n  function asBytes30(\n    bytes memory encoded,\n    uint offset\n  ) internal pure returns (bytes30, uint) {\n    (uint240 ret, uint nextOffset) = asUint240(encoded, offset);\n    return (bytes30(ret), nextOffset);\n  }\n\n  function asUint248Unchecked(\n    bytes memory encoded,\n    uint offset\n  ) internal pure returns (uint248 ret, uint nextOffset) {\n    assembly (\"memory-safe\") {\n      nextOffset := add(offset, 31)\n      ret := mload(add(encoded, nextOffset))\n    }\n    return (ret, nextOffset);\n  }\n\n  function asUint248(\n    bytes memory encoded,\n    uint offset\n  ) internal pure returns (uint248 ret, uint nextOffset) {\n    (ret, nextOffset) = asUint248Unchecked(encoded, offset);\n    checkBound(nextOffset, encoded.length);\n  }\n\n  function asBytes31Unchecked(\n    bytes memory encoded,\n    uint offset\n  ) internal pure returns (bytes31, uint) {\n    (uint248 ret, uint nextOffset) = asUint248Unchecked(encoded, offset);\n    return (bytes31(ret), nextOffset);\n  }\n\n  function asBytes31(\n    bytes memory encoded,\n    uint offset\n  ) internal pure returns (bytes31, uint) {\n    (uint248 ret, uint nextOffset) = asUint248(encoded, offset);\n    return (bytes31(ret), nextOffset);\n  }\n\n  function asUint256Unchecked(\n    bytes memory encoded,\n    uint offset\n  ) internal pure returns (uint256 ret, uint nextOffset) {\n    assembly (\"memory-safe\") {\n      nextOffset := add(offset, 32)\n      ret := mload(add(encoded, nextOffset))\n    }\n    return (ret, nextOffset);\n  }\n\n  function asUint256(\n    bytes memory encoded,\n    uint offset\n  ) internal pure returns (uint256 ret, uint nextOffset) {\n    (ret, nextOffset) = asUint256Unchecked(encoded, offset);\n    checkBound(nextOffset, encoded.length);\n  }\n\n  function asBytes32Unchecked(\n    bytes memory encoded,\n    uint offset\n  ) internal pure returns (bytes32, uint) {\n    (uint256 ret, uint nextOffset) = asUint256Unchecked(encoded, offset);\n    return (bytes32(ret), nextOffset);\n  }\n\n  function asBytes32(\n    bytes memory encoded,\n    uint offset\n  ) internal pure returns (bytes32, uint) {\n    (uint256 ret, uint nextOffset) = asUint256(encoded, offset);\n    return (bytes32(ret), nextOffset);\n  }\n}\n"
      },
      "src/libraries/RateLimiter.sol": {
        "content": "// SPDX-License-Identifier: Apache 2\npragma solidity >=0.8.8 <0.9.0;\n\nimport \"../interfaces/IRateLimiter.sol\";\nimport \"../interfaces/IRateLimiterEvents.sol\";\nimport \"./TransceiverHelpers.sol\";\nimport \"./TransceiverStructs.sol\";\nimport \"../libraries/TrimmedAmount.sol\";\nimport \"openzeppelin-contracts/contracts/utils/math/SafeCast.sol\";\n\nabstract contract RateLimiter is IRateLimiter, IRateLimiterEvents {\n    using TrimmedAmountLib for TrimmedAmount;\n\n    /// @dev The duration (in seconds) it takes for the limits to fully replenish.\n    uint64 public immutable rateLimitDuration;\n\n    /// =============== STORAGE ===============================================\n\n    bytes32 private constant OUTBOUND_LIMIT_PARAMS_SLOT =\n        bytes32(uint256(keccak256(\"ntt.outboundLimitParams\")) - 1);\n\n    bytes32 private constant OUTBOUND_QUEUE_SLOT =\n        bytes32(uint256(keccak256(\"ntt.outboundQueue\")) - 1);\n\n    bytes32 private constant INBOUND_LIMIT_PARAMS_SLOT =\n        bytes32(uint256(keccak256(\"ntt.inboundLimitParams\")) - 1);\n\n    bytes32 private constant INBOUND_QUEUE_SLOT =\n        bytes32(uint256(keccak256(\"ntt.inboundQueue\")) - 1);\n\n    function _getOutboundLimitParamsStorage() internal pure returns (RateLimitParams storage $) {\n        uint256 slot = uint256(OUTBOUND_LIMIT_PARAMS_SLOT);\n        assembly (\"memory-safe\") {\n            $.slot := slot\n        }\n    }\n\n    function _getOutboundQueueStorage()\n        internal\n        pure\n        returns (mapping(uint64 => OutboundQueuedTransfer) storage $)\n    {\n        uint256 slot = uint256(OUTBOUND_QUEUE_SLOT);\n        assembly (\"memory-safe\") {\n            $.slot := slot\n        }\n    }\n\n    function _getInboundLimitParamsStorage()\n        internal\n        pure\n        returns (mapping(uint16 => RateLimitParams) storage $)\n    {\n        uint256 slot = uint256(INBOUND_LIMIT_PARAMS_SLOT);\n        assembly (\"memory-safe\") {\n            $.slot := slot\n        }\n    }\n\n    function _getInboundQueueStorage()\n        internal\n        pure\n        returns (mapping(bytes32 => InboundQueuedTransfer) storage $)\n    {\n        uint256 slot = uint256(INBOUND_QUEUE_SLOT);\n        assembly (\"memory-safe\") {\n            $.slot := slot\n        }\n    }\n\n    constructor(uint64 _rateLimitDuration, bool _skipRateLimiting) {\n        if (\n            _rateLimitDuration == 0 && !_skipRateLimiting\n                || _rateLimitDuration != 0 && _skipRateLimiting\n        ) {\n            revert UndefinedRateLimiting();\n        }\n\n        rateLimitDuration = _rateLimitDuration;\n    }\n\n    function _setLimit(TrimmedAmount limit, RateLimitParams storage rateLimitParams) internal {\n        TrimmedAmount oldLimit = rateLimitParams.limit;\n        if (oldLimit.isNull()) {\n            rateLimitParams.currentCapacity = limit;\n        } else {\n            TrimmedAmount currentCapacity = _getCurrentCapacity(rateLimitParams);\n            rateLimitParams.currentCapacity =\n                _calculateNewCurrentCapacity(limit, oldLimit, currentCapacity);\n        }\n        rateLimitParams.limit = limit;\n\n        rateLimitParams.lastTxTimestamp = uint64(block.timestamp);\n    }\n\n    function _setOutboundLimit(TrimmedAmount limit) internal {\n        _setLimit(limit, _getOutboundLimitParamsStorage());\n    }\n\n    function getOutboundLimitParams() public pure returns (RateLimitParams memory) {\n        return _getOutboundLimitParamsStorage();\n    }\n\n    function getCurrentOutboundCapacity() public view returns (uint256) {\n        TrimmedAmount trimmedCapacity = _getCurrentCapacity(getOutboundLimitParams());\n        uint8 decimals = tokenDecimals();\n        return trimmedCapacity.untrim(decimals);\n    }\n\n    function getOutboundQueuedTransfer(uint64 queueSequence)\n        public\n        view\n        returns (OutboundQueuedTransfer memory)\n    {\n        return _getOutboundQueueStorage()[queueSequence];\n    }\n\n    function _setInboundLimit(TrimmedAmount limit, uint16 chainId_) internal {\n        _setLimit(limit, _getInboundLimitParamsStorage()[chainId_]);\n    }\n\n    function getInboundLimitParams(uint16 chainId_) public view returns (RateLimitParams memory) {\n        return _getInboundLimitParamsStorage()[chainId_];\n    }\n\n    function getCurrentInboundCapacity(uint16 chainId_) public view returns (uint256) {\n        TrimmedAmount trimmedCapacity = _getCurrentCapacity(getInboundLimitParams(chainId_));\n        uint8 decimals = tokenDecimals();\n        return trimmedCapacity.untrim(decimals);\n    }\n\n    function getInboundQueuedTransfer(bytes32 digest)\n        public\n        view\n        returns (InboundQueuedTransfer memory)\n    {\n        return _getInboundQueueStorage()[digest];\n    }\n\n    /**\n     * @dev Gets the current capacity for a parameterized rate limits struct\n     */\n    function _getCurrentCapacity(RateLimitParams memory rateLimitParams)\n        internal\n        view\n        returns (TrimmedAmount capacity)\n    {\n        // If the rate limit duration is 0 then the rate limiter is skipped\n        if (rateLimitDuration == 0) {\n            return\n                packTrimmedAmount(type(uint64).max, rateLimitParams.currentCapacity.getDecimals());\n        }\n\n        // The capacity and rate limit are expressed as trimmed amounts, i.e.\n        // 64-bit unsigned integers. The following operations upcast the 64-bit\n        // unsigned integers to 256-bit unsigned integers to avoid overflow.\n        // Specifically, the calculatedCapacity can overflow the u64 max.\n        // For example, if the limit is uint64.max, then the multiplication in calculatedCapacity\n        // will overflow when timePassed is greater than rateLimitDuration.\n        // Operating on uint256 avoids this issue. The overflow is cancelled out by the min operation,\n        // whose second argument is a uint64, so the result can safely be downcast to a uint64.\n        unchecked {\n            uint256 timePassed = block.timestamp - rateLimitParams.lastTxTimestamp;\n            // Multiply (limit * timePassed), then divide by the duration.\n            // Dividing first has terrible numerical stability --\n            // when rateLimitDuration is close to the limit, there is significant rounding error.\n            // We are safe to multiply first, since these numbers are u64 TrimmedAmount types\n            // and we're performing arithmetic on u256 words.\n            uint256 calculatedCapacity = rateLimitParams.currentCapacity.getAmount()\n                + (rateLimitParams.limit.getAmount() * timePassed) / rateLimitDuration;\n\n            uint256 result = min(calculatedCapacity, rateLimitParams.limit.getAmount());\n            return packTrimmedAmount(\n                SafeCast.toUint64(result), rateLimitParams.currentCapacity.getDecimals()\n            );\n        }\n    }\n\n    /**\n     * @dev Updates the current capacity\n     *\n     * @param newLimit The new limit\n     * @param oldLimit The old limit\n     * @param currentCapacity The current capacity\n     */\n    function _calculateNewCurrentCapacity(\n        TrimmedAmount newLimit,\n        TrimmedAmount oldLimit,\n        TrimmedAmount currentCapacity\n    ) internal pure returns (TrimmedAmount newCurrentCapacity) {\n        TrimmedAmount difference;\n\n        if (oldLimit > newLimit) {\n            difference = oldLimit - newLimit;\n            newCurrentCapacity = currentCapacity > difference\n                ? currentCapacity - difference\n                : packTrimmedAmount(0, currentCapacity.getDecimals());\n        } else {\n            difference = newLimit - oldLimit;\n            newCurrentCapacity = currentCapacity + difference;\n        }\n\n        if (newCurrentCapacity > newLimit) {\n            revert CapacityCannotExceedLimit(newCurrentCapacity, newLimit);\n        }\n    }\n\n    function _consumeOutboundAmount(TrimmedAmount amount) internal {\n        if (rateLimitDuration == 0) return;\n        _consumeRateLimitAmount(\n            amount, _getCurrentCapacity(getOutboundLimitParams()), _getOutboundLimitParamsStorage()\n        );\n    }\n\n    function _backfillOutboundAmount(TrimmedAmount amount) internal {\n        if (rateLimitDuration == 0) return;\n        _backfillRateLimitAmount(\n            amount, _getCurrentCapacity(getOutboundLimitParams()), _getOutboundLimitParamsStorage()\n        );\n    }\n\n    function _consumeInboundAmount(TrimmedAmount amount, uint16 chainId_) internal {\n        if (rateLimitDuration == 0) return;\n        _consumeRateLimitAmount(\n            amount,\n            _getCurrentCapacity(getInboundLimitParams(chainId_)),\n            _getInboundLimitParamsStorage()[chainId_]\n        );\n    }\n\n    function _backfillInboundAmount(TrimmedAmount amount, uint16 chainId_) internal {\n        if (rateLimitDuration == 0) return;\n        _backfillRateLimitAmount(\n            amount,\n            _getCurrentCapacity(getInboundLimitParams(chainId_)),\n            _getInboundLimitParamsStorage()[chainId_]\n        );\n    }\n\n    function _consumeRateLimitAmount(\n        TrimmedAmount amount,\n        TrimmedAmount capacity,\n        RateLimitParams storage rateLimitParams\n    ) internal {\n        rateLimitParams.lastTxTimestamp = uint64(block.timestamp);\n        rateLimitParams.currentCapacity = capacity - amount;\n    }\n\n    /// @dev Refills the capacity by the given amount.\n    /// This is used to replenish the capacity via backflows.\n    function _backfillRateLimitAmount(\n        TrimmedAmount amount,\n        TrimmedAmount capacity,\n        RateLimitParams storage rateLimitParams\n    ) internal {\n        rateLimitParams.lastTxTimestamp = uint64(block.timestamp);\n        rateLimitParams.currentCapacity = capacity.saturatingAdd(amount).min(rateLimitParams.limit);\n    }\n\n    function _isOutboundAmountRateLimited(TrimmedAmount amount) internal view returns (bool) {\n        return rateLimitDuration != 0\n            ? _isAmountRateLimited(_getCurrentCapacity(getOutboundLimitParams()), amount)\n            : false;\n    }\n\n    function _isInboundAmountRateLimited(\n        TrimmedAmount amount,\n        uint16 chainId_\n    ) internal view returns (bool) {\n        return rateLimitDuration != 0\n            ? _isAmountRateLimited(_getCurrentCapacity(getInboundLimitParams(chainId_)), amount)\n            : false;\n    }\n\n    function _isAmountRateLimited(\n        TrimmedAmount capacity,\n        TrimmedAmount amount\n    ) internal pure returns (bool) {\n        return capacity < amount;\n    }\n\n    function _enqueueOutboundTransfer(\n        uint64 sequence,\n        TrimmedAmount amount,\n        uint16 recipientChain,\n        bytes32 recipient,\n        bytes32 refundAddress,\n        address senderAddress,\n        bytes memory transceiverInstructions\n    ) internal {\n        _getOutboundQueueStorage()[sequence] = OutboundQueuedTransfer({\n            amount: amount,\n            recipientChain: recipientChain,\n            recipient: recipient,\n            refundAddress: refundAddress,\n            txTimestamp: uint64(block.timestamp),\n            sender: senderAddress,\n            transceiverInstructions: transceiverInstructions\n        });\n\n        emit OutboundTransferQueued(sequence);\n    }\n\n    function _enqueueInboundTransfer(\n        bytes32 digest,\n        TrimmedAmount amount,\n        address recipient\n    ) internal {\n        _getInboundQueueStorage()[digest] = InboundQueuedTransfer({\n            amount: amount,\n            recipient: recipient,\n            txTimestamp: uint64(block.timestamp)\n        });\n\n        emit InboundTransferQueued(digest);\n    }\n\n    function tokenDecimals() public view virtual returns (uint8);\n}\n"
      },
      "src/interfaces/INttManager.sol": {
        "content": "// SPDX-License-Identifier: Apache 2\npragma solidity >=0.8.8 <0.9.0;\n\nimport \"../libraries/TrimmedAmount.sol\";\nimport \"../libraries/TransceiverStructs.sol\";\n\nimport \"./IManagerBase.sol\";\n\ninterface INttManager is IManagerBase {\n    /// @dev The peer on another chain.\n    struct NttManagerPeer {\n        bytes32 peerAddress;\n        uint8 tokenDecimals;\n    }\n\n    /// @notice Emitted when a message is sent from the nttManager.\n    /// @dev Topic0\n    ///      0xe54e51e42099622516fa3b48e9733581c9dbdcb771cafb093f745a0532a35982.\n    /// @param recipient The recipient of the message.\n    /// @param refundAddress The address on the destination chain to which the\n    ///                      refund of unused gas will be paid\n    /// @param amount The amount transferred.\n    /// @param fee The amount of ether sent along with the tx to cover the delivery fee.\n    /// @param recipientChain The chain ID of the recipient.\n    /// @param msgSequence The unique sequence ID of the message.\n    event TransferSent(\n        bytes32 recipient,\n        bytes32 refundAddress,\n        uint256 amount,\n        uint256 fee,\n        uint16 recipientChain,\n        uint64 msgSequence\n    );\n\n    /// @notice Emitted when the peer contract is updated.\n    /// @dev Topic0\n    ///      0x1456404e7f41f35c3daac941bb50bad417a66275c3040061b4287d787719599d.\n    /// @param chainId_ The chain ID of the peer contract.\n    /// @param oldPeerContract The old peer contract address.\n    /// @param oldPeerDecimals The old peer contract decimals.\n    /// @param peerContract The new peer contract address.\n    /// @param peerDecimals The new peer contract decimals.\n    event PeerUpdated(\n        uint16 indexed chainId_,\n        bytes32 oldPeerContract,\n        uint8 oldPeerDecimals,\n        bytes32 peerContract,\n        uint8 peerDecimals\n    );\n\n    /// @notice Emitted when a transfer has been redeemed\n    ///         (either minted or unlocked on the recipient chain).\n    /// @dev Topic0\n    ///      0x504e6efe18ab9eed10dc6501a417f5b12a2f7f2b1593aed9b89f9bce3cf29a91.\n    /// @param digest The digest of the message.\n    event TransferRedeemed(bytes32 indexed digest);\n\n    /// @notice Emitted when an outbound transfer has been cancelled\n    /// @dev Topic0\n    ///      0xf80e572ae1b63e2449629b6c7d783add85c36473926f216077f17ee002bcfd07.\n    /// @param sequence The sequence number being cancelled\n    /// @param recipient The canceller and recipient of the funds\n    /// @param amount The amount of the transfer being cancelled\n    event OutboundTransferCancelled(uint256 sequence, address recipient, uint256 amount);\n\n    /// @notice The transfer has some dust.\n    /// @dev Selector 0x71f0634a\n    /// @dev This is a security measure to prevent users from losing funds.\n    ///      This is the result of trimming the amount and then untrimming it.\n    /// @param  amount The amount to transfer.\n    error TransferAmountHasDust(uint256 amount, uint256 dust);\n\n    /// @notice The mode is invalid. It is neither in LOCKING or BURNING mode.\n    /// @dev Selector 0x66001a89\n    /// @param mode The mode.\n    error InvalidMode(uint8 mode);\n\n    /// @notice Error when trying to execute a message on an unintended target chain.\n    /// @dev Selector 0x3dcb204a.\n    /// @param targetChain The target chain.\n    /// @param thisChain The current chain.\n    error InvalidTargetChain(uint16 targetChain, uint16 thisChain);\n\n    /// @notice Error when the transfer amount is zero.\n    /// @dev Selector 0x9993626a.\n    error ZeroAmount();\n\n    /// @notice Error when the recipient is invalid.\n    /// @dev Selector 0x9c8d2cd2.\n    error InvalidRecipient();\n\n    /// @notice Error when the recipient is invalid.\n    /// @dev Selector 0xe2fe2726.\n    error InvalidRefundAddress();\n\n    /// @notice Error when the amount burned is different than the balance difference,\n    ///         since NTT does not support burn fees.\n    /// @dev Selector 0x02156a8f.\n    /// @param burnAmount The amount burned.\n    /// @param balanceDiff The balance after burning.\n    error BurnAmountDifferentThanBalanceDiff(uint256 burnAmount, uint256 balanceDiff);\n\n    /// @notice The caller is not the deployer.\n    error UnexpectedDeployer(address expectedOwner, address owner);\n\n    /// @notice Peer for the chain does not match the configuration.\n    /// @param chainId ChainId of the source chain.\n    /// @param peerAddress Address of the peer nttManager contract.\n    error InvalidPeer(uint16 chainId, bytes32 peerAddress);\n\n    /// @notice Peer chain ID cannot be zero.\n    error InvalidPeerChainIdZero();\n\n    /// @notice Peer cannot be the zero address.\n    error InvalidPeerZeroAddress();\n\n    /// @notice Peer cannot have zero decimals.\n    error InvalidPeerDecimals();\n\n    /// @notice Staticcall reverted\n    /// @dev Selector 0x1222cd83\n    error StaticcallFailed();\n\n    /// @notice Error when someone other than the original sender tries to cancel a queued outbound transfer.\n    /// @dev Selector 0xceb40a85.\n    /// @param canceller The address trying to cancel the transfer.\n    /// @param sender The original sender that initiated the transfer that was queued.\n    error CancellerNotSender(address canceller, address sender);\n\n    /// @notice An unexpected msg.value was passed with the call\n    /// @dev Selector 0xbd28e889.\n    error UnexpectedMsgValue();\n\n    /// @notice Peer cannot be on the same chain\n    /// @dev Selector 0x20371f2a.\n    error InvalidPeerSameChainId();\n\n    /// @notice Transfer a given amount to a recipient on a given chain. This function is called\n    ///         by the user to send the token cross-chain. This function will either lock or burn the\n    ///         sender's tokens. Finally, this function will call into registered `Endpoint` contracts\n    ///         to send a message with the incrementing sequence number and the token transfer payload.\n    /// @param amount The amount to transfer.\n    /// @param recipientChain The chain ID for the destination.\n    /// @param recipient The recipient address.\n    function transfer(\n        uint256 amount,\n        uint16 recipientChain,\n        bytes32 recipient\n    ) external payable returns (uint64 msgId);\n\n    /// @notice Transfer a given amount to a recipient on a given chain. This function is called\n    ///         by the user to send the token cross-chain. This function will either lock or burn the\n    ///         sender's tokens. Finally, this function will call into registered `Endpoint` contracts\n    ///         to send a message with the incrementing sequence number and the token transfer payload.\n    /// @dev Transfers are queued if the outbound limit is hit and must be completed by the client.\n    /// @param amount The amount to transfer.\n    /// @param recipientChain The chain ID for the destination.\n    /// @param recipient The recipient address.\n    /// @param refundAddress The address to which a refund for unussed gas is issued on the recipient chain.\n    /// @param shouldQueue Whether the transfer should be queued if the outbound limit is hit.\n    /// @param encodedInstructions Additional instructions to be forwarded to the recipient chain.\n    function transfer(\n        uint256 amount,\n        uint16 recipientChain,\n        bytes32 recipient,\n        bytes32 refundAddress,\n        bool shouldQueue,\n        bytes memory encodedInstructions\n    ) external payable returns (uint64 msgId);\n\n    /// @notice Complete an outbound transfer that's been queued.\n    /// @dev This method is called by the client to complete an outbound transfer that's been queued.\n    /// @param queueSequence The sequence of the message in the queue.\n    /// @return msgSequence The sequence of the message.\n    function completeOutboundQueuedTransfer(uint64 queueSequence)\n        external\n        payable\n        returns (uint64 msgSequence);\n\n    /// @notice Cancels an outbound transfer that's been queued.\n    /// @dev This method is called by the client to cancel an outbound transfer that's been queued.\n    /// @param queueSequence The sequence of the message in the queue.\n    function cancelOutboundQueuedTransfer(uint64 queueSequence) external;\n\n    /// @notice Complete an inbound queued transfer.\n    /// @param digest The digest of the message to complete.\n    function completeInboundQueuedTransfer(bytes32 digest) external;\n\n    /// @notice Called by an Endpoint contract to deliver a verified attestation.\n    /// @dev This function enforces attestation threshold and replay logic for messages. Once all\n    ///      validations are complete, this function calls `executeMsg` to execute the command specified\n    ///      by the message.\n    /// @param sourceChainId The chain id of the sender.\n    /// @param sourceNttManagerAddress The address of the sender's nttManager contract.\n    /// @param payload The VAA payload.\n    function attestationReceived(\n        uint16 sourceChainId,\n        bytes32 sourceNttManagerAddress,\n        TransceiverStructs.NttManagerMessage memory payload\n    ) external;\n\n    /// @notice Called after a message has been sufficiently verified to execute\n    ///         the command in the message. This function will decode the payload\n    ///         as an NttManagerMessage to extract the sequence, msgType, and other parameters.\n    /// @dev This function is exposed as a fallback for when an `Transceiver` is deregistered\n    ///      when a message is in flight.\n    /// @param sourceChainId The chain id of the sender.\n    /// @param sourceNttManagerAddress The address of the sender's nttManager contract.\n    /// @param message The message to execute.\n    function executeMsg(\n        uint16 sourceChainId,\n        bytes32 sourceNttManagerAddress,\n        TransceiverStructs.NttManagerMessage memory message\n    ) external;\n\n    /// @notice Returns the number of decimals of the token managed by the NttManager.\n    /// @return decimals The number of decimals of the token.\n    function tokenDecimals() external view returns (uint8);\n\n    /// @notice Returns registered peer contract for a given chain.\n    /// @param chainId_ chain ID.\n    function getPeer(uint16 chainId_) external view returns (NttManagerPeer memory);\n\n    /// @notice Sets the corresponding peer.\n    /// @dev The nttManager that executes the message sets the source nttManager as the peer.\n    /// @param peerChainId The chain ID of the peer.\n    /// @param peerContract The address of the peer nttManager contract.\n    /// @param decimals The number of decimals of the token on the peer chain.\n    /// @param inboundLimit The inbound rate limit for the peer chain id\n    function setPeer(\n        uint16 peerChainId,\n        bytes32 peerContract,\n        uint8 decimals,\n        uint256 inboundLimit\n    ) external;\n\n    /// @notice Sets the outbound transfer limit for a given chain.\n    /// @dev This method can only be executed by the `owner`.\n    /// @param limit The new outbound limit.\n    function setOutboundLimit(uint256 limit) external;\n\n    /// @notice Sets the inbound transfer limit for a given chain.\n    /// @dev This method can only be executed by the `owner`.\n    /// @param limit The new limit.\n    /// @param chainId The chain to set the limit for.\n    function setInboundLimit(uint256 limit, uint16 chainId) external;\n}\n"
      },
      "src/interfaces/INttToken.sol": {
        "content": "// SPDX-License-Identifier: Apache 2\npragma solidity >=0.8.8 <0.9.0;\n\ninterface INttToken {\n    /// @notice Error when the caller is not the minter.\n    /// @dev Selector 0x5fb5729e.\n    /// @param caller The caller of the function.\n    error CallerNotMinter(address caller);\n\n    /// @notice Error when the minter is the zero address.\n    /// @dev Selector 0x04a208c7.\n    error InvalidMinterZeroAddress();\n\n    /// @notice Error when insufficient balance to burn the amount.\n    /// @dev Selector 0xcf479181.\n    /// @param balance The balance of the account.\n    /// @param amount The amount to burn.\n    error InsufficientBalance(uint256 balance, uint256 amount);\n\n    /// @notice The minter has been changed.\n    /// @dev Topic0\n    ///      0x0b5e7be615a67a819aff3f47c967d1535cead1b98db60fafdcbf22dcaa8fa5a9.\n    /// @param newMinter The new minter.\n    event NewMinter(address previousMinter, address newMinter);\n\n    // NOTE: the `mint` method is not present in the standard ERC20 interface.\n    function mint(address account, uint256 amount) external;\n\n    // NOTE: the `setMinter` method is not present in the standard ERC20 interface.\n    function setMinter(address newMinter) external;\n\n    // NOTE: NttTokens in `burn` mode require the `burn` method to be present.\n    //       This method is not present in the standard ERC20 interface, but is\n    //       found in the `ERC20Burnable` interface.\n    function burn(uint256 amount) external;\n}\n"
      },
      "src/interfaces/ITransceiver.sol": {
        "content": "// SPDX-License-Identifier: Apache 2\npragma solidity >=0.8.8 <0.9.0;\n\nimport \"../libraries/TransceiverStructs.sol\";\n\ninterface ITransceiver {\n    /// @notice The caller is not the deployer.\n    /// @dev Selector: 0xc68a0e42.\n    /// @param deployer The address of the deployer.\n    /// @param caller The address of the caller.\n    error UnexpectedDeployer(address deployer, address caller);\n\n    /// @notice The caller is not the NttManager.\n    /// @dev Selector: 0xc5aa6153.\n    /// @param caller The address of the caller.\n    error CallerNotNttManager(address caller);\n\n    /// @notice Error when trying renounce transceiver ownership.\n    ///         Ensures the owner of the transceiver is in sync with\n    ///         the owner of the NttManager.\n    /// @dev Selector: 0x66791dd6.\n    /// @param currentOwner he current owner of the transceiver.\n    error CannotRenounceTransceiverOwnership(address currentOwner);\n\n    /// @notice Error when trying to transfer transceiver ownership.\n    /// @dev Selector: 0x306239eb.\n    /// @param currentOwner The current owner of the transceiver.\n    /// @param newOwner The new owner of the transceiver.\n    error CannotTransferTransceiverOwnership(address currentOwner, address newOwner);\n\n    /// @notice Error when the recipient NttManager address is not the\n    ///         corresponding manager of the transceiver.\n    /// @dev Selector: 0x73bdd322.\n    /// @param recipientNttManagerAddress The address of the recipient NttManager.\n    /// @param expectedRecipientNttManagerAddress The expected address of the recipient NttManager.\n    error UnexpectedRecipientNttManagerAddress(\n        bytes32 recipientNttManagerAddress, bytes32 expectedRecipientNttManagerAddress\n    );\n\n    /// @notice Fetch the delivery price for a given recipient chain transfer.\n    /// @param recipientChain The Wormhole chain ID of the target chain.\n    /// @param instruction An additional Instruction provided by the Transceiver to be\n    ///        executed on the recipient chain.\n    /// @return deliveryPrice The cost of delivering a message to the recipient chain,\n    ///         in this chain's native token.\n    function quoteDeliveryPrice(\n        uint16 recipientChain,\n        TransceiverStructs.TransceiverInstruction memory instruction\n    ) external view returns (uint256);\n\n    /// @dev Send a message to another chain.\n    /// @param recipientChain The Wormhole chain ID of the recipient.\n    /// @param instruction An additional Instruction provided by the Transceiver to be\n    /// executed on the recipient chain.\n    /// @param nttManagerMessage A message to be sent to the nttManager on the recipient chain.\n    function sendMessage(\n        uint16 recipientChain,\n        TransceiverStructs.TransceiverInstruction memory instruction,\n        bytes memory nttManagerMessage,\n        bytes32 recipientNttManagerAddress,\n        bytes32 refundAddress\n    ) external payable;\n\n    /// @notice Upgrades the transceiver to a new implementation.\n    function upgrade(address newImplementation) external;\n\n    /// @notice Transfers the ownership of the transceiver to a new address.\n    function transferTransceiverOwnership(address newOwner) external;\n}\n"
      },
      "src/NttManager/ManagerBase.sol": {
        "content": "// SPDX-License-Identifier: Apache 2\npragma solidity >=0.8.8 <0.9.0;\n\nimport \"wormhole-solidity-sdk/Utils.sol\";\nimport \"wormhole-solidity-sdk/libraries/BytesParsing.sol\";\n\nimport \"../libraries/external/OwnableUpgradeable.sol\";\nimport \"../libraries/external/ReentrancyGuardUpgradeable.sol\";\nimport \"../libraries/TransceiverStructs.sol\";\nimport \"../libraries/TransceiverHelpers.sol\";\nimport \"../libraries/PausableOwnable.sol\";\nimport \"../libraries/Implementation.sol\";\n\nimport \"../interfaces/ITransceiver.sol\";\nimport \"../interfaces/IManagerBase.sol\";\n\nimport \"./TransceiverRegistry.sol\";\n\nabstract contract ManagerBase is\n    IManagerBase,\n    TransceiverRegistry,\n    PausableOwnable,\n    ReentrancyGuardUpgradeable,\n    Implementation\n{\n    // =============== Immutables ============================================================\n\n    address public immutable token;\n    address immutable deployer;\n    Mode public immutable mode;\n    uint16 public immutable chainId;\n    uint256 immutable evmChainId;\n\n    // =============== Setup =================================================================\n\n    constructor(address _token, Mode _mode, uint16 _chainId) {\n        token = _token;\n        mode = _mode;\n        chainId = _chainId;\n        evmChainId = block.chainid;\n        // save the deployer (check this on initialization)\n        deployer = msg.sender;\n    }\n\n    function _migrate() internal virtual override {\n        _checkThresholdInvariants();\n        _checkTransceiversInvariants();\n    }\n\n    // =============== Storage ==============================================================\n\n    bytes32 private constant MESSAGE_ATTESTATIONS_SLOT =\n        bytes32(uint256(keccak256(\"ntt.messageAttestations\")) - 1);\n\n    bytes32 private constant MESSAGE_SEQUENCE_SLOT =\n        bytes32(uint256(keccak256(\"ntt.messageSequence\")) - 1);\n\n    bytes32 private constant THRESHOLD_SLOT = bytes32(uint256(keccak256(\"ntt.threshold\")) - 1);\n\n    // =============== Storage Getters/Setters ==============================================\n\n    function _getThresholdStorage() private pure returns (_Threshold storage $) {\n        uint256 slot = uint256(THRESHOLD_SLOT);\n        assembly (\"memory-safe\") {\n            $.slot := slot\n        }\n    }\n\n    function _getMessageAttestationsStorage()\n        internal\n        pure\n        returns (mapping(bytes32 => AttestationInfo) storage $)\n    {\n        uint256 slot = uint256(MESSAGE_ATTESTATIONS_SLOT);\n        assembly (\"memory-safe\") {\n            $.slot := slot\n        }\n    }\n\n    function _getMessageSequenceStorage() internal pure returns (_Sequence storage $) {\n        uint256 slot = uint256(MESSAGE_SEQUENCE_SLOT);\n        assembly (\"memory-safe\") {\n            $.slot := slot\n        }\n    }\n\n    // =============== External Logic =============================================================\n\n    /// @inheritdoc IManagerBase\n    function quoteDeliveryPrice(\n        uint16 recipientChain,\n        bytes memory transceiverInstructions\n    ) public view returns (uint256[] memory, uint256) {\n        address[] memory enabledTransceivers = _getEnabledTransceiversStorage();\n\n        TransceiverStructs.TransceiverInstruction[] memory instructions = TransceiverStructs\n            .parseTransceiverInstructions(transceiverInstructions, enabledTransceivers.length);\n\n        return _quoteDeliveryPrice(recipientChain, instructions, enabledTransceivers);\n    }\n\n    // =============== Internal Logic ===========================================================\n\n    function _quoteDeliveryPrice(\n        uint16 recipientChain,\n        TransceiverStructs.TransceiverInstruction[] memory transceiverInstructions,\n        address[] memory enabledTransceivers\n    ) internal view returns (uint256[] memory, uint256) {\n        uint256 numEnabledTransceivers = enabledTransceivers.length;\n        mapping(address => TransceiverInfo) storage transceiverInfos = _getTransceiverInfosStorage();\n\n        uint256[] memory priceQuotes = new uint256[](numEnabledTransceivers);\n        uint256 totalPriceQuote = 0;\n        for (uint256 i = 0; i < numEnabledTransceivers; i++) {\n            address transceiverAddr = enabledTransceivers[i];\n            uint8 registeredTransceiverIndex = transceiverInfos[transceiverAddr].index;\n            uint256 transceiverPriceQuote = ITransceiver(transceiverAddr).quoteDeliveryPrice(\n                recipientChain, transceiverInstructions[registeredTransceiverIndex]\n            );\n            priceQuotes[i] = transceiverPriceQuote;\n            totalPriceQuote += transceiverPriceQuote;\n        }\n        return (priceQuotes, totalPriceQuote);\n    }\n\n    function _recordTransceiverAttestation(\n        uint16 sourceChainId,\n        TransceiverStructs.NttManagerMessage memory payload\n    ) internal returns (bytes32) {\n        bytes32 nttManagerMessageHash =\n            TransceiverStructs.nttManagerMessageDigest(sourceChainId, payload);\n\n        // set the attested flag for this transceiver.\n        // NOTE: Attestation is idempotent (bitwise or 1), but we revert\n        // anyway to ensure that the client does not continue to initiate calls\n        // to receive the same message through the same transceiver.\n        if (\n            transceiverAttestedToMessage(\n                nttManagerMessageHash, _getTransceiverInfosStorage()[msg.sender].index\n            )\n        ) {\n            revert TransceiverAlreadyAttestedToMessage(nttManagerMessageHash);\n        }\n        _setTransceiverAttestedToMessage(nttManagerMessageHash, msg.sender);\n\n        return nttManagerMessageHash;\n    }\n\n    function _isMessageExecuted(\n        uint16 sourceChainId,\n        bytes32 sourceNttManagerAddress,\n        TransceiverStructs.NttManagerMessage memory message\n    ) internal returns (bytes32, bool) {\n        bytes32 digest = TransceiverStructs.nttManagerMessageDigest(sourceChainId, message);\n\n        if (!isMessageApproved(digest)) {\n            revert MessageNotApproved(digest);\n        }\n\n        bool msgAlreadyExecuted = _replayProtect(digest);\n        if (msgAlreadyExecuted) {\n            // end execution early to mitigate the possibility of race conditions from transceivers\n            // attempting to deliver the same message when (threshold < number of transceiver messages)\n            // notify client (off-chain process) so they don't attempt redundant msg delivery\n            emit MessageAlreadyExecuted(sourceNttManagerAddress, digest);\n            return (bytes32(0), msgAlreadyExecuted);\n        }\n\n        return (digest, msgAlreadyExecuted);\n    }\n\n    function _sendMessageToTransceivers(\n        uint16 recipientChain,\n        bytes32 refundAddress,\n        bytes32 peerAddress,\n        uint256[] memory priceQuotes,\n        TransceiverStructs.TransceiverInstruction[] memory transceiverInstructions,\n        address[] memory enabledTransceivers,\n        bytes memory nttManagerMessage\n    ) internal {\n        uint256 numEnabledTransceivers = enabledTransceivers.length;\n        mapping(address => TransceiverInfo) storage transceiverInfos = _getTransceiverInfosStorage();\n\n        if (peerAddress == bytes32(0)) {\n            revert PeerNotRegistered(recipientChain);\n        }\n\n        // push onto the stack again to avoid stack too deep error\n        bytes32 refundRecipient = refundAddress;\n\n        // call into transceiver contracts to send the message\n        for (uint256 i = 0; i < numEnabledTransceivers; i++) {\n            address transceiverAddr = enabledTransceivers[i];\n\n            // send it to the recipient nttManager based on the chain\n            ITransceiver(transceiverAddr).sendMessage{value: priceQuotes[i]}(\n                recipientChain,\n                transceiverInstructions[transceiverInfos[transceiverAddr].index],\n                nttManagerMessage,\n                peerAddress,\n                refundRecipient\n            );\n        }\n    }\n\n    function _prepareForTransfer(\n        uint16 recipientChain,\n        bytes memory transceiverInstructions\n    )\n        internal\n        returns (\n            address[] memory,\n            TransceiverStructs.TransceiverInstruction[] memory,\n            uint256[] memory,\n            uint256\n        )\n    {\n        // cache enabled transceivers to avoid multiple storage reads\n        address[] memory enabledTransceivers = _getEnabledTransceiversStorage();\n\n        TransceiverStructs.TransceiverInstruction[] memory instructions;\n\n        {\n            uint256 numRegisteredTransceivers = _getRegisteredTransceiversStorage().length;\n            uint256 numEnabledTransceivers = enabledTransceivers.length;\n\n            if (numEnabledTransceivers == 0) {\n                revert NoEnabledTransceivers();\n            }\n\n            instructions = TransceiverStructs.parseTransceiverInstructions(\n                transceiverInstructions, numRegisteredTransceivers\n            );\n        }\n\n        (uint256[] memory priceQuotes, uint256 totalPriceQuote) =\n            _quoteDeliveryPrice(recipientChain, instructions, enabledTransceivers);\n        {\n            // check up front that msg.value will cover the delivery price\n            if (msg.value < totalPriceQuote) {\n                revert DeliveryPaymentTooLow(totalPriceQuote, msg.value);\n            }\n\n            // refund user extra excess value from msg.value\n            uint256 excessValue = msg.value - totalPriceQuote;\n            if (excessValue > 0) {\n                _refundToSender(excessValue);\n            }\n        }\n\n        return (enabledTransceivers, instructions, priceQuotes, totalPriceQuote);\n    }\n\n    function _refundToSender(uint256 refundAmount) internal {\n        // refund the price quote back to sender\n        (bool refundSuccessful,) = payable(msg.sender).call{value: refundAmount}(\"\");\n\n        // check success\n        if (!refundSuccessful) {\n            revert RefundFailed(refundAmount);\n        }\n    }\n\n    // =============== Public Getters ========================================================\n\n    /// @inheritdoc IManagerBase\n    function getMode() public view returns (uint8) {\n        return uint8(mode);\n    }\n\n    /// @inheritdoc IManagerBase\n    function getThreshold() public view returns (uint8) {\n        return _getThresholdStorage().num;\n    }\n\n    /// @inheritdoc IManagerBase\n    function isMessageApproved(bytes32 digest) public view returns (bool) {\n        uint8 threshold = getThreshold();\n        return messageAttestations(digest) >= threshold && threshold > 0;\n    }\n\n    /// @inheritdoc IManagerBase\n    function nextMessageSequence() external view returns (uint64) {\n        return _getMessageSequenceStorage().num;\n    }\n\n    /// @inheritdoc IManagerBase\n    function isMessageExecuted(bytes32 digest) public view returns (bool) {\n        return _getMessageAttestationsStorage()[digest].executed;\n    }\n\n    /// @inheritdoc IManagerBase\n    function transceiverAttestedToMessage(bytes32 digest, uint8 index) public view returns (bool) {\n        return\n            _getMessageAttestationsStorage()[digest].attestedTransceivers & uint64(1 << index) > 0;\n    }\n\n    /// @inheritdoc IManagerBase\n    function messageAttestations(bytes32 digest) public view returns (uint8 count) {\n        return countSetBits(_getMessageAttestations(digest));\n    }\n\n    // =============== Admin ==============================================================\n\n    /// @inheritdoc IManagerBase\n    function upgrade(address newImplementation) external onlyOwner {\n        _upgrade(newImplementation);\n    }\n\n    /// @inheritdoc IManagerBase\n    function pause() public onlyOwnerOrPauser {\n        _pause();\n    }\n\n    function unpause() public onlyOwnerOrPauser {\n        _unpause();\n    }\n\n    /// @notice Transfer ownership of the Manager contract and all Transceiver contracts to a new owner.\n    function transferOwnership(address newOwner) public override onlyOwner {\n        super.transferOwnership(newOwner);\n        // loop through all the registered transceivers and set the new owner of each transceiver to the newOwner\n        address[] storage _registeredTransceivers = _getRegisteredTransceiversStorage();\n        _checkRegisteredTransceiversInvariants();\n\n        for (uint256 i = 0; i < _registeredTransceivers.length; i++) {\n            ITransceiver(_registeredTransceivers[i]).transferTransceiverOwnership(newOwner);\n        }\n    }\n\n    /// @inheritdoc IManagerBase\n    function setTransceiver(address transceiver) external onlyOwner {\n        _setTransceiver(transceiver);\n\n        _Threshold storage _threshold = _getThresholdStorage();\n        // We do not automatically increase the threshold here.\n        // Automatically increasing the threshold can result in a scenario\n        // where in-flight messages can't be redeemed.\n        // For example: Assume there is 1 Transceiver and the threshold is 1.\n        // If we were to add a new Transceiver, the threshold would increase to 2.\n        // However, all messages that are either in-flight or that are sent on\n        // a source chain that does not yet have 2 Transceivers will only have been\n        // sent from a single transceiver, so they would never be able to get\n        // redeemed.\n        // Instead, we leave it up to the owner to manually update the threshold\n        // after some period of time, ideally once all chains have the new Transceiver\n        // and transfers that were sent via the old configuration are all complete.\n        // However if the threshold is 0 (the initial case) we do increment to 1.\n        if (_threshold.num == 0) {\n            _threshold.num = 1;\n        }\n\n        emit TransceiverAdded(transceiver, _getNumTransceiversStorage().enabled, _threshold.num);\n\n        _checkThresholdInvariants();\n    }\n\n    /// @inheritdoc IManagerBase\n    function removeTransceiver(address transceiver) external onlyOwner {\n        _removeTransceiver(transceiver);\n\n        _Threshold storage _threshold = _getThresholdStorage();\n        uint8 numEnabledTransceivers = _getNumTransceiversStorage().enabled;\n\n        if (numEnabledTransceivers < _threshold.num) {\n            _threshold.num = numEnabledTransceivers;\n        }\n\n        emit TransceiverRemoved(transceiver, _threshold.num);\n\n        _checkThresholdInvariants();\n    }\n\n    /// @inheritdoc IManagerBase\n    function setThreshold(uint8 threshold) external onlyOwner {\n        if (threshold == 0) {\n            revert ZeroThreshold();\n        }\n\n        _Threshold storage _threshold = _getThresholdStorage();\n        uint8 oldThreshold = _threshold.num;\n\n        _threshold.num = threshold;\n        _checkThresholdInvariants();\n\n        emit ThresholdChanged(oldThreshold, threshold);\n    }\n\n    // =============== Internal ==============================================================\n\n    function _setTransceiverAttestedToMessage(bytes32 digest, uint8 index) internal {\n        _getMessageAttestationsStorage()[digest].attestedTransceivers |= uint64(1 << index);\n    }\n\n    function _setTransceiverAttestedToMessage(bytes32 digest, address transceiver) internal {\n        _setTransceiverAttestedToMessage(digest, _getTransceiverInfosStorage()[transceiver].index);\n\n        emit MessageAttestedTo(\n            digest, transceiver, _getTransceiverInfosStorage()[transceiver].index\n        );\n    }\n\n    /// @dev Returns the bitmap of attestations from enabled transceivers for a given message.\n    function _getMessageAttestations(bytes32 digest) internal view returns (uint64) {\n        uint64 enabledTransceiverBitmap = _getEnabledTransceiversBitmap();\n        return\n            _getMessageAttestationsStorage()[digest].attestedTransceivers & enabledTransceiverBitmap;\n    }\n\n    function _getEnabledTransceiverAttestedToMessage(\n        bytes32 digest,\n        uint8 index\n    ) internal view returns (bool) {\n        return _getMessageAttestations(digest) & uint64(1 << index) != 0;\n    }\n\n    // @dev Mark a message as executed.\n    // This function will retuns `true` if the message has already been executed.\n    function _replayProtect(bytes32 digest) internal returns (bool) {\n        // check if this message has already been executed\n        if (isMessageExecuted(digest)) {\n            return true;\n        }\n\n        // mark this message as executed\n        _getMessageAttestationsStorage()[digest].executed = true;\n\n        return false;\n    }\n\n    function _useMessageSequence() internal returns (uint64 currentSequence) {\n        currentSequence = _getMessageSequenceStorage().num;\n        _getMessageSequenceStorage().num++;\n    }\n\n    /// ============== Invariants =============================================\n\n    /// @dev When we add new immutables, this function should be updated\n    function _checkImmutables() internal view virtual override {\n        assert(this.token() == token);\n        assert(this.mode() == mode);\n        assert(this.chainId() == chainId);\n    }\n\n    function _checkRegisteredTransceiversInvariants() internal view {\n        if (_getRegisteredTransceiversStorage().length != _getNumTransceiversStorage().registered) {\n            revert RetrievedIncorrectRegisteredTransceivers(\n                _getRegisteredTransceiversStorage().length, _getNumTransceiversStorage().registered\n            );\n        }\n    }\n\n    function _checkThresholdInvariants() internal view {\n        uint8 threshold = _getThresholdStorage().num;\n        _NumTransceivers memory numTransceivers = _getNumTransceiversStorage();\n\n        // invariant: threshold <= enabledTransceivers.length\n        if (threshold > numTransceivers.enabled) {\n            revert ThresholdTooHigh(threshold, numTransceivers.enabled);\n        }\n\n        if (numTransceivers.registered > 0) {\n            if (threshold == 0) {\n                revert ZeroThreshold();\n            }\n        }\n    }\n}\n"
      },
      "lib/openzeppelin-contracts/contracts/token/ERC20/extensions/draft-IERC20Permit.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (token/ERC20/extensions/draft-IERC20Permit.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Interface of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in\n * https://eips.ethereum.org/EIPS/eip-2612[EIP-2612].\n *\n * Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by\n * presenting a message signed by the account. By not relying on {IERC20-approve}, the token holder account doesn't\n * need to send a transaction, and thus is not required to hold Ether at all.\n */\ninterface IERC20Permit {\n    /**\n     * @dev Sets `value` as the allowance of `spender` over ``owner``'s tokens,\n     * given ``owner``'s signed approval.\n     *\n     * IMPORTANT: The same issues {IERC20-approve} has related to transaction\n     * ordering also apply here.\n     *\n     * Emits an {Approval} event.\n     *\n     * Requirements:\n     *\n     * - `spender` cannot be the zero address.\n     * - `deadline` must be a timestamp in the future.\n     * - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner`\n     * over the EIP712-formatted function arguments.\n     * - the signature must use ``owner``'s current nonce (see {nonces}).\n     *\n     * For more information on the signature format, see the\n     * https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP\n     * section].\n     */\n    function permit(\n        address owner,\n        address spender,\n        uint256 value,\n        uint256 deadline,\n        uint8 v,\n        bytes32 r,\n        bytes32 s\n    ) external;\n\n    /**\n     * @dev Returns the current nonce for `owner`. This value must be\n     * included whenever a signature is generated for {permit}.\n     *\n     * Every successful call to {permit} increases ``owner``'s nonce by one. This\n     * prevents a signature from being used multiple times.\n     */\n    function nonces(address owner) external view returns (uint256);\n\n    /**\n     * @dev Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}.\n     */\n    // solhint-disable-next-line func-name-mixedcase\n    function DOMAIN_SEPARATOR() external view returns (bytes32);\n}\n"
      },
      "lib/openzeppelin-contracts/contracts/utils/Address.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/Address.sol)\n\npragma solidity ^0.8.1;\n\n/**\n * @dev Collection of functions related to the address type\n */\nlibrary Address {\n    /**\n     * @dev Returns true if `account` is a contract.\n     *\n     * [IMPORTANT]\n     * ====\n     * It is unsafe to assume that an address for which this function returns\n     * false is an externally-owned account (EOA) and not a contract.\n     *\n     * Among others, `isContract` will return false for the following\n     * types of addresses:\n     *\n     *  - an externally-owned account\n     *  - a contract in construction\n     *  - an address where a contract will be created\n     *  - an address where a contract lived, but was destroyed\n     * ====\n     *\n     * [IMPORTANT]\n     * ====\n     * You shouldn't rely on `isContract` to protect against flash loan attacks!\n     *\n     * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets\n     * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract\n     * constructor.\n     * ====\n     */\n    function isContract(address account) internal view returns (bool) {\n        // This method relies on extcodesize/address.code.length, which returns 0\n        // for contracts in construction, since the code is only stored at the end\n        // of the constructor execution.\n\n        return account.code.length > 0;\n    }\n\n    /**\n     * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\n     * `recipient`, forwarding all available gas and reverting on errors.\n     *\n     * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\n     * of certain opcodes, possibly making contracts go over the 2300 gas limit\n     * imposed by `transfer`, making them unable to receive funds via\n     * `transfer`. {sendValue} removes this limitation.\n     *\n     * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more].\n     *\n     * IMPORTANT: because control is transferred to `recipient`, care must be\n     * taken to not create reentrancy vulnerabilities. Consider using\n     * {ReentrancyGuard} or the\n     * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\n     */\n    function sendValue(address payable recipient, uint256 amount) internal {\n        require(address(this).balance >= amount, \"Address: insufficient balance\");\n\n        (bool success, ) = recipient.call{value: amount}(\"\");\n        require(success, \"Address: unable to send value, recipient may have reverted\");\n    }\n\n    /**\n     * @dev Performs a Solidity function call using a low level `call`. A\n     * plain `call` is an unsafe replacement for a function call: use this\n     * function instead.\n     *\n     * If `target` reverts with a revert reason, it is bubbled up by this\n     * function (like regular Solidity function calls).\n     *\n     * Returns the raw returned data. To convert to the expected return value,\n     * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\n     *\n     * Requirements:\n     *\n     * - `target` must be a contract.\n     * - calling `target` with `data` must not revert.\n     *\n     * _Available since v3.1._\n     */\n    function functionCall(address target, bytes memory data) internal returns (bytes memory) {\n        return functionCallWithValue(target, data, 0, \"Address: low-level call failed\");\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with\n     * `errorMessage` as a fallback revert reason when `target` reverts.\n     *\n     * _Available since v3.1._\n     */\n    function functionCall(\n        address target,\n        bytes memory data,\n        string memory errorMessage\n    ) internal returns (bytes memory) {\n        return functionCallWithValue(target, data, 0, errorMessage);\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n     * but also transferring `value` wei to `target`.\n     *\n     * Requirements:\n     *\n     * - the calling contract must have an ETH balance of at least `value`.\n     * - the called Solidity function must be `payable`.\n     *\n     * _Available since v3.1._\n     */\n    function functionCallWithValue(\n        address target,\n        bytes memory data,\n        uint256 value\n    ) internal returns (bytes memory) {\n        return functionCallWithValue(target, data, value, \"Address: low-level call with value failed\");\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but\n     * with `errorMessage` as a fallback revert reason when `target` reverts.\n     *\n     * _Available since v3.1._\n     */\n    function functionCallWithValue(\n        address target,\n        bytes memory data,\n        uint256 value,\n        string memory errorMessage\n    ) internal returns (bytes memory) {\n        require(address(this).balance >= value, \"Address: insufficient balance for call\");\n        (bool success, bytes memory returndata) = target.call{value: value}(data);\n        return verifyCallResultFromTarget(target, success, returndata, errorMessage);\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n     * but performing a static call.\n     *\n     * _Available since v3.3._\n     */\n    function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\n        return functionStaticCall(target, data, \"Address: low-level static call failed\");\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\n     * but performing a static call.\n     *\n     * _Available since v3.3._\n     */\n    function functionStaticCall(\n        address target,\n        bytes memory data,\n        string memory errorMessage\n    ) internal view returns (bytes memory) {\n        (bool success, bytes memory returndata) = target.staticcall(data);\n        return verifyCallResultFromTarget(target, success, returndata, errorMessage);\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n     * but performing a delegate call.\n     *\n     * _Available since v3.4._\n     */\n    function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\n        return functionDelegateCall(target, data, \"Address: low-level delegate call failed\");\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\n     * but performing a delegate call.\n     *\n     * _Available since v3.4._\n     */\n    function functionDelegateCall(\n        address target,\n        bytes memory data,\n        string memory errorMessage\n    ) internal returns (bytes memory) {\n        (bool success, bytes memory returndata) = target.delegatecall(data);\n        return verifyCallResultFromTarget(target, success, returndata, errorMessage);\n    }\n\n    /**\n     * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling\n     * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract.\n     *\n     * _Available since v4.8._\n     */\n    function verifyCallResultFromTarget(\n        address target,\n        bool success,\n        bytes memory returndata,\n        string memory errorMessage\n    ) internal view returns (bytes memory) {\n        if (success) {\n            if (returndata.length == 0) {\n                // only check isContract if the call was successful and the return data is empty\n                // otherwise we already know that it was a contract\n                require(isContract(target), \"Address: call to non-contract\");\n            }\n            return returndata;\n        } else {\n            _revert(returndata, errorMessage);\n        }\n    }\n\n    /**\n     * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the\n     * revert reason or using the provided one.\n     *\n     * _Available since v4.3._\n     */\n    function verifyCallResult(\n        bool success,\n        bytes memory returndata,\n        string memory errorMessage\n    ) internal pure returns (bytes memory) {\n        if (success) {\n            return returndata;\n        } else {\n            _revert(returndata, errorMessage);\n        }\n    }\n\n    function _revert(bytes memory returndata, string memory errorMessage) private pure {\n        // Look for revert reason and bubble it up if present\n        if (returndata.length > 0) {\n            // The easiest way to bubble the revert reason is using memory via assembly\n            /// @solidity memory-safe-assembly\n            assembly {\n                let returndata_size := mload(returndata)\n                revert(add(32, returndata), returndata_size)\n            }\n        } else {\n            revert(errorMessage);\n        }\n    }\n}\n"
      },
      "lib/openzeppelin-contracts/contracts/token/ERC20/ERC20.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (token/ERC20/ERC20.sol)\n\npragma solidity ^0.8.0;\n\nimport \"./IERC20.sol\";\nimport \"./extensions/IERC20Metadata.sol\";\nimport \"../../utils/Context.sol\";\n\n/**\n * @dev Implementation of the {IERC20} interface.\n *\n * This implementation is agnostic to the way tokens are created. This means\n * that a supply mechanism has to be added in a derived contract using {_mint}.\n * For a generic mechanism see {ERC20PresetMinterPauser}.\n *\n * TIP: For a detailed writeup see our guide\n * https://forum.openzeppelin.com/t/how-to-implement-erc20-supply-mechanisms/226[How\n * to implement supply mechanisms].\n *\n * We have followed general OpenZeppelin Contracts guidelines: functions revert\n * instead returning `false` on failure. This behavior is nonetheless\n * conventional and does not conflict with the expectations of ERC20\n * applications.\n *\n * Additionally, an {Approval} event is emitted on calls to {transferFrom}.\n * This allows applications to reconstruct the allowance for all accounts just\n * by listening to said events. Other implementations of the EIP may not emit\n * these events, as it isn't required by the specification.\n *\n * Finally, the non-standard {decreaseAllowance} and {increaseAllowance}\n * functions have been added to mitigate the well-known issues around setting\n * allowances. See {IERC20-approve}.\n */\ncontract ERC20 is Context, IERC20, IERC20Metadata {\n    mapping(address => uint256) private _balances;\n\n    mapping(address => mapping(address => uint256)) private _allowances;\n\n    uint256 private _totalSupply;\n\n    string private _name;\n    string private _symbol;\n\n    /**\n     * @dev Sets the values for {name} and {symbol}.\n     *\n     * The default value of {decimals} is 18. To select a different value for\n     * {decimals} you should overload it.\n     *\n     * All two of these values are immutable: they can only be set once during\n     * construction.\n     */\n    constructor(string memory name_, string memory symbol_) {\n        _name = name_;\n        _symbol = symbol_;\n    }\n\n    /**\n     * @dev Returns the name of the token.\n     */\n    function name() public view virtual override returns (string memory) {\n        return _name;\n    }\n\n    /**\n     * @dev Returns the symbol of the token, usually a shorter version of the\n     * name.\n     */\n    function symbol() public view virtual override returns (string memory) {\n        return _symbol;\n    }\n\n    /**\n     * @dev Returns the number of decimals used to get its user representation.\n     * For example, if `decimals` equals `2`, a balance of `505` tokens should\n     * be displayed to a user as `5.05` (`505 / 10 ** 2`).\n     *\n     * Tokens usually opt for a value of 18, imitating the relationship between\n     * Ether and Wei. This is the value {ERC20} uses, unless this function is\n     * overridden;\n     *\n     * NOTE: This information is only used for _display_ purposes: it in\n     * no way affects any of the arithmetic of the contract, including\n     * {IERC20-balanceOf} and {IERC20-transfer}.\n     */\n    function decimals() public view virtual override returns (uint8) {\n        return 18;\n    }\n\n    /**\n     * @dev See {IERC20-totalSupply}.\n     */\n    function totalSupply() public view virtual override returns (uint256) {\n        return _totalSupply;\n    }\n\n    /**\n     * @dev See {IERC20-balanceOf}.\n     */\n    function balanceOf(address account) public view virtual override returns (uint256) {\n        return _balances[account];\n    }\n\n    /**\n     * @dev See {IERC20-transfer}.\n     *\n     * Requirements:\n     *\n     * - `to` cannot be the zero address.\n     * - the caller must have a balance of at least `amount`.\n     */\n    function transfer(address to, uint256 amount) public virtual override returns (bool) {\n        address owner = _msgSender();\n        _transfer(owner, to, amount);\n        return true;\n    }\n\n    /**\n     * @dev See {IERC20-allowance}.\n     */\n    function allowance(address owner, address spender) public view virtual override returns (uint256) {\n        return _allowances[owner][spender];\n    }\n\n    /**\n     * @dev See {IERC20-approve}.\n     *\n     * NOTE: If `amount` is the maximum `uint256`, the allowance is not updated on\n     * `transferFrom`. This is semantically equivalent to an infinite approval.\n     *\n     * Requirements:\n     *\n     * - `spender` cannot be the zero address.\n     */\n    function approve(address spender, uint256 amount) public virtual override returns (bool) {\n        address owner = _msgSender();\n        _approve(owner, spender, amount);\n        return true;\n    }\n\n    /**\n     * @dev See {IERC20-transferFrom}.\n     *\n     * Emits an {Approval} event indicating the updated allowance. This is not\n     * required by the EIP. See the note at the beginning of {ERC20}.\n     *\n     * NOTE: Does not update the allowance if the current allowance\n     * is the maximum `uint256`.\n     *\n     * Requirements:\n     *\n     * - `from` and `to` cannot be the zero address.\n     * - `from` must have a balance of at least `amount`.\n     * - the caller must have allowance for ``from``'s tokens of at least\n     * `amount`.\n     */\n    function transferFrom(\n        address from,\n        address to,\n        uint256 amount\n    ) public virtual override returns (bool) {\n        address spender = _msgSender();\n        _spendAllowance(from, spender, amount);\n        _transfer(from, to, amount);\n        return true;\n    }\n\n    /**\n     * @dev Atomically increases the allowance granted to `spender` by the caller.\n     *\n     * This is an alternative to {approve} that can be used as a mitigation for\n     * problems described in {IERC20-approve}.\n     *\n     * Emits an {Approval} event indicating the updated allowance.\n     *\n     * Requirements:\n     *\n     * - `spender` cannot be the zero address.\n     */\n    function increaseAllowance(address spender, uint256 addedValue) public virtual returns (bool) {\n        address owner = _msgSender();\n        _approve(owner, spender, allowance(owner, spender) + addedValue);\n        return true;\n    }\n\n    /**\n     * @dev Atomically decreases the allowance granted to `spender` by the caller.\n     *\n     * This is an alternative to {approve} that can be used as a mitigation for\n     * problems described in {IERC20-approve}.\n     *\n     * Emits an {Approval} event indicating the updated allowance.\n     *\n     * Requirements:\n     *\n     * - `spender` cannot be the zero address.\n     * - `spender` must have allowance for the caller of at least\n     * `subtractedValue`.\n     */\n    function decreaseAllowance(address spender, uint256 subtractedValue) public virtual returns (bool) {\n        address owner = _msgSender();\n        uint256 currentAllowance = allowance(owner, spender);\n        require(currentAllowance >= subtractedValue, \"ERC20: decreased allowance below zero\");\n        unchecked {\n            _approve(owner, spender, currentAllowance - subtractedValue);\n        }\n\n        return true;\n    }\n\n    /**\n     * @dev Moves `amount` of tokens from `from` to `to`.\n     *\n     * This internal function is equivalent to {transfer}, and can be used to\n     * e.g. implement automatic token fees, slashing mechanisms, etc.\n     *\n     * Emits a {Transfer} event.\n     *\n     * Requirements:\n     *\n     * - `from` cannot be the zero address.\n     * - `to` cannot be the zero address.\n     * - `from` must have a balance of at least `amount`.\n     */\n    function _transfer(\n        address from,\n        address to,\n        uint256 amount\n    ) internal virtual {\n        require(from != address(0), \"ERC20: transfer from the zero address\");\n        require(to != address(0), \"ERC20: transfer to the zero address\");\n\n        _beforeTokenTransfer(from, to, amount);\n\n        uint256 fromBalance = _balances[from];\n        require(fromBalance >= amount, \"ERC20: transfer amount exceeds balance\");\n        unchecked {\n            _balances[from] = fromBalance - amount;\n            // Overflow not possible: the sum of all balances is capped by totalSupply, and the sum is preserved by\n            // decrementing then incrementing.\n            _balances[to] += amount;\n        }\n\n        emit Transfer(from, to, amount);\n\n        _afterTokenTransfer(from, to, amount);\n    }\n\n    /** @dev Creates `amount` tokens and assigns them to `account`, increasing\n     * the total supply.\n     *\n     * Emits a {Transfer} event with `from` set to the zero address.\n     *\n     * Requirements:\n     *\n     * - `account` cannot be the zero address.\n     */\n    function _mint(address account, uint256 amount) internal virtual {\n        require(account != address(0), \"ERC20: mint to the zero address\");\n\n        _beforeTokenTransfer(address(0), account, amount);\n\n        _totalSupply += amount;\n        unchecked {\n            // Overflow not possible: balance + amount is at most totalSupply + amount, which is checked above.\n            _balances[account] += amount;\n        }\n        emit Transfer(address(0), account, amount);\n\n        _afterTokenTransfer(address(0), account, amount);\n    }\n\n    /**\n     * @dev Destroys `amount` tokens from `account`, reducing the\n     * total supply.\n     *\n     * Emits a {Transfer} event with `to` set to the zero address.\n     *\n     * Requirements:\n     *\n     * - `account` cannot be the zero address.\n     * - `account` must have at least `amount` tokens.\n     */\n    function _burn(address account, uint256 amount) internal virtual {\n        require(account != address(0), \"ERC20: burn from the zero address\");\n\n        _beforeTokenTransfer(account, address(0), amount);\n\n        uint256 accountBalance = _balances[account];\n        require(accountBalance >= amount, \"ERC20: burn amount exceeds balance\");\n        unchecked {\n            _balances[account] = accountBalance - amount;\n            // Overflow not possible: amount <= accountBalance <= totalSupply.\n            _totalSupply -= amount;\n        }\n\n        emit Transfer(account, address(0), amount);\n\n        _afterTokenTransfer(account, address(0), amount);\n    }\n\n    /**\n     * @dev Sets `amount` as the allowance of `spender` over the `owner` s tokens.\n     *\n     * This internal function is equivalent to `approve`, and can be used to\n     * e.g. set automatic allowances for certain subsystems, etc.\n     *\n     * Emits an {Approval} event.\n     *\n     * Requirements:\n     *\n     * - `owner` cannot be the zero address.\n     * - `spender` cannot be the zero address.\n     */\n    function _approve(\n        address owner,\n        address spender,\n        uint256 amount\n    ) internal virtual {\n        require(owner != address(0), \"ERC20: approve from the zero address\");\n        require(spender != address(0), \"ERC20: approve to the zero address\");\n\n        _allowances[owner][spender] = amount;\n        emit Approval(owner, spender, amount);\n    }\n\n    /**\n     * @dev Updates `owner` s allowance for `spender` based on spent `amount`.\n     *\n     * Does not update the allowance amount in case of infinite allowance.\n     * Revert if not enough allowance is available.\n     *\n     * Might emit an {Approval} event.\n     */\n    function _spendAllowance(\n        address owner,\n        address spender,\n        uint256 amount\n    ) internal virtual {\n        uint256 currentAllowance = allowance(owner, spender);\n        if (currentAllowance != type(uint256).max) {\n            require(currentAllowance >= amount, \"ERC20: insufficient allowance\");\n            unchecked {\n                _approve(owner, spender, currentAllowance - amount);\n            }\n        }\n    }\n\n    /**\n     * @dev Hook that is called before any transfer of tokens. This includes\n     * minting and burning.\n     *\n     * Calling conditions:\n     *\n     * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens\n     * will be transferred to `to`.\n     * - when `from` is zero, `amount` tokens will be minted for `to`.\n     * - when `to` is zero, `amount` of ``from``'s tokens will be burned.\n     * - `from` and `to` are never both zero.\n     *\n     * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].\n     */\n    function _beforeTokenTransfer(\n        address from,\n        address to,\n        uint256 amount\n    ) internal virtual {}\n\n    /**\n     * @dev Hook that is called after any transfer of tokens. This includes\n     * minting and burning.\n     *\n     * Calling conditions:\n     *\n     * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens\n     * has been transferred to `to`.\n     * - when `from` is zero, `amount` tokens have been minted for `to`.\n     * - when `to` is zero, `amount` of ``from``'s tokens have been burned.\n     * - `from` and `to` are never both zero.\n     *\n     * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].\n     */\n    function _afterTokenTransfer(\n        address from,\n        address to,\n        uint256 amount\n    ) internal virtual {}\n}\n"
      },
      "lib/openzeppelin-contracts/contracts/utils/Context.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Provides information about the current execution context, including the\n * sender of the transaction and its data. While these are generally available\n * via msg.sender and msg.data, they should not be accessed in such a direct\n * manner, since when dealing with meta-transactions the account sending and\n * paying for execution may not be the actual sender (as far as an application\n * is concerned).\n *\n * This contract is only required for intermediate, library-like contracts.\n */\nabstract contract Context {\n    function _msgSender() internal view virtual returns (address) {\n        return msg.sender;\n    }\n\n    function _msgData() internal view virtual returns (bytes calldata) {\n        return msg.data;\n    }\n}\n"
      },
      "lib/wormhole-solidity-sdk/src/interfaces/IWormholeRelayer.sol": {
        "content": "// SPDX-License-Identifier: Apache 2\n\npragma solidity ^0.8.0;\n\n/**\n * @title WormholeRelayer\n * @author\n * @notice This project allows developers to build cross-chain applications powered by Wormhole without needing to\n * write and run their own relaying infrastructure\n *\n * We implement the IWormholeRelayer interface that allows users to request a delivery provider to relay a payload (and/or additional messages)\n * to a chain and address of their choice.\n */\n\n/**\n * @notice VaaKey identifies a wormhole message\n *\n * @custom:member chainId Wormhole chain ID of the chain where this VAA was emitted from\n * @custom:member emitterAddress Address of the emitter of the VAA, in Wormhole bytes32 format\n * @custom:member sequence Sequence number of the VAA\n */\nstruct VaaKey {\n    uint16 chainId;\n    bytes32 emitterAddress;\n    uint64 sequence;\n}\n\n// 0-127 are reserved for standardized KeyTypes, 128-255 are for custom use\nuint8 constant VAA_KEY_TYPE = 1;\n\nstruct MessageKey {\n    uint8 keyType; // 0-127 are reserved for standardized KeyTypes, 128-255 are for custom use\n    bytes encodedKey;\n}\n\ninterface IWormholeRelayerBase {\n    event SendEvent(\n        uint64 indexed sequence,\n        uint256 deliveryQuote,\n        uint256 paymentForExtraReceiverValue\n    );\n\n    function getRegisteredWormholeRelayerContract(\n        uint16 chainId\n    ) external view returns (bytes32);\n\n    /**\n     * @notice Returns true if a delivery has been attempted for the given deliveryHash\n     * Note: invalid deliveries where the tx reverts are not considered attempted\n     */\n    function deliveryAttempted(\n        bytes32 deliveryHash\n    ) external view returns (bool attempted);\n\n    /**\n     * @notice block number at which a delivery was successfully executed\n     */\n    function deliverySuccessBlock(\n        bytes32 deliveryHash\n    ) external view returns (uint256 blockNumber);\n\n    /**\n     * @notice block number of the latest attempt to execute a delivery that failed\n     */\n    function deliveryFailureBlock(\n        bytes32 deliveryHash\n    ) external view returns (uint256 blockNumber);\n}\n\n/**\n * @title IWormholeRelayerSend\n * @notice The interface to request deliveries\n */\ninterface IWormholeRelayerSend is IWormholeRelayerBase {\n    /**\n     * @notice Publishes an instruction for the default delivery provider\n     * to relay a payload to the address `targetAddress` on chain `targetChain`\n     * with gas limit `gasLimit` and `msg.value` equal to `receiverValue`\n     *\n     * `targetAddress` must implement the IWormholeReceiver interface\n     *\n     * This function must be called with `msg.value` equal to `quoteEVMDeliveryPrice(targetChain, receiverValue, gasLimit)`\n     *\n     * Any refunds (from leftover gas) will be paid to the delivery provider. In order to receive the refunds, use the `sendPayloadToEvm` function\n     * with `refundChain` and `refundAddress` as parameters\n     *\n     * @param targetChain in Wormhole Chain ID format\n     * @param targetAddress address to call on targetChain (that implements IWormholeReceiver)\n     * @param payload arbitrary bytes to pass in as parameter in call to `targetAddress`\n     * @param receiverValue msg.value that delivery provider should pass in for call to `targetAddress` (in targetChain currency units)\n     * @param gasLimit gas limit with which to call `targetAddress`.\n     * @return sequence sequence number of published VAA containing delivery instructions\n     */\n    function sendPayloadToEvm(\n        uint16 targetChain,\n        address targetAddress,\n        bytes memory payload,\n        uint256 receiverValue,\n        uint256 gasLimit\n    ) external payable returns (uint64 sequence);\n\n    /**\n     * @notice Publishes an instruction for the default delivery provider\n     * to relay a payload to the address `targetAddress` on chain `targetChain`\n     * with gas limit `gasLimit` and `msg.value` equal to `receiverValue`\n     *\n     * Any refunds (from leftover gas) will be sent to `refundAddress` on chain `refundChain`\n     * `targetAddress` must implement the IWormholeReceiver interface\n     *\n     * This function must be called with `msg.value` equal to `quoteEVMDeliveryPrice(targetChain, receiverValue, gasLimit)`\n     *\n     * @param targetChain in Wormhole Chain ID format\n     * @param targetAddress address to call on targetChain (that implements IWormholeReceiver)\n     * @param payload arbitrary bytes to pass in as parameter in call to `targetAddress`\n     * @param receiverValue msg.value that delivery provider should pass in for call to `targetAddress` (in targetChain currency units)\n     * @param gasLimit gas limit with which to call `targetAddress`. Any units of gas unused will be refunded according to the\n     *        `targetChainRefundPerGasUnused` rate quoted by the delivery provider\n     * @param refundChain The chain to deliver any refund to, in Wormhole Chain ID format\n     * @param refundAddress The address on `refundChain` to deliver any refund to\n     * @return sequence sequence number of published VAA containing delivery instructions\n     */\n    function sendPayloadToEvm(\n        uint16 targetChain,\n        address targetAddress,\n        bytes memory payload,\n        uint256 receiverValue,\n        uint256 gasLimit,\n        uint16 refundChain,\n        address refundAddress\n    ) external payable returns (uint64 sequence);\n\n    /**\n     * @notice Publishes an instruction for the default delivery provider\n     * to relay a payload and VAAs specified by `vaaKeys` to the address `targetAddress` on chain `targetChain`\n     * with gas limit `gasLimit` and `msg.value` equal to `receiverValue`\n     *\n     * `targetAddress` must implement the IWormholeReceiver interface\n     *\n     * This function must be called with `msg.value` equal to `quoteEVMDeliveryPrice(targetChain, receiverValue, gasLimit)`\n     *\n     * Any refunds (from leftover gas) will be paid to the delivery provider. In order to receive the refunds, use the `sendVaasToEvm` function\n     * with `refundChain` and `refundAddress` as parameters\n     *\n     * @param targetChain in Wormhole Chain ID format\n     * @param targetAddress address to call on targetChain (that implements IWormholeReceiver)\n     * @param payload arbitrary bytes to pass in as parameter in call to `targetAddress`\n     * @param receiverValue msg.value that delivery provider should pass in for call to `targetAddress` (in targetChain currency units)\n     * @param gasLimit gas limit with which to call `targetAddress`.\n     * @param vaaKeys Additional VAAs to pass in as parameter in call to `targetAddress`\n     * @return sequence sequence number of published VAA containing delivery instructions\n     */\n    function sendVaasToEvm(\n        uint16 targetChain,\n        address targetAddress,\n        bytes memory payload,\n        uint256 receiverValue,\n        uint256 gasLimit,\n        VaaKey[] memory vaaKeys\n    ) external payable returns (uint64 sequence);\n\n    /**\n     * @notice Publishes an instruction for the default delivery provider\n     * to relay a payload and VAAs specified by `vaaKeys` to the address `targetAddress` on chain `targetChain`\n     * with gas limit `gasLimit` and `msg.value` equal to `receiverValue`\n     *\n     * Any refunds (from leftover gas) will be sent to `refundAddress` on chain `refundChain`\n     * `targetAddress` must implement the IWormholeReceiver interface\n     *\n     * This function must be called with `msg.value` equal to `quoteEVMDeliveryPrice(targetChain, receiverValue, gasLimit)`\n     *\n     * @param targetChain in Wormhole Chain ID format\n     * @param targetAddress address to call on targetChain (that implements IWormholeReceiver)\n     * @param payload arbitrary bytes to pass in as parameter in call to `targetAddress`\n     * @param receiverValue msg.value that delivery provider should pass in for call to `targetAddress` (in targetChain currency units)\n     * @param gasLimit gas limit with which to call `targetAddress`. Any units of gas unused will be refunded according to the\n     *        `targetChainRefundPerGasUnused` rate quoted by the delivery provider\n     * @param vaaKeys Additional VAAs to pass in as parameter in call to `targetAddress`\n     * @param refundChain The chain to deliver any refund to, in Wormhole Chain ID format\n     * @param refundAddress The address on `refundChain` to deliver any refund to\n     * @return sequence sequence number of published VAA containing delivery instructions\n     */\n    function sendVaasToEvm(\n        uint16 targetChain,\n        address targetAddress,\n        bytes memory payload,\n        uint256 receiverValue,\n        uint256 gasLimit,\n        VaaKey[] memory vaaKeys,\n        uint16 refundChain,\n        address refundAddress\n    ) external payable returns (uint64 sequence);\n\n    /**\n     * @notice Publishes an instruction for the delivery provider at `deliveryProviderAddress`\n     * to relay a payload and VAAs specified by `vaaKeys` to the address `targetAddress` on chain `targetChain`\n     * with gas limit `gasLimit` and `msg.value` equal to\n     * receiverValue + (arbitrary amount that is paid for by paymentForExtraReceiverValue of this chain's wei) in targetChain wei.\n     *\n     * Any refunds (from leftover gas) will be sent to `refundAddress` on chain `refundChain`\n     * `targetAddress` must implement the IWormholeReceiver interface\n     *\n     * This function must be called with `msg.value` equal to\n     * quoteEVMDeliveryPrice(targetChain, receiverValue, gasLimit, deliveryProviderAddress) + paymentForExtraReceiverValue\n     *\n     * @param targetChain in Wormhole Chain ID format\n     * @param targetAddress address to call on targetChain (that implements IWormholeReceiver)\n     * @param payload arbitrary bytes to pass in as parameter in call to `targetAddress`\n     * @param receiverValue msg.value that delivery provider should pass in for call to `targetAddress` (in targetChain currency units)\n     * @param paymentForExtraReceiverValue amount (in current chain currency units) to spend on extra receiverValue\n     *        (in addition to the `receiverValue` specified)\n     * @param gasLimit gas limit with which to call `targetAddress`. Any units of gas unused will be refunded according to the\n     *        `targetChainRefundPerGasUnused` rate quoted by the delivery provider\n     * @param refundChain The chain to deliver any refund to, in Wormhole Chain ID format\n     * @param refundAddress The address on `refundChain` to deliver any refund to\n     * @param deliveryProviderAddress The address of the desired delivery provider's implementation of IDeliveryProvider\n     * @param vaaKeys Additional VAAs to pass in as parameter in call to `targetAddress`\n     * @param consistencyLevel Consistency level with which to publish the delivery instructions - see\n     *        https://book.wormhole.com/wormhole/3_coreLayerContracts.html?highlight=consistency#consistency-levels\n     * @return sequence sequence number of published VAA containing delivery instructions\n     */\n    function sendToEvm(\n        uint16 targetChain,\n        address targetAddress,\n        bytes memory payload,\n        uint256 receiverValue,\n        uint256 paymentForExtraReceiverValue,\n        uint256 gasLimit,\n        uint16 refundChain,\n        address refundAddress,\n        address deliveryProviderAddress,\n        VaaKey[] memory vaaKeys,\n        uint8 consistencyLevel\n    ) external payable returns (uint64 sequence);\n\n    /**\n     * @notice Publishes an instruction for the delivery provider at `deliveryProviderAddress`\n     * to relay a payload and external messages specified by `messageKeys` to the address `targetAddress` on chain `targetChain`\n     * with gas limit `gasLimit` and `msg.value` equal to\n     * receiverValue + (arbitrary amount that is paid for by paymentForExtraReceiverValue of this chain's wei) in targetChain wei.\n     *\n     * Any refunds (from leftover gas) will be sent to `refundAddress` on chain `refundChain`\n     * `targetAddress` must implement the IWormholeReceiver interface\n     *\n     * This function must be called with `msg.value` equal to\n     * quoteEVMDeliveryPrice(targetChain, receiverValue, gasLimit, deliveryProviderAddress) + paymentForExtraReceiverValue\n     *\n     * Note: MessageKeys can specify wormhole messages (VaaKeys) or other types of messages (ex. USDC CCTP attestations). Ensure the selected\n     * DeliveryProvider supports all the MessageKey.keyType values specified or it will not be delivered!\n     *\n     * @param targetChain in Wormhole Chain ID format\n     * @param targetAddress address to call on targetChain (that implements IWormholeReceiver)\n     * @param payload arbitrary bytes to pass in as parameter in call to `targetAddress`\n     * @param receiverValue msg.value that delivery provider should pass in for call to `targetAddress` (in targetChain currency units)\n     * @param paymentForExtraReceiverValue amount (in current chain currency units) to spend on extra receiverValue\n     *        (in addition to the `receiverValue` specified)\n     * @param gasLimit gas limit with which to call `targetAddress`. Any units of gas unused will be refunded according to the\n     *        `targetChainRefundPerGasUnused` rate quoted by the delivery provider\n     * @param refundChain The chain to deliver any refund to, in Wormhole Chain ID format\n     * @param refundAddress The address on `refundChain` to deliver any refund to\n     * @param deliveryProviderAddress The address of the desired delivery provider's implementation of IDeliveryProvider\n     * @param messageKeys Additional messagess to pass in as parameter in call to `targetAddress`\n     * @param consistencyLevel Consistency level with which to publish the delivery instructions - see\n     *        https://book.wormhole.com/wormhole/3_coreLayerContracts.html?highlight=consistency#consistency-levels\n     * @return sequence sequence number of published VAA containing delivery instructions\n     */\n    function sendToEvm(\n        uint16 targetChain,\n        address targetAddress,\n        bytes memory payload,\n        uint256 receiverValue,\n        uint256 paymentForExtraReceiverValue,\n        uint256 gasLimit,\n        uint16 refundChain,\n        address refundAddress,\n        address deliveryProviderAddress,\n        MessageKey[] memory messageKeys,\n        uint8 consistencyLevel\n    ) external payable returns (uint64 sequence);\n\n    /**\n     * @notice Publishes an instruction for the delivery provider at `deliveryProviderAddress`\n     * to relay a payload and VAAs specified by `vaaKeys` to the address `targetAddress` on chain `targetChain`\n     * with `msg.value` equal to\n     * receiverValue + (arbitrary amount that is paid for by paymentForExtraReceiverValue of this chain's wei) in targetChain wei.\n     *\n     * Any refunds (from leftover gas) will be sent to `refundAddress` on chain `refundChain`\n     * `targetAddress` must implement the IWormholeReceiver interface\n     *\n     * This function must be called with `msg.value` equal to\n     * quoteDeliveryPrice(targetChain, receiverValue, encodedExecutionParameters, deliveryProviderAddress) + paymentForExtraReceiverValue\n     *\n     * @param targetChain in Wormhole Chain ID format\n     * @param targetAddress address to call on targetChain (that implements IWormholeReceiver), in Wormhole bytes32 format\n     * @param payload arbitrary bytes to pass in as parameter in call to `targetAddress`\n     * @param receiverValue msg.value that delivery provider should pass in for call to `targetAddress` (in targetChain currency units)\n     * @param paymentForExtraReceiverValue amount (in current chain currency units) to spend on extra receiverValue\n     *        (in addition to the `receiverValue` specified)\n     * @param encodedExecutionParameters encoded information on how to execute delivery that may impact pricing\n     *        e.g. for version EVM_V1, this is a struct that encodes the `gasLimit` with which to call `targetAddress`\n     * @param refundChain The chain to deliver any refund to, in Wormhole Chain ID format\n     * @param refundAddress The address on `refundChain` to deliver any refund to, in Wormhole bytes32 format\n     * @param deliveryProviderAddress The address of the desired delivery provider's implementation of IDeliveryProvider\n     * @param vaaKeys Additional VAAs to pass in as parameter in call to `targetAddress`\n     * @param consistencyLevel Consistency level with which to publish the delivery instructions - see\n     *        https://book.wormhole.com/wormhole/3_coreLayerContracts.html?highlight=consistency#consistency-levels\n     * @return sequence sequence number of published VAA containing delivery instructions\n     */\n    function send(\n        uint16 targetChain,\n        bytes32 targetAddress,\n        bytes memory payload,\n        uint256 receiverValue,\n        uint256 paymentForExtraReceiverValue,\n        bytes memory encodedExecutionParameters,\n        uint16 refundChain,\n        bytes32 refundAddress,\n        address deliveryProviderAddress,\n        VaaKey[] memory vaaKeys,\n        uint8 consistencyLevel\n    ) external payable returns (uint64 sequence);\n\n    /**\n     * @notice Publishes an instruction for the delivery provider at `deliveryProviderAddress`\n     * to relay a payload and VAAs specified by `vaaKeys` to the address `targetAddress` on chain `targetChain`\n     * with `msg.value` equal to\n     * receiverValue + (arbitrary amount that is paid for by paymentForExtraReceiverValue of this chain's wei) in targetChain wei.\n     *\n     * Any refunds (from leftover gas) will be sent to `refundAddress` on chain `refundChain`\n     * `targetAddress` must implement the IWormholeReceiver interface\n     *\n     * This function must be called with `msg.value` equal to\n     * quoteDeliveryPrice(targetChain, receiverValue, encodedExecutionParameters, deliveryProviderAddress) + paymentForExtraReceiverValue\n     *\n     * Note: MessageKeys can specify wormhole messages (VaaKeys) or other types of messages (ex. USDC CCTP attestations). Ensure the selected\n     * DeliveryProvider supports all the MessageKey.keyType values specified or it will not be delivered!\n     *\n     * @param targetChain in Wormhole Chain ID format\n     * @param targetAddress address to call on targetChain (that implements IWormholeReceiver), in Wormhole bytes32 format\n     * @param payload arbitrary bytes to pass in as parameter in call to `targetAddress`\n     * @param receiverValue msg.value that delivery provider should pass in for call to `targetAddress` (in targetChain currency units)\n     * @param paymentForExtraReceiverValue amount (in current chain currency units) to spend on extra receiverValue\n     *        (in addition to the `receiverValue` specified)\n     * @param encodedExecutionParameters encoded information on how to execute delivery that may impact pricing\n     *        e.g. for version EVM_V1, this is a struct that encodes the `gasLimit` with which to call `targetAddress`\n     * @param refundChain The chain to deliver any refund to, in Wormhole Chain ID format\n     * @param refundAddress The address on `refundChain` to deliver any refund to, in Wormhole bytes32 format\n     * @param deliveryProviderAddress The address of the desired delivery provider's implementation of IDeliveryProvider\n     * @param messageKeys Additional messagess to pass in as parameter in call to `targetAddress`\n     * @param consistencyLevel Consistency level with which to publish the delivery instructions - see\n     *        https://book.wormhole.com/wormhole/3_coreLayerContracts.html?highlight=consistency#consistency-levels\n     * @return sequence sequence number of published VAA containing delivery instructions\n     */\n    function send(\n        uint16 targetChain,\n        bytes32 targetAddress,\n        bytes memory payload,\n        uint256 receiverValue,\n        uint256 paymentForExtraReceiverValue,\n        bytes memory encodedExecutionParameters,\n        uint16 refundChain,\n        bytes32 refundAddress,\n        address deliveryProviderAddress,\n        MessageKey[] memory messageKeys,\n        uint8 consistencyLevel\n    ) external payable returns (uint64 sequence);\n\n    /**\n     * @notice Requests a previously published delivery instruction to be redelivered\n     * (e.g. with a different delivery provider)\n     *\n     * This function must be called with `msg.value` equal to\n     * quoteEVMDeliveryPrice(targetChain, newReceiverValue, newGasLimit, newDeliveryProviderAddress)\n     *\n     *  @notice *** This will only be able to succeed if the following is true **\n     *         - newGasLimit >= gas limit of the old instruction\n     *         - newReceiverValue >= receiver value of the old instruction\n     *         - newDeliveryProvider's `targetChainRefundPerGasUnused` >= old relay provider's `targetChainRefundPerGasUnused`\n     *\n     * @param deliveryVaaKey VaaKey identifying the wormhole message containing the\n     *        previously published delivery instructions\n     * @param targetChain The target chain that the original delivery targeted. Must match targetChain from original delivery instructions\n     * @param newReceiverValue new msg.value that delivery provider should pass in for call to `targetAddress` (in targetChain currency units)\n     * @param newGasLimit gas limit with which to call `targetAddress`. Any units of gas unused will be refunded according to the\n     *        `targetChainRefundPerGasUnused` rate quoted by the delivery provider, to the refund chain and address specified in the original request\n     * @param newDeliveryProviderAddress The address of the desired delivery provider's implementation of IDeliveryProvider\n     * @return sequence sequence number of published VAA containing redelivery instructions\n     *\n     * @notice *** This will only be able to succeed if the following is true **\n     *         - newGasLimit >= gas limit of the old instruction\n     *         - newReceiverValue >= receiver value of the old instruction\n     */\n    function resendToEvm(\n        VaaKey memory deliveryVaaKey,\n        uint16 targetChain,\n        uint256 newReceiverValue,\n        uint256 newGasLimit,\n        address newDeliveryProviderAddress\n    ) external payable returns (uint64 sequence);\n\n    /**\n     * @notice Requests a previously published delivery instruction to be redelivered\n     *\n     *\n     * This function must be called with `msg.value` equal to\n     * quoteDeliveryPrice(targetChain, newReceiverValue, newEncodedExecutionParameters, newDeliveryProviderAddress)\n     *\n     * @param deliveryVaaKey VaaKey identifying the wormhole message containing the\n     *        previously published delivery instructions\n     * @param targetChain The target chain that the original delivery targeted. Must match targetChain from original delivery instructions\n     * @param newReceiverValue new msg.value that delivery provider should pass in for call to `targetAddress` (in targetChain currency units)\n     * @param newEncodedExecutionParameters new encoded information on how to execute delivery that may impact pricing\n     *        e.g. for version EVM_V1, this is a struct that encodes the `gasLimit` with which to call `targetAddress`\n     * @param newDeliveryProviderAddress The address of the desired delivery provider's implementation of IDeliveryProvider\n     * @return sequence sequence number of published VAA containing redelivery instructions\n     *\n     *  @notice *** This will only be able to succeed if the following is true **\n     *         - (For EVM_V1) newGasLimit >= gas limit of the old instruction\n     *         - newReceiverValue >= receiver value of the old instruction\n     *         - (For EVM_V1) newDeliveryProvider's `targetChainRefundPerGasUnused` >= old relay provider's `targetChainRefundPerGasUnused`\n     */\n    function resend(\n        VaaKey memory deliveryVaaKey,\n        uint16 targetChain,\n        uint256 newReceiverValue,\n        bytes memory newEncodedExecutionParameters,\n        address newDeliveryProviderAddress\n    ) external payable returns (uint64 sequence);\n\n    /**\n     * @notice Returns the price to request a relay to chain `targetChain`, using the default delivery provider\n     *\n     * @param targetChain in Wormhole Chain ID format\n     * @param receiverValue msg.value that delivery provider should pass in for call to `targetAddress` (in targetChain currency units)\n     * @param gasLimit gas limit with which to call `targetAddress`.\n     * @return nativePriceQuote Price, in units of current chain currency, that the delivery provider charges to perform the relay\n     * @return targetChainRefundPerGasUnused amount of target chain currency that will be refunded per unit of gas unused,\n     *         if a refundAddress is specified.\n     *         Note: This value can be overridden by the delivery provider on the target chain. The returned value here should be considered to be a\n     *         promise by the delivery provider of the amount of refund per gas unused that will be returned to the refundAddress at the target chain.\n     *         If a delivery provider decides to override, this will be visible as part of the emitted Delivery event on the target chain.\n     */\n    function quoteEVMDeliveryPrice(\n        uint16 targetChain,\n        uint256 receiverValue,\n        uint256 gasLimit\n    )\n        external\n        view\n        returns (\n            uint256 nativePriceQuote,\n            uint256 targetChainRefundPerGasUnused\n        );\n\n    /**\n     * @notice Returns the price to request a relay to chain `targetChain`, using delivery provider `deliveryProviderAddress`\n     *\n     * @param targetChain in Wormhole Chain ID format\n     * @param receiverValue msg.value that delivery provider should pass in for call to `targetAddress` (in targetChain currency units)\n     * @param gasLimit gas limit with which to call `targetAddress`.\n     * @param deliveryProviderAddress The address of the desired delivery provider's implementation of IDeliveryProvider\n     * @return nativePriceQuote Price, in units of current chain currency, that the delivery provider charges to perform the relay\n     * @return targetChainRefundPerGasUnused amount of target chain currency that will be refunded per unit of gas unused,\n     *         if a refundAddress is specified\n     *         Note: This value can be overridden by the delivery provider on the target chain. The returned value here should be considered to be a\n     *         promise by the delivery provider of the amount of refund per gas unused that will be returned to the refundAddress at the target chain.\n     *         If a delivery provider decides to override, this will be visible as part of the emitted Delivery event on the target chain.\n     */\n    function quoteEVMDeliveryPrice(\n        uint16 targetChain,\n        uint256 receiverValue,\n        uint256 gasLimit,\n        address deliveryProviderAddress\n    )\n        external\n        view\n        returns (\n            uint256 nativePriceQuote,\n            uint256 targetChainRefundPerGasUnused\n        );\n\n    /**\n     * @notice Returns the price to request a relay to chain `targetChain`, using delivery provider `deliveryProviderAddress`\n     *\n     * @param targetChain in Wormhole Chain ID format\n     * @param receiverValue msg.value that delivery provider should pass in for call to `targetAddress` (in targetChain currency units)\n     * @param encodedExecutionParameters encoded information on how to execute delivery that may impact pricing\n     *        e.g. for version EVM_V1, this is a struct that encodes the `gasLimit` with which to call `targetAddress`\n     * @param deliveryProviderAddress The address of the desired delivery provider's implementation of IDeliveryProvider\n     * @return nativePriceQuote Price, in units of current chain currency, that the delivery provider charges to perform the relay\n     * @return encodedExecutionInfo encoded information on how the delivery will be executed\n     *        e.g. for version EVM_V1, this is a struct that encodes the `gasLimit` and `targetChainRefundPerGasUnused`\n     *             (which is the amount of target chain currency that will be refunded per unit of gas unused,\n     *              if a refundAddress is specified)\n     */\n    function quoteDeliveryPrice(\n        uint16 targetChain,\n        uint256 receiverValue,\n        bytes memory encodedExecutionParameters,\n        address deliveryProviderAddress\n    )\n        external\n        view\n        returns (uint256 nativePriceQuote, bytes memory encodedExecutionInfo);\n\n    /**\n     * @notice Returns the (extra) amount of target chain currency that `targetAddress`\n     * will be called with, if the `paymentForExtraReceiverValue` field is set to `currentChainAmount`\n     *\n     * @param targetChain in Wormhole Chain ID format\n     * @param currentChainAmount The value that `paymentForExtraReceiverValue` will be set to\n     * @param deliveryProviderAddress The address of the desired delivery provider's implementation of IDeliveryProvider\n     * @return targetChainAmount The amount such that if `targetAddress` will be called with `msg.value` equal to\n     *         receiverValue + targetChainAmount\n     */\n    function quoteNativeForChain(\n        uint16 targetChain,\n        uint256 currentChainAmount,\n        address deliveryProviderAddress\n    ) external view returns (uint256 targetChainAmount);\n\n    /**\n     * @notice Returns the address of the current default delivery provider\n     * @return deliveryProvider The address of (the default delivery provider)'s contract on this source\n     *   chain. This must be a contract that implements IDeliveryProvider.\n     */\n    function getDefaultDeliveryProvider()\n        external\n        view\n        returns (address deliveryProvider);\n}\n\n/**\n * @title IWormholeRelayerDelivery\n * @notice The interface to execute deliveries. Only relevant for Delivery Providers\n */\ninterface IWormholeRelayerDelivery is IWormholeRelayerBase {\n    enum DeliveryStatus {\n        SUCCESS,\n        RECEIVER_FAILURE\n    }\n\n    enum RefundStatus {\n        REFUND_SENT,\n        REFUND_FAIL,\n        CROSS_CHAIN_REFUND_SENT,\n        CROSS_CHAIN_REFUND_FAIL_PROVIDER_NOT_SUPPORTED,\n        CROSS_CHAIN_REFUND_FAIL_NOT_ENOUGH,\n        NO_REFUND_REQUESTED\n    }\n\n    /**\n     * @custom:member recipientContract - The target contract address\n     * @custom:member sourceChain - The chain which this delivery was requested from (in wormhole\n     *     ChainID format)\n     * @custom:member sequence - The wormhole sequence number of the delivery VAA on the source chain\n     *     corresponding to this delivery request\n     * @custom:member deliveryVaaHash - The hash of the delivery VAA corresponding to this delivery\n     *     request\n     * @custom:member gasUsed - The amount of gas that was used to call your target contract\n     * @custom:member status:\n     *   - RECEIVER_FAILURE, if the target contract reverts\n     *   - SUCCESS, if the target contract doesn't revert\n     * @custom:member additionalStatusInfo:\n     *   - If status is SUCCESS, then this is empty.\n     *   - If status is RECEIVER_FAILURE, this is `RETURNDATA_TRUNCATION_THRESHOLD` bytes of the\n     *       return data (i.e. potentially truncated revert reason information).\n     * @custom:member refundStatus - Result of the refund. REFUND_SUCCESS or REFUND_FAIL are for\n     *     refunds where targetChain=refundChain; the others are for targetChain!=refundChain,\n     *     where a cross chain refund is necessary, or if the default code path is used where no refund is requested (NO_REFUND_REQUESTED)\n     * @custom:member overridesInfo:\n     *   - If not an override: empty bytes array\n     *   - Otherwise: An encoded `DeliveryOverride`\n     */\n    event Delivery(\n        address indexed recipientContract,\n        uint16 indexed sourceChain,\n        uint64 indexed sequence,\n        bytes32 deliveryVaaHash,\n        DeliveryStatus status,\n        uint256 gasUsed,\n        RefundStatus refundStatus,\n        bytes additionalStatusInfo,\n        bytes overridesInfo\n    );\n\n    /**\n     * @notice The delivery provider calls `deliver` to relay messages as described by one delivery instruction\n     *\n     * The delivery provider must pass in the specified (by VaaKeys[]) signed wormhole messages (VAAs) from the source chain\n     * as well as the signed wormhole message with the delivery instructions (the delivery VAA)\n     *\n     * The messages will be relayed to the target address (with the specified gas limit and receiver value) iff the following checks are met:\n     * - the delivery VAA has a valid signature\n     * - the delivery VAA's emitter is one of these WormholeRelayer contracts\n     * - the delivery provider passed in at least enough of this chain's currency as msg.value (enough meaning the maximum possible refund)\n     * - the instruction's target chain is this chain\n     * - the relayed signed VAAs match the descriptions in container.messages (the VAA hashes match, or the emitter address, sequence number pair matches, depending on the description given)\n     *\n     * @param encodedVMs - An array of signed wormhole messages (all from the same source chain\n     *     transaction)\n     * @param encodedDeliveryVAA - Signed wormhole message from the source chain's WormholeRelayer\n     *     contract with payload being the encoded delivery instruction container\n     * @param relayerRefundAddress - The address to which any refunds to the delivery provider\n     *     should be sent\n     * @param deliveryOverrides - Optional overrides field which must be either an empty bytes array or\n     *     an encoded DeliveryOverride struct\n     */\n    function deliver(\n        bytes[] memory encodedVMs,\n        bytes memory encodedDeliveryVAA,\n        address payable relayerRefundAddress,\n        bytes memory deliveryOverrides\n    ) external payable;\n}\n\ninterface IWormholeRelayer is IWormholeRelayerDelivery, IWormholeRelayerSend {}\n\n/*\n *  Errors thrown by IWormholeRelayer contract\n */\n\n// Bound chosen by the following formula: `memoryWord * 4 + selectorSize`.\n// This means that an error identifier plus four fixed size arguments should be available to developers.\n// In the case of a `require` revert with error message, this should provide 2 memory word's worth of data.\nuint256 constant RETURNDATA_TRUNCATION_THRESHOLD = 132;\n\n//When msg.value was not equal to `delivery provider's quoted delivery price` + `paymentForExtraReceiverValue`\nerror InvalidMsgValue(uint256 msgValue, uint256 totalFee);\n\nerror RequestedGasLimitTooLow();\n\nerror DeliveryProviderDoesNotSupportTargetChain(\n    address relayer,\n    uint16 chainId\n);\nerror DeliveryProviderCannotReceivePayment();\nerror DeliveryProviderDoesNotSupportMessageKeyType(uint8 keyType);\n\n//When calling `delivery()` a second time even though a delivery is already in progress\nerror ReentrantDelivery(address msgSender, address lockedBy);\n\nerror InvalidPayloadId(uint8 parsed, uint8 expected);\nerror InvalidPayloadLength(uint256 received, uint256 expected);\nerror InvalidVaaKeyType(uint8 parsed);\nerror TooManyMessageKeys(uint256 numMessageKeys);\n\nerror InvalidDeliveryVaa(string reason);\n//When the delivery VAA (signed wormhole message with delivery instructions) was not emitted by the\n//  registered WormholeRelayer contract\nerror InvalidEmitter(bytes32 emitter, bytes32 registered, uint16 chainId);\nerror MessageKeysLengthDoesNotMatchMessagesLength(uint256 keys, uint256 vaas);\nerror VaaKeysDoNotMatchVaas(uint8 index);\n//When someone tries to call an external function of the WormholeRelayer that is only intended to be\n//  called by the WormholeRelayer itself (to allow retroactive reverts for atomicity)\nerror RequesterNotWormholeRelayer();\n\n//When trying to relay a `DeliveryInstruction` to any other chain but the one it was specified for\nerror TargetChainIsNotThisChain(uint16 targetChain);\n//When a `DeliveryOverride` contains a gas limit that's less than the original\nerror InvalidOverrideGasLimit();\n//When a `DeliveryOverride` contains a receiver value that's less than the original\nerror InvalidOverrideReceiverValue();\n//When a `DeliveryOverride` contains a 'refund per unit of gas unused' that's less than the original\nerror InvalidOverrideRefundPerGasUnused();\n\n//When the delivery provider doesn't pass in sufficient funds (i.e. msg.value does not cover the\n// maximum possible refund to the user)\nerror InsufficientRelayerFunds(uint256 msgValue, uint256 minimum);\n\n//When a bytes32 field can't be converted into a 20 byte EVM address, because the 12 padding bytes\n//  are non-zero (duplicated from Utils.sol)\nerror NotAnEvmAddress(bytes32);\n"
      },
      "src/interfaces/IRateLimiter.sol": {
        "content": "// SPDX-License-Identifier: Apache 2\npragma solidity >=0.8.8 <0.9.0;\n\nimport \"../libraries/TrimmedAmount.sol\";\nimport \"../libraries/TransceiverStructs.sol\";\n\ninterface IRateLimiter {\n    /// @notice Not enough capacity to send the transfer.\n    /// @dev Selector 0x26fb55dd.\n    /// @param currentCapacity The current capacity.\n    /// @param amount The amount of the transfer.\n    error NotEnoughCapacity(uint256 currentCapacity, uint256 amount);\n\n    /// @notice Outbound transfer is not longer queued.\n    /// @dev Selector 0xbfd5f462.\n    /// @param queueSequence The sequence of the queue.\n    error OutboundQueuedTransferNotFound(uint64 queueSequence);\n\n    /// @notice Cannot complete the outbound transfer, the transfer is still queued.\n    /// @dev Selector 0xc06cf05f.\n    /// @param queueSequence The sequence of the queue.\n    /// @param transferTimestamp The timestamp of when the transfer was queued.\n    error OutboundQueuedTransferStillQueued(uint64 queueSequence, uint256 transferTimestamp);\n\n    /// @notice The inbound transfer is not longer queued.\n    /// @dev Selector 0xc06f2bc0.\n    /// @param digest The digest of the transfer.\n    error InboundQueuedTransferNotFound(bytes32 digest);\n\n    /// @notice The transfer is still queued.\n    /// @dev Selector 0xe5b9ce80.\n    /// @param digest The digest of the transfer.\n    /// @param transferTimestamp The timestamp of the transfer.\n    error InboundQueuedTransferStillQueued(bytes32 digest, uint256 transferTimestamp);\n\n    /// @notice The new capacity cannot exceed the limit.\n    /// @dev Selector 0x0f85ba52.\n    /// @param newCurrentCapacity The new current capacity.\n    /// @param newLimit The new limit.\n    error CapacityCannotExceedLimit(TrimmedAmount newCurrentCapacity, TrimmedAmount newLimit);\n\n    /// @notice If the rate limiting behaviour isn't explicitly defined in the constructor.\n    /// @dev Selector 0xe543ef05.\n    error UndefinedRateLimiting();\n\n    /// @notice Parameters used in determining rate limits and queuing.\n    /// @dev\n    ///    - limit: current rate limit value.\n    ///    - currentCapacity: the current capacity left.\n    ///    - lastTxTimestamp: the timestamp of when the\n    ///                       capacity was previously consumption.\n    struct RateLimitParams {\n        TrimmedAmount limit;\n        TrimmedAmount currentCapacity;\n        uint64 lastTxTimestamp;\n    }\n\n    /// @notice Parameters for an outbound queued transfer.\n    /// @dev\n    ///    - recipient: the recipient of the transfer.\n    ///    - amount: the amount of the transfer, trimmed.\n    ///    - txTimestamp: the timestamp of the transfer.\n    ///    - recipientChain: the chain of the recipient.\n    ///    - sender: the sender of the transfer.\n    ///    - transceiverInstructions: additional instructions to be forwarded to the recipient chain.\n    struct OutboundQueuedTransfer {\n        bytes32 recipient;\n        bytes32 refundAddress;\n        TrimmedAmount amount;\n        uint64 txTimestamp;\n        uint16 recipientChain;\n        address sender;\n        bytes transceiverInstructions;\n    }\n\n    /// @notice Parameters for an inbound queued transfer.\n    /// @dev\n    ///   - amount: the amount of the transfer, trimmed.\n    ///   - txTimestamp: the timestamp of the transfer.\n    ///   - recipient: the recipient of the transfer.\n    struct InboundQueuedTransfer {\n        TrimmedAmount amount;\n        uint64 txTimestamp;\n        address recipient;\n    }\n\n    function getCurrentOutboundCapacity() external view returns (uint256);\n\n    function getOutboundQueuedTransfer(uint64 queueSequence)\n        external\n        view\n        returns (OutboundQueuedTransfer memory);\n\n    function getCurrentInboundCapacity(uint16 chainId) external view returns (uint256);\n\n    function getInboundQueuedTransfer(bytes32 digest)\n        external\n        view\n        returns (InboundQueuedTransfer memory);\n}\n"
      },
      "src/interfaces/IRateLimiterEvents.sol": {
        "content": "// SPDX-License-Identifier: Apache 2\npragma solidity >=0.8.8 <0.9.0;\n\nimport \"../libraries/TrimmedAmount.sol\";\n\ninterface IRateLimiterEvents {\n    /// @notice Emitted when an inbound transfer is queued\n    /// @dev Topic0\n    ///      0x7f63c9251d82a933210c2b6d0b0f116252c3c116788120e64e8e8215df6f3162.\n    /// @param digest The digest of the message.\n    event InboundTransferQueued(bytes32 digest);\n\n    /// @notice Emitted whenn an outbound transfer is queued.\n    /// @dev Topic0\n    ///      0x69add1952a6a6b9cb86f04d05f0cb605cbb469a50ae916139d34495a9991481f.\n    /// @param queueSequence The location of the transfer in the queue.\n    event OutboundTransferQueued(uint64 queueSequence);\n\n    /// @notice Emitted when an outbound transfer is rate limited.\n    /// @dev Topic0\n    ///      0xf33512b84e24a49905c26c6991942fc5a9652411769fc1e448f967cdb049f08a.\n    /// @param sender The initial sender of the transfer.\n    /// @param amount The amount to be transferred.\n    /// @param currentCapacity The capacity left for transfers within the 24-hour window.\n    event OutboundTransferRateLimited(\n        address indexed sender, uint64 sequence, uint256 amount, uint256 currentCapacity\n    );\n}\n"
      },
      "src/libraries/TransceiverHelpers.sol": {
        "content": "// SPDX-License-Identifier: Apache 2\npragma solidity >=0.8.8 <0.9.0;\n\nerror InvalidFork(uint256 evmChainId, uint256 blockChainId);\n\nfunction checkFork(uint256 evmChainId) view {\n    if (isFork(evmChainId)) {\n        revert InvalidFork(evmChainId, block.chainid);\n    }\n}\n\nfunction isFork(uint256 evmChainId) view returns (bool) {\n    return evmChainId != block.chainid;\n}\n\nfunction min(uint256 a, uint256 b) pure returns (uint256) {\n    return a < b ? a : b;\n}\n\n// @dev Count the number of set bits in a uint64\nfunction countSetBits(uint64 x) pure returns (uint8 count) {\n    while (x != 0) {\n        x &= x - 1;\n        count++;\n    }\n\n    return count;\n}\n"
      },
      "src/libraries/TransceiverStructs.sol": {
        "content": "// SPDX-License-Identifier: Apache 2\npragma solidity >=0.8.8 <0.9.0;\n\nimport \"wormhole-solidity-sdk/libraries/BytesParsing.sol\";\nimport \"./TrimmedAmount.sol\";\n\nlibrary TransceiverStructs {\n    using BytesParsing for bytes;\n    using TrimmedAmountLib for TrimmedAmount;\n\n    /// @notice Error thrown when the payload length exceeds the allowed maximum.\n    /// @dev Selector 0xa3419691.\n    /// @param size The size of the payload.\n    error PayloadTooLong(uint256 size);\n\n    /// @notice Error thrown when the prefix of an encoded message\n    ///         does not match the expected value.\n    /// @dev Selector 0x56d2569d.\n    /// @param prefix The prefix that was found in the encoded message.\n    error IncorrectPrefix(bytes4 prefix);\n\n    /// @notice Error thrown when the transceiver instructions aren't\n    ///         encoded with strictly increasing indices\n    /// @dev Selector 0x0555a4b9.\n    /// @param lastIndex Last parsed instruction index\n    /// @param instructionIndex The instruction index that was unordered\n    error UnorderedInstructions(uint256 lastIndex, uint256 instructionIndex);\n\n    /// @notice Error thrown when a transceiver instruction index\n    ///         is greater than the number of registered transceivers\n    /// @dev We index from 0 so if providedIndex == numTransceivers then we're out-of-bounds too\n    /// @dev Selector 0x689f5016.\n    /// @param providedIndex The index specified in the instruction\n    /// @param numTransceivers The number of registered transceivers\n    error InvalidInstructionIndex(uint256 providedIndex, uint256 numTransceivers);\n\n    /// @dev Prefix for all NativeTokenTransfer payloads\n    ///      This is 0x99'N''T''T'\n    bytes4 constant NTT_PREFIX = 0x994E5454;\n\n    /// @dev Message emitted and received by the nttManager contract.\n    ///      The wire format is as follows:\n    ///      - id - 32 bytes\n    ///      - sender - 32 bytes\n    ///      - payloadLength - 2 bytes\n    ///      - payload - `payloadLength` bytes\n    struct NttManagerMessage {\n        /// @notice unique message identifier\n        /// @dev This is incrementally assigned on EVM chains, but this is not\n        /// guaranteed on other runtimes.\n        bytes32 id;\n        /// @notice original message sender address.\n        bytes32 sender;\n        /// @notice payload that corresponds to the type.\n        bytes payload;\n    }\n\n    function nttManagerMessageDigest(\n        uint16 sourceChainId,\n        NttManagerMessage memory m\n    ) public pure returns (bytes32) {\n        return keccak256(abi.encodePacked(sourceChainId, encodeNttManagerMessage(m)));\n    }\n\n    function encodeNttManagerMessage(NttManagerMessage memory m)\n        public\n        pure\n        returns (bytes memory encoded)\n    {\n        if (m.payload.length > type(uint16).max) {\n            revert PayloadTooLong(m.payload.length);\n        }\n        uint16 payloadLength = uint16(m.payload.length);\n        return abi.encodePacked(m.id, m.sender, payloadLength, m.payload);\n    }\n\n    /// @notice Parse a NttManagerMessage.\n    /// @param encoded The byte array corresponding to the encoded message\n    /// @return nttManagerMessage The parsed NttManagerMessage struct.\n    function parseNttManagerMessage(bytes memory encoded)\n        public\n        pure\n        returns (NttManagerMessage memory nttManagerMessage)\n    {\n        uint256 offset = 0;\n        (nttManagerMessage.id, offset) = encoded.asBytes32Unchecked(offset);\n        (nttManagerMessage.sender, offset) = encoded.asBytes32Unchecked(offset);\n        uint256 payloadLength;\n        (payloadLength, offset) = encoded.asUint16Unchecked(offset);\n        (nttManagerMessage.payload, offset) = encoded.sliceUnchecked(offset, payloadLength);\n        encoded.checkLength(offset);\n    }\n\n    /// @dev Native Token Transfer payload.\n    ///      The wire format is as follows:\n    ///      - NTT_PREFIX - 4 bytes\n    ///      - numDecimals - 1 byte\n    ///      - amount - 8 bytes\n    ///      - sourceToken - 32 bytes\n    ///      - to - 32 bytes\n    ///      - toChain - 2 bytes\n    struct NativeTokenTransfer {\n        /// @notice Amount being transferred (big-endian u64 and u8 for decimals)\n        TrimmedAmount amount;\n        /// @notice Source chain token address.\n        bytes32 sourceToken;\n        /// @notice Address of the recipient.\n        bytes32 to;\n        /// @notice Chain ID of the recipient\n        uint16 toChain;\n    }\n\n    function encodeNativeTokenTransfer(NativeTokenTransfer memory m)\n        public\n        pure\n        returns (bytes memory encoded)\n    {\n        // The `amount` and `decimals` fields are encoded in reverse order compared to how they are declared in the\n        // `TrimmedAmount` type. This is consistent with the Rust NTT implementation.\n        TrimmedAmount transferAmount = m.amount;\n        return abi.encodePacked(\n            NTT_PREFIX,\n            transferAmount.getDecimals(),\n            transferAmount.getAmount(),\n            m.sourceToken,\n            m.to,\n            m.toChain\n        );\n    }\n\n    /// @dev Parse a NativeTokenTransfer.\n    /// @param encoded The byte array corresponding to the encoded message\n    /// @return nativeTokenTransfer The parsed NativeTokenTransfer struct.\n    function parseNativeTokenTransfer(bytes memory encoded)\n        public\n        pure\n        returns (NativeTokenTransfer memory nativeTokenTransfer)\n    {\n        uint256 offset = 0;\n        bytes4 prefix;\n        (prefix, offset) = encoded.asBytes4Unchecked(offset);\n        if (prefix != NTT_PREFIX) {\n            revert IncorrectPrefix(prefix);\n        }\n\n        // The `amount` and `decimals` fields are parsed in reverse order compared to how they are declared in the\n        // `TrimmedAmount` struct. This is consistent with the Rust NTT implementation.\n        uint8 numDecimals;\n        (numDecimals, offset) = encoded.asUint8Unchecked(offset);\n        uint64 amount;\n        (amount, offset) = encoded.asUint64Unchecked(offset);\n        nativeTokenTransfer.amount = packTrimmedAmount(amount, numDecimals);\n\n        (nativeTokenTransfer.sourceToken, offset) = encoded.asBytes32Unchecked(offset);\n        (nativeTokenTransfer.to, offset) = encoded.asBytes32Unchecked(offset);\n        (nativeTokenTransfer.toChain, offset) = encoded.asUint16Unchecked(offset);\n        encoded.checkLength(offset);\n    }\n\n    /// @dev Message emitted by Transceiver implementations.\n    ///      Each message includes an Transceiver-specified 4-byte prefix.\n    ///      The wire format is as follows:\n    ///      - prefix - 4 bytes\n    ///      - sourceNttManagerAddress - 32 bytes\n    ///      - recipientNttManagerAddress - 32 bytes\n    ///      - nttManagerPayloadLength - 2 bytes\n    ///      - nttManagerPayload - `nttManagerPayloadLength` bytes\n    ///      - transceiverPayloadLength - 2 bytes\n    ///      - transceiverPayload - `transceiverPayloadLength` bytes\n    struct TransceiverMessage {\n        /// @notice Address of the NttManager contract that emitted this message.\n        bytes32 sourceNttManagerAddress;\n        /// @notice Address of the NttManager contract that receives this message.\n        bytes32 recipientNttManagerAddress;\n        /// @notice Payload provided to the Transceiver contract by the NttManager contract.\n        bytes nttManagerPayload;\n        /// @notice Optional payload that the transceiver can encode and use for its own message passing purposes.\n        bytes transceiverPayload;\n    }\n\n    // @notice Encodes an Transceiver message for communication between the\n    //         NttManager and the Transceiver.\n    // @param m The TransceiverMessage struct containing the message details.\n    // @return encoded The byte array corresponding to the encoded message.\n    // @custom:throw PayloadTooLong if the length of transceiverId, nttManagerPayload,\n    //         or transceiverPayload exceeds the allowed maximum.\n    function encodeTransceiverMessage(\n        bytes4 prefix,\n        TransceiverMessage memory m\n    ) public pure returns (bytes memory encoded) {\n        if (m.nttManagerPayload.length > type(uint16).max) {\n            revert PayloadTooLong(m.nttManagerPayload.length);\n        }\n        uint16 nttManagerPayloadLength = uint16(m.nttManagerPayload.length);\n\n        if (m.transceiverPayload.length > type(uint16).max) {\n            revert PayloadTooLong(m.transceiverPayload.length);\n        }\n        uint16 transceiverPayloadLength = uint16(m.transceiverPayload.length);\n\n        return abi.encodePacked(\n            prefix,\n            m.sourceNttManagerAddress,\n            m.recipientNttManagerAddress,\n            nttManagerPayloadLength,\n            m.nttManagerPayload,\n            transceiverPayloadLength,\n            m.transceiverPayload\n        );\n    }\n\n    function buildAndEncodeTransceiverMessage(\n        bytes4 prefix,\n        bytes32 sourceNttManagerAddress,\n        bytes32 recipientNttManagerAddress,\n        bytes memory nttManagerMessage,\n        bytes memory transceiverPayload\n    ) public pure returns (TransceiverMessage memory, bytes memory) {\n        TransceiverMessage memory transceiverMessage = TransceiverMessage({\n            sourceNttManagerAddress: sourceNttManagerAddress,\n            recipientNttManagerAddress: recipientNttManagerAddress,\n            nttManagerPayload: nttManagerMessage,\n            transceiverPayload: transceiverPayload\n        });\n        bytes memory encoded = encodeTransceiverMessage(prefix, transceiverMessage);\n        return (transceiverMessage, encoded);\n    }\n\n    /// @dev Parses an encoded message and extracts information into an TransceiverMessage struct.\n    /// @param encoded The encoded bytes containing information about the TransceiverMessage.\n    /// @return transceiverMessage The parsed TransceiverMessage struct.\n    /// @custom:throw IncorrectPrefix if the prefix of the encoded message does not\n    ///         match the expected prefix.\n    function parseTransceiverMessage(\n        bytes4 expectedPrefix,\n        bytes memory encoded\n    ) internal pure returns (TransceiverMessage memory transceiverMessage) {\n        uint256 offset = 0;\n        bytes4 prefix;\n\n        (prefix, offset) = encoded.asBytes4Unchecked(offset);\n\n        if (prefix != expectedPrefix) {\n            revert IncorrectPrefix(prefix);\n        }\n\n        (transceiverMessage.sourceNttManagerAddress, offset) = encoded.asBytes32Unchecked(offset);\n        (transceiverMessage.recipientNttManagerAddress, offset) = encoded.asBytes32Unchecked(offset);\n        uint16 nttManagerPayloadLength;\n        (nttManagerPayloadLength, offset) = encoded.asUint16Unchecked(offset);\n        (transceiverMessage.nttManagerPayload, offset) =\n            encoded.sliceUnchecked(offset, nttManagerPayloadLength);\n        uint16 transceiverPayloadLength;\n        (transceiverPayloadLength, offset) = encoded.asUint16Unchecked(offset);\n        (transceiverMessage.transceiverPayload, offset) =\n            encoded.sliceUnchecked(offset, transceiverPayloadLength);\n\n        // Check if the entire byte array has been processed\n        encoded.checkLength(offset);\n    }\n\n    /// @dev Parses the payload of an Transceiver message and returns\n    ///      the parsed NttManagerMessage struct.\n    /// @param expectedPrefix The prefix that should be encoded in the nttManager message.\n    /// @param payload The payload sent across the wire.\n    function parseTransceiverAndNttManagerMessage(\n        bytes4 expectedPrefix,\n        bytes memory payload\n    ) public pure returns (TransceiverMessage memory, NttManagerMessage memory) {\n        // parse the encoded message payload from the Transceiver\n        TransceiverMessage memory parsedTransceiverMessage =\n            parseTransceiverMessage(expectedPrefix, payload);\n\n        // parse the encoded message payload from the NttManager\n        NttManagerMessage memory parsedNttManagerMessage =\n            parseNttManagerMessage(parsedTransceiverMessage.nttManagerPayload);\n\n        return (parsedTransceiverMessage, parsedNttManagerMessage);\n    }\n\n    /// @dev Variable-length transceiver-specific instruction that can be passed by the caller to the nttManager.\n    ///      The index field refers to the index of the registeredTransceiver that this instruction should be passed to.\n    ///      The serialization format is:\n    ///      - index - 1 byte\n    ///      - payloadLength - 1 byte\n    ///      - payload - `payloadLength` bytes\n    struct TransceiverInstruction {\n        uint8 index;\n        bytes payload;\n    }\n\n    function encodeTransceiverInstruction(TransceiverInstruction memory instruction)\n        public\n        pure\n        returns (bytes memory)\n    {\n        if (instruction.payload.length > type(uint8).max) {\n            revert PayloadTooLong(instruction.payload.length);\n        }\n        uint8 payloadLength = uint8(instruction.payload.length);\n        return abi.encodePacked(instruction.index, payloadLength, instruction.payload);\n    }\n\n    function parseTransceiverInstructionUnchecked(\n        bytes memory encoded,\n        uint256 offset\n    ) public pure returns (TransceiverInstruction memory instruction, uint256 nextOffset) {\n        (instruction.index, nextOffset) = encoded.asUint8Unchecked(offset);\n        uint8 instructionLength;\n        (instructionLength, nextOffset) = encoded.asUint8Unchecked(nextOffset);\n        (instruction.payload, nextOffset) = encoded.sliceUnchecked(nextOffset, instructionLength);\n    }\n\n    function parseTransceiverInstructionChecked(bytes memory encoded)\n        public\n        pure\n        returns (TransceiverInstruction memory instruction)\n    {\n        uint256 offset = 0;\n        (instruction, offset) = parseTransceiverInstructionUnchecked(encoded, offset);\n        encoded.checkLength(offset);\n    }\n\n    /// @dev Encode an array of multiple variable-length transceiver-specific instructions.\n    ///      The serialization format is:\n    ///      - instructionsLength - 1 byte\n    ///      - `instructionsLength` number of serialized `TransceiverInstruction` types.\n    function encodeTransceiverInstructions(TransceiverInstruction[] memory instructions)\n        public\n        pure\n        returns (bytes memory)\n    {\n        if (instructions.length > type(uint8).max) {\n            revert PayloadTooLong(instructions.length);\n        }\n        uint256 instructionsLength = instructions.length;\n\n        bytes memory encoded;\n        for (uint256 i = 0; i < instructionsLength; i++) {\n            bytes memory innerEncoded = encodeTransceiverInstruction(instructions[i]);\n            encoded = bytes.concat(encoded, innerEncoded);\n        }\n        return abi.encodePacked(uint8(instructionsLength), encoded);\n    }\n\n    function parseTransceiverInstructions(\n        bytes memory encoded,\n        uint256 numRegisteredTransceivers\n    ) public pure returns (TransceiverInstruction[] memory) {\n        uint256 offset = 0;\n        uint256 instructionsLength;\n        (instructionsLength, offset) = encoded.asUint8Unchecked(offset);\n\n        // We allocate an array with the length of the number of registered transceivers\n        // This gives us the flexibility to not have to pass instructions for transceivers that\n        // don't need them\n        TransceiverInstruction[] memory instructions =\n            new TransceiverInstruction[](numRegisteredTransceivers);\n\n        uint256 lastIndex = 0;\n        for (uint256 i = 0; i < instructionsLength; i++) {\n            TransceiverInstruction memory instruction;\n            (instruction, offset) = parseTransceiverInstructionUnchecked(encoded, offset);\n\n            uint8 instructionIndex = instruction.index;\n\n            // The instructions passed in have to be strictly increasing in terms of transceiver index\n            if (i != 0 && instructionIndex <= lastIndex) {\n                revert UnorderedInstructions(lastIndex, instructionIndex);\n            }\n\n            // Instruction index is out of bounds\n            if (instructionIndex >= numRegisteredTransceivers) {\n                revert InvalidInstructionIndex(instructionIndex, numRegisteredTransceivers);\n            }\n\n            lastIndex = instructionIndex;\n\n            instructions[instructionIndex] = instruction;\n        }\n\n        encoded.checkLength(offset);\n\n        return instructions;\n    }\n\n    struct TransceiverInit {\n        bytes4 transceiverIdentifier;\n        bytes32 nttManagerAddress;\n        uint8 nttManagerMode;\n        bytes32 tokenAddress;\n        uint8 tokenDecimals;\n    }\n\n    function encodeTransceiverInit(TransceiverInit memory init)\n        public\n        pure\n        returns (bytes memory)\n    {\n        return abi.encodePacked(\n            init.transceiverIdentifier,\n            init.nttManagerAddress,\n            init.nttManagerMode,\n            init.tokenAddress,\n            init.tokenDecimals\n        );\n    }\n\n    function decodeTransceiverInit(bytes memory encoded)\n        public\n        pure\n        returns (TransceiverInit memory init)\n    {\n        uint256 offset = 0;\n        (init.transceiverIdentifier, offset) = encoded.asBytes4Unchecked(offset);\n        (init.nttManagerAddress, offset) = encoded.asBytes32Unchecked(offset);\n        (init.nttManagerMode, offset) = encoded.asUint8Unchecked(offset);\n        (init.tokenAddress, offset) = encoded.asBytes32Unchecked(offset);\n        (init.tokenDecimals, offset) = encoded.asUint8Unchecked(offset);\n        encoded.checkLength(offset);\n    }\n\n    struct TransceiverRegistration {\n        bytes4 transceiverIdentifier;\n        uint16 transceiverChainId;\n        bytes32 transceiverAddress;\n    }\n\n    function encodeTransceiverRegistration(TransceiverRegistration memory registration)\n        public\n        pure\n        returns (bytes memory)\n    {\n        return abi.encodePacked(\n            registration.transceiverIdentifier,\n            registration.transceiverChainId,\n            registration.transceiverAddress\n        );\n    }\n\n    function decodeTransceiverRegistration(bytes memory encoded)\n        public\n        pure\n        returns (TransceiverRegistration memory registration)\n    {\n        uint256 offset = 0;\n        (registration.transceiverIdentifier, offset) = encoded.asBytes4Unchecked(offset);\n        (registration.transceiverChainId, offset) = encoded.asUint16Unchecked(offset);\n        (registration.transceiverAddress, offset) = encoded.asBytes32Unchecked(offset);\n        encoded.checkLength(offset);\n    }\n}\n"
      },
      "src/libraries/TrimmedAmount.sol": {
        "content": "// SPDX-License-Identifier: Apache 2\n/// @dev TrimmedAmount is a utility library to handle token amounts with different decimals\npragma solidity >=0.8.8 <0.9.0;\n\nimport \"openzeppelin-contracts/contracts/utils/math/SafeCast.sol\";\n\n/// @dev TrimmedAmount is a bit-packed representation of a token amount and its decimals.\n/// @dev 64 bits: [0 - 64] amount\n/// @dev 8 bits: [64 - 72] decimals\ntype TrimmedAmount is uint72;\n\nusing {gt as >, lt as <, sub as -, add as +, eq as ==, min, unwrap} for TrimmedAmount global;\n\nfunction minUint8(uint8 a, uint8 b) pure returns (uint8) {\n    return a < b ? a : b;\n}\n\n/// @notice Error when the decimals of two TrimmedAmounts are not equal\n/// @dev Selector. b9cdb6c2\n/// @param decimals the decimals of the first TrimmedAmount\n/// @param decimalsOther the decimals of the second TrimmedAmount\nerror NumberOfDecimalsNotEqual(uint8 decimals, uint8 decimalsOther);\n\nuint8 constant TRIMMED_DECIMALS = 8;\n\nfunction unwrap(TrimmedAmount a) pure returns (uint72) {\n    return TrimmedAmount.unwrap(a);\n}\n\nfunction packTrimmedAmount(uint64 amt, uint8 decimals) pure returns (TrimmedAmount) {\n    // cast to u72 first to prevent overflow\n    uint72 amount = uint72(amt);\n    uint72 dec = uint72(decimals);\n\n    // shift the amount to the left 8 bits\n    amount <<= 8;\n\n    return TrimmedAmount.wrap(amount | dec);\n}\n\nfunction eq(TrimmedAmount a, TrimmedAmount b) pure returns (bool) {\n    return TrimmedAmountLib.getAmount(a) == TrimmedAmountLib.getAmount(b)\n        && TrimmedAmountLib.getDecimals(a) == TrimmedAmountLib.getDecimals(b);\n}\n\nfunction checkDecimals(TrimmedAmount a, TrimmedAmount b) pure {\n    uint8 aDecimals = TrimmedAmountLib.getDecimals(a);\n    uint8 bDecimals = TrimmedAmountLib.getDecimals(b);\n    if (aDecimals != bDecimals) {\n        revert NumberOfDecimalsNotEqual(aDecimals, bDecimals);\n    }\n}\n\nfunction gt(TrimmedAmount a, TrimmedAmount b) pure returns (bool) {\n    checkDecimals(a, b);\n\n    return TrimmedAmountLib.getAmount(a) > TrimmedAmountLib.getAmount(b);\n}\n\nfunction lt(TrimmedAmount a, TrimmedAmount b) pure returns (bool) {\n    checkDecimals(a, b);\n\n    return TrimmedAmountLib.getAmount(a) < TrimmedAmountLib.getAmount(b);\n}\n\nfunction sub(TrimmedAmount a, TrimmedAmount b) pure returns (TrimmedAmount) {\n    checkDecimals(a, b);\n\n    return packTrimmedAmount(\n        TrimmedAmountLib.getAmount(a) - TrimmedAmountLib.getAmount(b),\n        TrimmedAmountLib.getDecimals(a)\n    );\n}\n\nfunction add(TrimmedAmount a, TrimmedAmount b) pure returns (TrimmedAmount) {\n    checkDecimals(a, b);\n\n    return packTrimmedAmount(\n        TrimmedAmountLib.getAmount(a) + TrimmedAmountLib.getAmount(b),\n        TrimmedAmountLib.getDecimals(b)\n    );\n}\n\nfunction min(TrimmedAmount a, TrimmedAmount b) pure returns (TrimmedAmount) {\n    checkDecimals(a, b);\n\n    return TrimmedAmountLib.getAmount(a) < TrimmedAmountLib.getAmount(b) ? a : b;\n}\n\nlibrary TrimmedAmountLib {\n    /// @notice Error when the amount to be trimmed is greater than u64MAX.\n    /// @dev Selector 0x08083b2a.\n    /// @param amount The amount to be trimmed.\n    error AmountTooLarge(uint256 amount);\n\n    function getAmount(TrimmedAmount a) internal pure returns (uint64) {\n        // Extract the raw integer value from TrimmedAmount\n        uint72 rawValue = TrimmedAmount.unwrap(a);\n\n        // Right shift to keep only the higher 64 bits\n        uint64 result = uint64(rawValue >> 8);\n        return result;\n    }\n\n    function getDecimals(TrimmedAmount a) internal pure returns (uint8) {\n        return uint8(TrimmedAmount.unwrap(a) & 0xFF);\n    }\n\n    function isNull(TrimmedAmount a) internal pure returns (bool) {\n        return (getAmount(a) == 0 && getDecimals(a) == 0);\n    }\n\n    function saturatingAdd(\n        TrimmedAmount a,\n        TrimmedAmount b\n    ) internal pure returns (TrimmedAmount) {\n        checkDecimals(a, b);\n\n        uint256 saturatedSum;\n        uint64 aAmount = getAmount(a);\n        uint64 bAmount = getAmount(b);\n        unchecked {\n            saturatedSum = uint256(aAmount) + uint256(bAmount);\n            saturatedSum = saturatedSum > type(uint64).max ? type(uint64).max : saturatedSum;\n        }\n\n        return packTrimmedAmount(SafeCast.toUint64(saturatedSum), getDecimals(a));\n    }\n\n    /// @dev scale the amount from original decimals to target decimals (base 10)\n    function scale(\n        uint256 amount,\n        uint8 fromDecimals,\n        uint8 toDecimals\n    ) internal pure returns (uint256) {\n        if (fromDecimals == toDecimals) {\n            return amount;\n        }\n\n        if (fromDecimals > toDecimals) {\n            return amount / (10 ** (fromDecimals - toDecimals));\n        } else {\n            return amount * (10 ** (toDecimals - fromDecimals));\n        }\n    }\n\n    function shift(TrimmedAmount amount, uint8 toDecimals) internal pure returns (TrimmedAmount) {\n        uint8 actualToDecimals = minUint8(TRIMMED_DECIMALS, toDecimals);\n        return packTrimmedAmount(\n            SafeCast.toUint64(scale(getAmount(amount), getDecimals(amount), actualToDecimals)),\n            actualToDecimals\n        );\n    }\n\n    function max(uint8 decimals) internal pure returns (TrimmedAmount) {\n        uint8 actualDecimals = minUint8(TRIMMED_DECIMALS, decimals);\n        return packTrimmedAmount(type(uint64).max, actualDecimals);\n    }\n\n    /// @dev trim the amount to target decimals.\n    ///      The actual resulting decimals is the minimum of TRIMMED_DECIMALS,\n    ///      fromDecimals, and toDecimals. This ensures that no dust is\n    ///      destroyed on either side of the transfer.\n    /// @param amt the amount to be trimmed\n    /// @param fromDecimals the original decimals of the amount\n    /// @param toDecimals the target decimals of the amount\n    /// @return TrimmedAmount uint72 value type bit-packed with decimals\n    function trim(\n        uint256 amt,\n        uint8 fromDecimals,\n        uint8 toDecimals\n    ) internal pure returns (TrimmedAmount) {\n        uint8 actualToDecimals = minUint8(minUint8(TRIMMED_DECIMALS, fromDecimals), toDecimals);\n        uint256 amountScaled = scale(amt, fromDecimals, actualToDecimals);\n\n        // NOTE: amt after trimming must fit into uint64 (that's the point of\n        // trimming, as Solana only supports uint64 for token amts)\n        return packTrimmedAmount(SafeCast.toUint64(amountScaled), actualToDecimals);\n    }\n\n    function untrim(TrimmedAmount amt, uint8 toDecimals) internal pure returns (uint256) {\n        uint256 deNorm = uint256(getAmount(amt));\n        uint8 fromDecimals = getDecimals(amt);\n        uint256 amountScaled = scale(deNorm, fromDecimals, toDecimals);\n\n        return amountScaled;\n    }\n}\n"
      },
      "lib/openzeppelin-contracts/contracts/utils/math/SafeCast.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/math/SafeCast.sol)\n// This file was procedurally generated from scripts/generate/templates/SafeCast.js.\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Wrappers over Solidity's uintXX/intXX casting operators with added overflow\n * checks.\n *\n * Downcasting from uint256/int256 in Solidity does not revert on overflow. This can\n * easily result in undesired exploitation or bugs, since developers usually\n * assume that overflows raise errors. `SafeCast` restores this intuition by\n * reverting the transaction when such an operation overflows.\n *\n * Using this library instead of the unchecked operations eliminates an entire\n * class of bugs, so it's recommended to use it always.\n *\n * Can be combined with {SafeMath} and {SignedSafeMath} to extend it to smaller types, by performing\n * all math on `uint256` and `int256` and then downcasting.\n */\nlibrary SafeCast {\n    /**\n     * @dev Returns the downcasted uint248 from uint256, reverting on\n     * overflow (when the input is greater than largest uint248).\n     *\n     * Counterpart to Solidity's `uint248` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 248 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint248(uint256 value) internal pure returns (uint248) {\n        require(value <= type(uint248).max, \"SafeCast: value doesn't fit in 248 bits\");\n        return uint248(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint240 from uint256, reverting on\n     * overflow (when the input is greater than largest uint240).\n     *\n     * Counterpart to Solidity's `uint240` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 240 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint240(uint256 value) internal pure returns (uint240) {\n        require(value <= type(uint240).max, \"SafeCast: value doesn't fit in 240 bits\");\n        return uint240(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint232 from uint256, reverting on\n     * overflow (when the input is greater than largest uint232).\n     *\n     * Counterpart to Solidity's `uint232` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 232 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint232(uint256 value) internal pure returns (uint232) {\n        require(value <= type(uint232).max, \"SafeCast: value doesn't fit in 232 bits\");\n        return uint232(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint224 from uint256, reverting on\n     * overflow (when the input is greater than largest uint224).\n     *\n     * Counterpart to Solidity's `uint224` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 224 bits\n     *\n     * _Available since v4.2._\n     */\n    function toUint224(uint256 value) internal pure returns (uint224) {\n        require(value <= type(uint224).max, \"SafeCast: value doesn't fit in 224 bits\");\n        return uint224(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint216 from uint256, reverting on\n     * overflow (when the input is greater than largest uint216).\n     *\n     * Counterpart to Solidity's `uint216` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 216 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint216(uint256 value) internal pure returns (uint216) {\n        require(value <= type(uint216).max, \"SafeCast: value doesn't fit in 216 bits\");\n        return uint216(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint208 from uint256, reverting on\n     * overflow (when the input is greater than largest uint208).\n     *\n     * Counterpart to Solidity's `uint208` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 208 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint208(uint256 value) internal pure returns (uint208) {\n        require(value <= type(uint208).max, \"SafeCast: value doesn't fit in 208 bits\");\n        return uint208(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint200 from uint256, reverting on\n     * overflow (when the input is greater than largest uint200).\n     *\n     * Counterpart to Solidity's `uint200` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 200 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint200(uint256 value) internal pure returns (uint200) {\n        require(value <= type(uint200).max, \"SafeCast: value doesn't fit in 200 bits\");\n        return uint200(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint192 from uint256, reverting on\n     * overflow (when the input is greater than largest uint192).\n     *\n     * Counterpart to Solidity's `uint192` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 192 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint192(uint256 value) internal pure returns (uint192) {\n        require(value <= type(uint192).max, \"SafeCast: value doesn't fit in 192 bits\");\n        return uint192(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint184 from uint256, reverting on\n     * overflow (when the input is greater than largest uint184).\n     *\n     * Counterpart to Solidity's `uint184` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 184 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint184(uint256 value) internal pure returns (uint184) {\n        require(value <= type(uint184).max, \"SafeCast: value doesn't fit in 184 bits\");\n        return uint184(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint176 from uint256, reverting on\n     * overflow (when the input is greater than largest uint176).\n     *\n     * Counterpart to Solidity's `uint176` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 176 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint176(uint256 value) internal pure returns (uint176) {\n        require(value <= type(uint176).max, \"SafeCast: value doesn't fit in 176 bits\");\n        return uint176(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint168 from uint256, reverting on\n     * overflow (when the input is greater than largest uint168).\n     *\n     * Counterpart to Solidity's `uint168` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 168 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint168(uint256 value) internal pure returns (uint168) {\n        require(value <= type(uint168).max, \"SafeCast: value doesn't fit in 168 bits\");\n        return uint168(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint160 from uint256, reverting on\n     * overflow (when the input is greater than largest uint160).\n     *\n     * Counterpart to Solidity's `uint160` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 160 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint160(uint256 value) internal pure returns (uint160) {\n        require(value <= type(uint160).max, \"SafeCast: value doesn't fit in 160 bits\");\n        return uint160(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint152 from uint256, reverting on\n     * overflow (when the input is greater than largest uint152).\n     *\n     * Counterpart to Solidity's `uint152` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 152 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint152(uint256 value) internal pure returns (uint152) {\n        require(value <= type(uint152).max, \"SafeCast: value doesn't fit in 152 bits\");\n        return uint152(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint144 from uint256, reverting on\n     * overflow (when the input is greater than largest uint144).\n     *\n     * Counterpart to Solidity's `uint144` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 144 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint144(uint256 value) internal pure returns (uint144) {\n        require(value <= type(uint144).max, \"SafeCast: value doesn't fit in 144 bits\");\n        return uint144(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint136 from uint256, reverting on\n     * overflow (when the input is greater than largest uint136).\n     *\n     * Counterpart to Solidity's `uint136` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 136 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint136(uint256 value) internal pure returns (uint136) {\n        require(value <= type(uint136).max, \"SafeCast: value doesn't fit in 136 bits\");\n        return uint136(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint128 from uint256, reverting on\n     * overflow (when the input is greater than largest uint128).\n     *\n     * Counterpart to Solidity's `uint128` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 128 bits\n     *\n     * _Available since v2.5._\n     */\n    function toUint128(uint256 value) internal pure returns (uint128) {\n        require(value <= type(uint128).max, \"SafeCast: value doesn't fit in 128 bits\");\n        return uint128(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint120 from uint256, reverting on\n     * overflow (when the input is greater than largest uint120).\n     *\n     * Counterpart to Solidity's `uint120` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 120 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint120(uint256 value) internal pure returns (uint120) {\n        require(value <= type(uint120).max, \"SafeCast: value doesn't fit in 120 bits\");\n        return uint120(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint112 from uint256, reverting on\n     * overflow (when the input is greater than largest uint112).\n     *\n     * Counterpart to Solidity's `uint112` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 112 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint112(uint256 value) internal pure returns (uint112) {\n        require(value <= type(uint112).max, \"SafeCast: value doesn't fit in 112 bits\");\n        return uint112(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint104 from uint256, reverting on\n     * overflow (when the input is greater than largest uint104).\n     *\n     * Counterpart to Solidity's `uint104` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 104 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint104(uint256 value) internal pure returns (uint104) {\n        require(value <= type(uint104).max, \"SafeCast: value doesn't fit in 104 bits\");\n        return uint104(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint96 from uint256, reverting on\n     * overflow (when the input is greater than largest uint96).\n     *\n     * Counterpart to Solidity's `uint96` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 96 bits\n     *\n     * _Available since v4.2._\n     */\n    function toUint96(uint256 value) internal pure returns (uint96) {\n        require(value <= type(uint96).max, \"SafeCast: value doesn't fit in 96 bits\");\n        return uint96(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint88 from uint256, reverting on\n     * overflow (when the input is greater than largest uint88).\n     *\n     * Counterpart to Solidity's `uint88` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 88 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint88(uint256 value) internal pure returns (uint88) {\n        require(value <= type(uint88).max, \"SafeCast: value doesn't fit in 88 bits\");\n        return uint88(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint80 from uint256, reverting on\n     * overflow (when the input is greater than largest uint80).\n     *\n     * Counterpart to Solidity's `uint80` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 80 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint80(uint256 value) internal pure returns (uint80) {\n        require(value <= type(uint80).max, \"SafeCast: value doesn't fit in 80 bits\");\n        return uint80(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint72 from uint256, reverting on\n     * overflow (when the input is greater than largest uint72).\n     *\n     * Counterpart to Solidity's `uint72` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 72 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint72(uint256 value) internal pure returns (uint72) {\n        require(value <= type(uint72).max, \"SafeCast: value doesn't fit in 72 bits\");\n        return uint72(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint64 from uint256, reverting on\n     * overflow (when the input is greater than largest uint64).\n     *\n     * Counterpart to Solidity's `uint64` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 64 bits\n     *\n     * _Available since v2.5._\n     */\n    function toUint64(uint256 value) internal pure returns (uint64) {\n        require(value <= type(uint64).max, \"SafeCast: value doesn't fit in 64 bits\");\n        return uint64(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint56 from uint256, reverting on\n     * overflow (when the input is greater than largest uint56).\n     *\n     * Counterpart to Solidity's `uint56` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 56 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint56(uint256 value) internal pure returns (uint56) {\n        require(value <= type(uint56).max, \"SafeCast: value doesn't fit in 56 bits\");\n        return uint56(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint48 from uint256, reverting on\n     * overflow (when the input is greater than largest uint48).\n     *\n     * Counterpart to Solidity's `uint48` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 48 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint48(uint256 value) internal pure returns (uint48) {\n        require(value <= type(uint48).max, \"SafeCast: value doesn't fit in 48 bits\");\n        return uint48(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint40 from uint256, reverting on\n     * overflow (when the input is greater than largest uint40).\n     *\n     * Counterpart to Solidity's `uint40` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 40 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint40(uint256 value) internal pure returns (uint40) {\n        require(value <= type(uint40).max, \"SafeCast: value doesn't fit in 40 bits\");\n        return uint40(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint32 from uint256, reverting on\n     * overflow (when the input is greater than largest uint32).\n     *\n     * Counterpart to Solidity's `uint32` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 32 bits\n     *\n     * _Available since v2.5._\n     */\n    function toUint32(uint256 value) internal pure returns (uint32) {\n        require(value <= type(uint32).max, \"SafeCast: value doesn't fit in 32 bits\");\n        return uint32(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint24 from uint256, reverting on\n     * overflow (when the input is greater than largest uint24).\n     *\n     * Counterpart to Solidity's `uint24` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 24 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint24(uint256 value) internal pure returns (uint24) {\n        require(value <= type(uint24).max, \"SafeCast: value doesn't fit in 24 bits\");\n        return uint24(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint16 from uint256, reverting on\n     * overflow (when the input is greater than largest uint16).\n     *\n     * Counterpart to Solidity's `uint16` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 16 bits\n     *\n     * _Available since v2.5._\n     */\n    function toUint16(uint256 value) internal pure returns (uint16) {\n        require(value <= type(uint16).max, \"SafeCast: value doesn't fit in 16 bits\");\n        return uint16(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint8 from uint256, reverting on\n     * overflow (when the input is greater than largest uint8).\n     *\n     * Counterpart to Solidity's `uint8` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 8 bits\n     *\n     * _Available since v2.5._\n     */\n    function toUint8(uint256 value) internal pure returns (uint8) {\n        require(value <= type(uint8).max, \"SafeCast: value doesn't fit in 8 bits\");\n        return uint8(value);\n    }\n\n    /**\n     * @dev Converts a signed int256 into an unsigned uint256.\n     *\n     * Requirements:\n     *\n     * - input must be greater than or equal to 0.\n     *\n     * _Available since v3.0._\n     */\n    function toUint256(int256 value) internal pure returns (uint256) {\n        require(value >= 0, \"SafeCast: value must be positive\");\n        return uint256(value);\n    }\n\n    /**\n     * @dev Returns the downcasted int248 from int256, reverting on\n     * overflow (when the input is less than smallest int248 or\n     * greater than largest int248).\n     *\n     * Counterpart to Solidity's `int248` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 248 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt248(int256 value) internal pure returns (int248 downcasted) {\n        downcasted = int248(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 248 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int240 from int256, reverting on\n     * overflow (when the input is less than smallest int240 or\n     * greater than largest int240).\n     *\n     * Counterpart to Solidity's `int240` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 240 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt240(int256 value) internal pure returns (int240 downcasted) {\n        downcasted = int240(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 240 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int232 from int256, reverting on\n     * overflow (when the input is less than smallest int232 or\n     * greater than largest int232).\n     *\n     * Counterpart to Solidity's `int232` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 232 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt232(int256 value) internal pure returns (int232 downcasted) {\n        downcasted = int232(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 232 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int224 from int256, reverting on\n     * overflow (when the input is less than smallest int224 or\n     * greater than largest int224).\n     *\n     * Counterpart to Solidity's `int224` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 224 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt224(int256 value) internal pure returns (int224 downcasted) {\n        downcasted = int224(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 224 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int216 from int256, reverting on\n     * overflow (when the input is less than smallest int216 or\n     * greater than largest int216).\n     *\n     * Counterpart to Solidity's `int216` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 216 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt216(int256 value) internal pure returns (int216 downcasted) {\n        downcasted = int216(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 216 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int208 from int256, reverting on\n     * overflow (when the input is less than smallest int208 or\n     * greater than largest int208).\n     *\n     * Counterpart to Solidity's `int208` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 208 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt208(int256 value) internal pure returns (int208 downcasted) {\n        downcasted = int208(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 208 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int200 from int256, reverting on\n     * overflow (when the input is less than smallest int200 or\n     * greater than largest int200).\n     *\n     * Counterpart to Solidity's `int200` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 200 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt200(int256 value) internal pure returns (int200 downcasted) {\n        downcasted = int200(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 200 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int192 from int256, reverting on\n     * overflow (when the input is less than smallest int192 or\n     * greater than largest int192).\n     *\n     * Counterpart to Solidity's `int192` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 192 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt192(int256 value) internal pure returns (int192 downcasted) {\n        downcasted = int192(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 192 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int184 from int256, reverting on\n     * overflow (when the input is less than smallest int184 or\n     * greater than largest int184).\n     *\n     * Counterpart to Solidity's `int184` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 184 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt184(int256 value) internal pure returns (int184 downcasted) {\n        downcasted = int184(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 184 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int176 from int256, reverting on\n     * overflow (when the input is less than smallest int176 or\n     * greater than largest int176).\n     *\n     * Counterpart to Solidity's `int176` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 176 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt176(int256 value) internal pure returns (int176 downcasted) {\n        downcasted = int176(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 176 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int168 from int256, reverting on\n     * overflow (when the input is less than smallest int168 or\n     * greater than largest int168).\n     *\n     * Counterpart to Solidity's `int168` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 168 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt168(int256 value) internal pure returns (int168 downcasted) {\n        downcasted = int168(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 168 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int160 from int256, reverting on\n     * overflow (when the input is less than smallest int160 or\n     * greater than largest int160).\n     *\n     * Counterpart to Solidity's `int160` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 160 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt160(int256 value) internal pure returns (int160 downcasted) {\n        downcasted = int160(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 160 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int152 from int256, reverting on\n     * overflow (when the input is less than smallest int152 or\n     * greater than largest int152).\n     *\n     * Counterpart to Solidity's `int152` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 152 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt152(int256 value) internal pure returns (int152 downcasted) {\n        downcasted = int152(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 152 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int144 from int256, reverting on\n     * overflow (when the input is less than smallest int144 or\n     * greater than largest int144).\n     *\n     * Counterpart to Solidity's `int144` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 144 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt144(int256 value) internal pure returns (int144 downcasted) {\n        downcasted = int144(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 144 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int136 from int256, reverting on\n     * overflow (when the input is less than smallest int136 or\n     * greater than largest int136).\n     *\n     * Counterpart to Solidity's `int136` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 136 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt136(int256 value) internal pure returns (int136 downcasted) {\n        downcasted = int136(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 136 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int128 from int256, reverting on\n     * overflow (when the input is less than smallest int128 or\n     * greater than largest int128).\n     *\n     * Counterpart to Solidity's `int128` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 128 bits\n     *\n     * _Available since v3.1._\n     */\n    function toInt128(int256 value) internal pure returns (int128 downcasted) {\n        downcasted = int128(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 128 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int120 from int256, reverting on\n     * overflow (when the input is less than smallest int120 or\n     * greater than largest int120).\n     *\n     * Counterpart to Solidity's `int120` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 120 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt120(int256 value) internal pure returns (int120 downcasted) {\n        downcasted = int120(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 120 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int112 from int256, reverting on\n     * overflow (when the input is less than smallest int112 or\n     * greater than largest int112).\n     *\n     * Counterpart to Solidity's `int112` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 112 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt112(int256 value) internal pure returns (int112 downcasted) {\n        downcasted = int112(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 112 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int104 from int256, reverting on\n     * overflow (when the input is less than smallest int104 or\n     * greater than largest int104).\n     *\n     * Counterpart to Solidity's `int104` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 104 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt104(int256 value) internal pure returns (int104 downcasted) {\n        downcasted = int104(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 104 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int96 from int256, reverting on\n     * overflow (when the input is less than smallest int96 or\n     * greater than largest int96).\n     *\n     * Counterpart to Solidity's `int96` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 96 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt96(int256 value) internal pure returns (int96 downcasted) {\n        downcasted = int96(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 96 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int88 from int256, reverting on\n     * overflow (when the input is less than smallest int88 or\n     * greater than largest int88).\n     *\n     * Counterpart to Solidity's `int88` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 88 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt88(int256 value) internal pure returns (int88 downcasted) {\n        downcasted = int88(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 88 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int80 from int256, reverting on\n     * overflow (when the input is less than smallest int80 or\n     * greater than largest int80).\n     *\n     * Counterpart to Solidity's `int80` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 80 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt80(int256 value) internal pure returns (int80 downcasted) {\n        downcasted = int80(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 80 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int72 from int256, reverting on\n     * overflow (when the input is less than smallest int72 or\n     * greater than largest int72).\n     *\n     * Counterpart to Solidity's `int72` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 72 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt72(int256 value) internal pure returns (int72 downcasted) {\n        downcasted = int72(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 72 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int64 from int256, reverting on\n     * overflow (when the input is less than smallest int64 or\n     * greater than largest int64).\n     *\n     * Counterpart to Solidity's `int64` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 64 bits\n     *\n     * _Available since v3.1._\n     */\n    function toInt64(int256 value) internal pure returns (int64 downcasted) {\n        downcasted = int64(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 64 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int56 from int256, reverting on\n     * overflow (when the input is less than smallest int56 or\n     * greater than largest int56).\n     *\n     * Counterpart to Solidity's `int56` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 56 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt56(int256 value) internal pure returns (int56 downcasted) {\n        downcasted = int56(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 56 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int48 from int256, reverting on\n     * overflow (when the input is less than smallest int48 or\n     * greater than largest int48).\n     *\n     * Counterpart to Solidity's `int48` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 48 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt48(int256 value) internal pure returns (int48 downcasted) {\n        downcasted = int48(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 48 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int40 from int256, reverting on\n     * overflow (when the input is less than smallest int40 or\n     * greater than largest int40).\n     *\n     * Counterpart to Solidity's `int40` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 40 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt40(int256 value) internal pure returns (int40 downcasted) {\n        downcasted = int40(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 40 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int32 from int256, reverting on\n     * overflow (when the input is less than smallest int32 or\n     * greater than largest int32).\n     *\n     * Counterpart to Solidity's `int32` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 32 bits\n     *\n     * _Available since v3.1._\n     */\n    function toInt32(int256 value) internal pure returns (int32 downcasted) {\n        downcasted = int32(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 32 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int24 from int256, reverting on\n     * overflow (when the input is less than smallest int24 or\n     * greater than largest int24).\n     *\n     * Counterpart to Solidity's `int24` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 24 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt24(int256 value) internal pure returns (int24 downcasted) {\n        downcasted = int24(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 24 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int16 from int256, reverting on\n     * overflow (when the input is less than smallest int16 or\n     * greater than largest int16).\n     *\n     * Counterpart to Solidity's `int16` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 16 bits\n     *\n     * _Available since v3.1._\n     */\n    function toInt16(int256 value) internal pure returns (int16 downcasted) {\n        downcasted = int16(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 16 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int8 from int256, reverting on\n     * overflow (when the input is less than smallest int8 or\n     * greater than largest int8).\n     *\n     * Counterpart to Solidity's `int8` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 8 bits\n     *\n     * _Available since v3.1._\n     */\n    function toInt8(int256 value) internal pure returns (int8 downcasted) {\n        downcasted = int8(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 8 bits\");\n    }\n\n    /**\n     * @dev Converts an unsigned uint256 into a signed int256.\n     *\n     * Requirements:\n     *\n     * - input must be less than or equal to maxInt256.\n     *\n     * _Available since v3.0._\n     */\n    function toInt256(uint256 value) internal pure returns (int256) {\n        // Note: Unsafe cast below is okay because `type(int256).max` is guaranteed to be positive\n        require(value <= uint256(type(int256).max), \"SafeCast: value doesn't fit in an int256\");\n        return int256(value);\n    }\n}\n"
      },
      "src/interfaces/IManagerBase.sol": {
        "content": "// SPDX-License-Identifier: Apache 2\npragma solidity >=0.8.8 <0.9.0;\n\nimport \"../libraries/TransceiverStructs.sol\";\n\ninterface IManagerBase {\n    /// @notice The mode is either LOCKING or BURNING. In LOCKING mode, the NttManager locks the\n    ///         tokens of the sender and mints an equivalent amount on the target chain. In BURNING\n    ///         mode, the NttManager burns the tokens of the sender and mints an equivalent amount\n    ///         on the target chain.LOCKING mode preserves the total supply of the tokens.\n    enum Mode {\n        LOCKING,\n        BURNING\n    }\n\n    /// @notice Information about attestations for a given message.\n    /// @dev The fields are as follows:\n    ///      - executed: whether the message has been executed.\n    ///      - attested: bitmap of transceivers that have attested to this message.\n    ///                  (NOTE: might contain disabled transceivers)\n    struct AttestationInfo {\n        bool executed;\n        uint64 attestedTransceivers;\n    }\n\n    struct _Sequence {\n        uint64 num;\n    }\n\n    struct _Threshold {\n        uint8 num;\n    }\n\n    /// @notice Emitted when a message has been attested to.\n    /// @dev Topic0\n    ///      0x35a2101eaac94b493e0dfca061f9a7f087913fde8678e7cde0aca9897edba0e5.\n    /// @param digest The digest of the message.\n    /// @param transceiver The address of the transceiver.\n    /// @param index The index of the transceiver in the bitmap.\n    event MessageAttestedTo(bytes32 digest, address transceiver, uint8 index);\n\n    /// @notice Emmitted when the threshold required transceivers is changed.\n    /// @dev Topic0\n    ///      0x2a855b929b9a53c6fb5b5ed248b27e502b709c088e036a5aa17620c8fc5085a9.\n    /// @param oldThreshold The old threshold.\n    /// @param threshold The new threshold.\n    event ThresholdChanged(uint8 oldThreshold, uint8 threshold);\n\n    /// @notice Emitted when an transceiver is removed from the nttManager.\n    /// @dev Topic0\n    ///      0xf05962b5774c658e85ed80c91a75af9d66d2af2253dda480f90bce78aff5eda5.\n    /// @param transceiver The address of the transceiver.\n    /// @param transceiversNum The current number of transceivers.\n    /// @param threshold The current threshold of transceivers.\n    event TransceiverAdded(address transceiver, uint256 transceiversNum, uint8 threshold);\n\n    /// @notice Emitted when an transceiver is removed from the nttManager.\n    /// @dev Topic0\n    ///     0x697a3853515b88013ad432f29f53d406debc9509ed6d9313dcfe115250fcd18f.\n    /// @param transceiver The address of the transceiver.\n    /// @param threshold The current threshold of transceivers.\n    event TransceiverRemoved(address transceiver, uint8 threshold);\n\n    /// @notice payment for a transfer is too low.\n    /// @param requiredPayment The required payment.\n    /// @param providedPayment The provided payment.\n    error DeliveryPaymentTooLow(uint256 requiredPayment, uint256 providedPayment);\n\n    /// @notice Error when the refund to the sender fails.\n    /// @dev Selector 0x2ca23714.\n    /// @param refundAmount The refund amount.\n    error RefundFailed(uint256 refundAmount);\n\n    /// @notice The number of thresholds should not be zero.\n    error ZeroThreshold();\n\n    error RetrievedIncorrectRegisteredTransceivers(uint256 retrieved, uint256 registered);\n\n    /// @notice The threshold for transceiver attestations is too high.\n    /// @param threshold The threshold.\n    /// @param transceivers The number of transceivers.\n    error ThresholdTooHigh(uint256 threshold, uint256 transceivers);\n\n    /// @notice Error when the tranceiver already attested to the message.\n    ///         To ensure the client does not continue to initiate calls to the attestationReceived function.\n    /// @dev Selector 0x2113894.\n    /// @param nttManagerMessageHash The hash of the message.\n    error TransceiverAlreadyAttestedToMessage(bytes32 nttManagerMessageHash);\n\n    /// @notice Error when the message is not approved.\n    /// @dev Selector 0x451c4fb0.\n    /// @param msgHash The hash of the message.\n    error MessageNotApproved(bytes32 msgHash);\n\n    /// @notice Emitted when a message has already been executed to\n    ///         notify client of against retries.\n    /// @dev Topic0\n    ///      0x4069dff8c9df7e38d2867c0910bd96fd61787695e5380281148c04932d02bef2.\n    /// @param sourceNttManager The address of the source nttManager.\n    /// @param msgHash The keccak-256 hash of the message.\n    event MessageAlreadyExecuted(bytes32 indexed sourceNttManager, bytes32 indexed msgHash);\n\n    /// @notice There are no transceivers enabled with the Manager\n    /// @dev Selector 0x69cf632a\n    error NoEnabledTransceivers();\n\n    /// @notice Error when the manager doesn't have a peer registered for the destination chain\n    /// @dev Selector 0x3af256bc.\n    /// @param chainId The target chain id\n    error PeerNotRegistered(uint16 chainId);\n\n    /// @notice Fetch the delivery price for a given recipient chain transfer.\n    /// @param recipientChain The chain ID of the transfer destination.\n    /// @param transceiverInstructions The transceiver specific instructions for quoting and sending\n    /// @return - The delivery prices associated with each enabled endpoint and the total price.\n    function quoteDeliveryPrice(\n        uint16 recipientChain,\n        bytes memory transceiverInstructions\n    ) external view returns (uint256[] memory, uint256);\n\n    /// @notice Sets the threshold for the number of attestations required for a message\n    /// to be considered valid.\n    /// @param threshold The new threshold.\n    /// @dev This method can only be executed by the `owner`.\n    function setThreshold(uint8 threshold) external;\n\n    /// @notice Sets the transceiver for the given chain.\n    /// @param transceiver The address of the transceiver.\n    /// @dev This method can only be executed by the `owner`.\n    function setTransceiver(address transceiver) external;\n\n    /// @notice Removes the transceiver for the given chain.\n    /// @param transceiver The address of the transceiver.\n    /// @dev This method can only be executed by the `owner`.\n    function removeTransceiver(address transceiver) external;\n\n    /// @notice Checks if a message has been approved. The message should have at least\n    /// the minimum threshold of attestations from distinct endpoints.\n    /// @param digest The digest of the message.\n    /// @return - Boolean indicating if message has been approved.\n    function isMessageApproved(bytes32 digest) external view returns (bool);\n\n    /// @notice Checks if a message has been executed.\n    /// @param digest The digest of the message.\n    /// @return - Boolean indicating if message has been executed.\n    function isMessageExecuted(bytes32 digest) external view returns (bool);\n\n    /// @notice Returns the next message sequence.\n    function nextMessageSequence() external view returns (uint64);\n\n    /// @notice Upgrades to a new manager implementation.\n    /// @dev This is upgraded via a proxy, and can only be executed\n    /// by the `owner`.\n    /// @param newImplementation The address of the new implementation.\n    function upgrade(address newImplementation) external;\n\n    /// @notice Pauses the manager.\n    function pause() external;\n\n    /// @notice Returns the mode (locking or burning) of the NttManager.\n    /// @return mode A uint8 corresponding to the mode\n    function getMode() external view returns (uint8);\n\n    /// @notice Returns the number of Transceivers that must attest to a msgId for\n    /// it to be considered valid and acted upon.\n    function getThreshold() external view returns (uint8);\n\n    /// @notice Returns a boolean indicating if the transceiver has attested to the message.\n    function transceiverAttestedToMessage(\n        bytes32 digest,\n        uint8 index\n    ) external view returns (bool);\n\n    /// @notice Returns the number of attestations for a given message.\n    function messageAttestations(bytes32 digest) external view returns (uint8 count);\n\n    /// @notice Returns of the address of the token managed by this contract.\n    function token() external view returns (address);\n\n    /// @notice Returns the chain ID.\n    function chainId() external view returns (uint16);\n}\n"
      },
      "src/libraries/external/OwnableUpgradeable.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.0.0) (access/Ownable.sol)\n\n// COPIED FROM OPENZEPPELIN v5.0.1\n// COPIED TO CHANGE SOLC FROM ^0.8.20 TO ^0.8.19\n\npragma solidity ^0.8.19;\n\nimport {ContextUpgradeable} from \"./ContextUpgradeable.sol\";\nimport {Initializable} from \"./Initializable.sol\";\nimport \"../../interfaces/IOwnableUpgradeable.sol\";\n\n/**\n * @dev Contract module which provides a basic access control mechanism, where\n * there is an account (an owner) that can be granted exclusive access to\n * specific functions.\n *\n * The initial owner is set to the address provided by the deployer. This can\n * later be changed with {transferOwnership}.\n *\n * This module is used through inheritance. It will make available the modifier\n * `onlyOwner`, which can be applied to your functions to restrict their use to\n * the owner.\n */\nabstract contract OwnableUpgradeable is Initializable, ContextUpgradeable, IOwnableUpgradeable {\n    /// @custom:storage-location erc7201:openzeppelin.storage.Ownable\n    struct OwnableStorage {\n        address _owner;\n    }\n\n    // keccak256(abi.encode(uint256(keccak256(\"openzeppelin.storage.Ownable\")) - 1)) & ~bytes32(uint256(0xff))\n    bytes32 private constant OwnableStorageLocation =\n        0x9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c199300;\n\n    function _getOwnableStorage() private pure returns (OwnableStorage storage $) {\n        assembly {\n            $.slot := OwnableStorageLocation\n        }\n    }\n\n    /**\n     * @dev The caller account is not authorized to perform an operation.\n     */\n    error OwnableUnauthorizedAccount(address account);\n\n    /**\n     * @dev The owner is not a valid owner account. (eg. `address(0)`)\n     */\n    error OwnableInvalidOwner(address owner);\n\n    event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);\n\n    /**\n     * @dev Initializes the contract setting the address provided by the deployer as the initial owner.\n     */\n    function __Ownable_init(address initialOwner) internal onlyInitializing {\n        __Ownable_init_unchained(initialOwner);\n    }\n\n    function __Ownable_init_unchained(address initialOwner) internal onlyInitializing {\n        if (initialOwner == address(0)) {\n            revert OwnableInvalidOwner(address(0));\n        }\n        _transferOwnership(initialOwner);\n    }\n\n    /**\n     * @dev Throws if called by any account other than the owner.\n     */\n    modifier onlyOwner() {\n        _checkOwner();\n        _;\n    }\n\n    /**\n     * @dev Returns the address of the current owner.\n     */\n    function owner() public view virtual returns (address) {\n        OwnableStorage storage $ = _getOwnableStorage();\n        return $._owner;\n    }\n\n    /**\n     * @dev Throws if the sender is not the owner.\n     */\n    function _checkOwner() internal view virtual {\n        if (owner() != _msgSender()) {\n            revert OwnableUnauthorizedAccount(_msgSender());\n        }\n    }\n\n    /**\n     * @dev Transfers ownership of the contract to a new account (`newOwner`).\n     * Can only be called by the current owner.\n     */\n    function transferOwnership(address newOwner) public virtual onlyOwner {\n        if (newOwner == address(0)) {\n            revert OwnableInvalidOwner(address(0));\n        }\n        _transferOwnership(newOwner);\n    }\n\n    /**\n     * @dev Transfers ownership of the contract to a new account (`newOwner`).\n     * Internal function without access restriction.\n     */\n    function _transferOwnership(address newOwner) internal virtual {\n        OwnableStorage storage $ = _getOwnableStorage();\n        address oldOwner = $._owner;\n        $._owner = newOwner;\n        emit OwnershipTransferred(oldOwner, newOwner);\n    }\n}\n"
      },
      "src/libraries/external/ReentrancyGuardUpgradeable.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.0.0) (utils/ReentrancyGuard.sol)\n\npragma solidity ^0.8.19;\n\nimport {Initializable} from \"./Initializable.sol\";\n\n/**\n * @dev Contract module that helps prevent reentrant calls to a function.\n *\n * Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier\n * available, which can be applied to functions to make sure there are no nested\n * (reentrant) calls to them.\n *\n * Note that because there is a single `nonReentrant` guard, functions marked as\n * `nonReentrant` may not call one another. This can be worked around by making\n * those functions `private`, and then adding `external` `nonReentrant` entry\n * points to them.\n *\n * TIP: If you would like to learn more about reentrancy and alternative ways\n * to protect against it, check out our blog post\n * https://blog.openzeppelin.com/reentrancy-after-istanbul/[Reentrancy After Istanbul].\n */\nabstract contract ReentrancyGuardUpgradeable is Initializable {\n    // Booleans are more expensive than uint256 or any type that takes up a full\n    // word because each write operation emits an extra SLOAD to first read the\n    // slot's contents, replace the bits taken up by the boolean, and then write\n    // back. This is the compiler's defense against contract upgrades and\n    // pointer aliasing, and it cannot be disabled.\n\n    // The values being non-zero value makes deployment a bit more expensive,\n    // but in exchange the refund on every call to nonReentrant will be lower in\n    // amount. Since refunds are capped to a percentage of the total\n    // transaction's gas, it is best to keep them low in cases like this one, to\n    // increase the likelihood of the full refund coming into effect.\n    uint256 private constant NOT_ENTERED = 1;\n    uint256 private constant ENTERED = 2;\n\n    /// @custom:storage-location erc7201:openzeppelin.storage.ReentrancyGuard\n    struct ReentrancyGuardStorage {\n        uint256 _status;\n    }\n\n    // keccak256(abi.encode(uint256(keccak256(\"openzeppelin.storage.ReentrancyGuard\")) - 1)) & ~bytes32(uint256(0xff))\n    bytes32 private constant ReentrancyGuardStorageLocation =\n        0x9b779b17422d0df92223018b32b4d1fa46e071723d6817e2486d003becc55f00;\n\n    function _getReentrancyGuardStorage() private pure returns (ReentrancyGuardStorage storage $) {\n        assembly {\n            $.slot := ReentrancyGuardStorageLocation\n        }\n    }\n\n    /**\n     * @dev Unauthorized reentrant call.\n     */\n    error ReentrancyGuardReentrantCall();\n\n    function __ReentrancyGuard_init() internal onlyInitializing {\n        __ReentrancyGuard_init_unchained();\n    }\n\n    function __ReentrancyGuard_init_unchained() internal onlyInitializing {\n        ReentrancyGuardStorage storage $ = _getReentrancyGuardStorage();\n        $._status = NOT_ENTERED;\n    }\n\n    /**\n     * @dev Prevents a contract from calling itself, directly or indirectly.\n     * Calling a `nonReentrant` function from another `nonReentrant`\n     * function is not supported. It is possible to prevent this from happening\n     * by making the `nonReentrant` function external, and making it call a\n     * `private` function that does the actual work.\n     */\n    modifier nonReentrant() {\n        _nonReentrantBefore();\n        _;\n        _nonReentrantAfter();\n    }\n\n    function _nonReentrantBefore() private {\n        ReentrancyGuardStorage storage $ = _getReentrancyGuardStorage();\n        // On the first call to nonReentrant, _status will be NOT_ENTERED\n        if ($._status == ENTERED) {\n            revert ReentrancyGuardReentrantCall();\n        }\n\n        // Any calls to nonReentrant after this point will fail\n        $._status = ENTERED;\n    }\n\n    function _nonReentrantAfter() private {\n        ReentrancyGuardStorage storage $ = _getReentrancyGuardStorage();\n        // By storing the original value once again, a refund is triggered (see\n        // https://eips.ethereum.org/EIPS/eip-2200)\n        $._status = NOT_ENTERED;\n    }\n\n    /**\n     * @dev Returns true if the reentrancy guard is currently set to \"entered\", which indicates there is a\n     * `nonReentrant` function in the call stack.\n     */\n    function _reentrancyGuardEntered() internal view returns (bool) {\n        ReentrancyGuardStorage storage $ = _getReentrancyGuardStorage();\n        return $._status == ENTERED;\n    }\n}\n"
      },
      "src/libraries/PausableOwnable.sol": {
        "content": "// SPDX-License-Identifier: Apache 2\n\npragma solidity >=0.8.8 <0.9.0;\n\nimport \"./PausableUpgradeable.sol\";\nimport \"./external/OwnableUpgradeable.sol\";\n\nabstract contract PausableOwnable is PausableUpgradeable, OwnableUpgradeable {\n    /*\n     * @dev Modifier to allow only the Pauser and the Owner to access pausing functionality\n     */\n    modifier onlyOwnerOrPauser() {\n        _checkOwnerOrPauser(owner());\n        _;\n    }\n\n    /*\n     * @dev Modifier to allow only the Pauser to access some functionality\n     */\n    function _checkOwnerOrPauser(address owner) internal view {\n        if (pauser() != msg.sender && owner != msg.sender) {\n            revert InvalidPauser(msg.sender);\n        }\n    }\n\n    function __PausedOwnable_init(address initialPauser, address owner) internal onlyInitializing {\n        __Paused_init(initialPauser);\n        __Ownable_init(owner);\n    }\n\n    /**\n     * @dev Transfers the ability to pause to a new account (`newPauser`).\n     */\n    function transferPauserCapability(address newPauser) public virtual onlyOwnerOrPauser {\n        PauserStorage storage $ = _getPauserStorage();\n        address oldPauser = $._pauser;\n        $._pauser = newPauser;\n        emit PauserTransferred(oldPauser, newPauser);\n    }\n}\n"
      },
      "src/libraries/Implementation.sol": {
        "content": "// SPDX-License-Identifier: Apache 2\npragma solidity >=0.8.8 <0.9.0;\n\nimport \"./external/Initializable.sol\";\nimport \"openzeppelin-contracts/contracts/proxy/ERC1967/ERC1967Upgrade.sol\";\n\n/// @dev This contract should be used as a base contract for implementation contracts\n///      that are used with ERC1967Proxy.\n///      It ensures that the contract cannot be initialized directly, only through\n///      the proxy (by disabling initializers in the constructor).\n///      It also exposes a migrate function that is called during upgrades.\nabstract contract Implementation is Initializable, ERC1967Upgrade {\n    address immutable _this;\n\n    error OnlyDelegateCall();\n    error NotMigrating();\n\n    constructor() {\n        _disableInitializers();\n        _this = address(this);\n    }\n\n    modifier onlyDelegateCall() {\n        _checkDelegateCall();\n        _;\n    }\n\n    struct _Migrating {\n        bool isMigrating;\n    }\n\n    struct _Bool {\n        bool value;\n    }\n\n    bytes32 private constant MIGRATING_SLOT = bytes32(uint256(keccak256(\"ntt.migrating\")) - 1);\n\n    bytes32 private constant MIGRATES_IMMUTABLES_SLOT =\n        bytes32(uint256(keccak256(\"ntt.migratesImmutables\")) - 1);\n\n    function _getMigratingStorage() private pure returns (_Migrating storage $) {\n        uint256 slot = uint256(MIGRATING_SLOT);\n        assembly (\"memory-safe\") {\n            $.slot := slot\n        }\n    }\n\n    function _getMigratesImmutablesStorage() internal pure returns (_Bool storage $) {\n        uint256 slot = uint256(MIGRATES_IMMUTABLES_SLOT);\n        assembly (\"memory-safe\") {\n            $.slot := slot\n        }\n    }\n\n    function _checkDelegateCall() internal view {\n        if (address(this) == _this) {\n            revert OnlyDelegateCall();\n        }\n    }\n\n    function initialize() external payable onlyDelegateCall initializer {\n        _initialize();\n    }\n\n    function migrate() external onlyDelegateCall reinitializer(_getInitializedVersion() + 1) {\n        // NOTE: we add the reinitializer() modifier so that onlyInitializing\n        // functions can be called inside\n        if (!_getMigratingStorage().isMigrating) {\n            revert NotMigrating();\n        }\n        _migrate();\n    }\n\n    function _migrate() internal virtual;\n\n    function _initialize() internal virtual;\n\n    function _checkImmutables() internal view virtual;\n\n    function _upgrade(address newImplementation) internal {\n        _checkDelegateCall();\n        _upgradeTo(newImplementation);\n\n        _Migrating storage _migrating = _getMigratingStorage();\n        assert(!_migrating.isMigrating);\n        _migrating.isMigrating = true;\n\n        this.migrate();\n        if (!this.getMigratesImmutables()) {\n            _checkImmutables();\n        }\n        _setMigratesImmutables(false);\n\n        _migrating.isMigrating = false;\n    }\n\n    function getMigratesImmutables() public view returns (bool) {\n        return _getMigratesImmutablesStorage().value;\n    }\n\n    function _setMigratesImmutables(bool value) internal {\n        _getMigratesImmutablesStorage().value = value;\n    }\n}\n"
      },
      "src/NttManager/TransceiverRegistry.sol": {
        "content": "// SPDX-License-Identifier: Apache 2\npragma solidity >=0.8.8 <0.9.0;\n\n/// @title TransceiverRegistry\n/// @author Wormhole Project Contributors.\n/// @notice This contract is responsible for handling the registration of Transceivers.\n/// @dev This contract checks that a few critical invariants hold when transceivers are added or removed,\n///      including:\n///         1. If a transceiver is not registered, it should be enabled.\n///         2. The value set in the bitmap of trannsceivers\n///            should directly correspond to the whether the transceiver is enabled\nabstract contract TransceiverRegistry {\n    constructor() {\n        _checkTransceiversInvariants();\n    }\n\n    /// @dev Information about registered transceivers.\n    struct TransceiverInfo {\n        // whether this transceiver is registered\n        bool registered;\n        // whether this transceiver is enabled\n        bool enabled;\n        uint8 index;\n    }\n\n    /// @dev Bitmap encoding the enabled transceivers.\n    /// invariant: forall (i: uint8), enabledTransceiverBitmap & i == 1 <=> transceiverInfos[i].enabled\n    struct _EnabledTransceiverBitmap {\n        uint64 bitmap;\n    }\n\n    /// @dev Total number of registered transceivers. This number can only increase.\n    /// invariant: numRegisteredTransceivers <= MAX_TRANSCEIVERS\n    /// invariant: forall (i: uint8),\n    ///   i < numRegisteredTransceivers <=> exists (a: address), transceiverInfos[a].index == i\n    struct _NumTransceivers {\n        uint8 registered;\n        uint8 enabled;\n    }\n\n    uint8 constant MAX_TRANSCEIVERS = 64;\n\n    /// @notice Error when the caller is not the transceiver.\n    /// @dev Selector 0xa0ae911d.\n    /// @param caller The address of the caller.\n    error CallerNotTransceiver(address caller);\n\n    /// @notice Error when the transceiver is the zero address.\n    /// @dev Selector 0x2f44bd77.\n    error InvalidTransceiverZeroAddress();\n\n    /// @notice Error when the transceiver is disabled.\n    /// @dev Selector 0x1f61ba44.\n    error DisabledTransceiver(address transceiver);\n\n    /// @notice Error when the number of registered transceivers\n    ///         exceeeds (MAX_TRANSCEIVERS = 64).\n    /// @dev Selector 0x891684c3.\n    error TooManyTransceivers();\n\n    /// @notice Error when attempting to remove a transceiver\n    ///         that is not registered.\n    /// @dev Selector 0xd583f470.\n    /// @param transceiver The address of the transceiver.\n    error NonRegisteredTransceiver(address transceiver);\n\n    /// @notice Error when attempting to enable a transceiver that is already enabled.\n    /// @dev Selector 0x8d68f84d.\n    /// @param transceiver The address of the transceiver.\n    error TransceiverAlreadyEnabled(address transceiver);\n\n    modifier onlyTransceiver() {\n        if (!_getTransceiverInfosStorage()[msg.sender].enabled) {\n            revert CallerNotTransceiver(msg.sender);\n        }\n        _;\n    }\n\n    // =============== Storage ===============================================\n\n    bytes32 private constant TRANSCEIVER_INFOS_SLOT =\n        bytes32(uint256(keccak256(\"ntt.transceiverInfos\")) - 1);\n\n    bytes32 private constant TRANSCEIVER_BITMAP_SLOT =\n        bytes32(uint256(keccak256(\"ntt.transceiverBitmap\")) - 1);\n\n    bytes32 private constant ENABLED_TRANSCEIVERS_SLOT =\n        bytes32(uint256(keccak256(\"ntt.enabledTransceivers\")) - 1);\n\n    bytes32 private constant REGISTERED_TRANSCEIVERS_SLOT =\n        bytes32(uint256(keccak256(\"ntt.registeredTransceivers\")) - 1);\n\n    bytes32 private constant NUM_REGISTERED_TRANSCEIVERS_SLOT =\n        bytes32(uint256(keccak256(\"ntt.numRegisteredTransceivers\")) - 1);\n\n    function _getTransceiverInfosStorage()\n        internal\n        pure\n        returns (mapping(address => TransceiverInfo) storage $)\n    {\n        uint256 slot = uint256(TRANSCEIVER_INFOS_SLOT);\n        assembly (\"memory-safe\") {\n            $.slot := slot\n        }\n    }\n\n    function _getEnabledTransceiversStorage() internal pure returns (address[] storage $) {\n        uint256 slot = uint256(ENABLED_TRANSCEIVERS_SLOT);\n        assembly (\"memory-safe\") {\n            $.slot := slot\n        }\n    }\n\n    function _getTransceiverBitmapStorage()\n        private\n        pure\n        returns (_EnabledTransceiverBitmap storage $)\n    {\n        uint256 slot = uint256(TRANSCEIVER_BITMAP_SLOT);\n        assembly (\"memory-safe\") {\n            $.slot := slot\n        }\n    }\n\n    function _getRegisteredTransceiversStorage() internal pure returns (address[] storage $) {\n        uint256 slot = uint256(REGISTERED_TRANSCEIVERS_SLOT);\n        assembly (\"memory-safe\") {\n            $.slot := slot\n        }\n    }\n\n    function _getNumTransceiversStorage() internal pure returns (_NumTransceivers storage $) {\n        uint256 slot = uint256(NUM_REGISTERED_TRANSCEIVERS_SLOT);\n        assembly (\"memory-safe\") {\n            $.slot := slot\n        }\n    }\n\n    // =============== Storage Getters/Setters ========================================\n\n    function _setTransceiver(address transceiver) internal returns (uint8 index) {\n        mapping(address => TransceiverInfo) storage transceiverInfos = _getTransceiverInfosStorage();\n        _EnabledTransceiverBitmap storage _enabledTransceiverBitmap = _getTransceiverBitmapStorage();\n        address[] storage _enabledTransceivers = _getEnabledTransceiversStorage();\n\n        _NumTransceivers storage _numTransceivers = _getNumTransceiversStorage();\n\n        if (transceiver == address(0)) {\n            revert InvalidTransceiverZeroAddress();\n        }\n\n        if (transceiverInfos[transceiver].registered) {\n            transceiverInfos[transceiver].enabled = true;\n        } else {\n            if (_numTransceivers.registered >= MAX_TRANSCEIVERS) {\n                revert TooManyTransceivers();\n            }\n\n            transceiverInfos[transceiver] = TransceiverInfo({\n                registered: true,\n                enabled: true,\n                index: _numTransceivers.registered\n            });\n            _numTransceivers.registered++;\n            _getRegisteredTransceiversStorage().push(transceiver);\n        }\n\n        _enabledTransceivers.push(transceiver);\n        _numTransceivers.enabled++;\n\n        uint64 updatedEnabledTransceiverBitmap =\n            _enabledTransceiverBitmap.bitmap | uint64(1 << transceiverInfos[transceiver].index);\n        // ensure that this actually changed the bitmap\n        if (updatedEnabledTransceiverBitmap == _enabledTransceiverBitmap.bitmap) {\n            revert TransceiverAlreadyEnabled(transceiver);\n        }\n        _enabledTransceiverBitmap.bitmap = updatedEnabledTransceiverBitmap;\n\n        _checkTransceiversInvariants();\n\n        return transceiverInfos[transceiver].index;\n    }\n\n    function _removeTransceiver(address transceiver) internal {\n        mapping(address => TransceiverInfo) storage transceiverInfos = _getTransceiverInfosStorage();\n        _EnabledTransceiverBitmap storage _enabledTransceiverBitmap = _getTransceiverBitmapStorage();\n        address[] storage _enabledTransceivers = _getEnabledTransceiversStorage();\n\n        if (transceiver == address(0)) {\n            revert InvalidTransceiverZeroAddress();\n        }\n\n        if (!transceiverInfos[transceiver].registered) {\n            revert NonRegisteredTransceiver(transceiver);\n        }\n\n        if (!transceiverInfos[transceiver].enabled) {\n            revert DisabledTransceiver(transceiver);\n        }\n\n        transceiverInfos[transceiver].enabled = false;\n        _getNumTransceiversStorage().enabled--;\n\n        uint64 updatedEnabledTransceiverBitmap =\n            _enabledTransceiverBitmap.bitmap & uint64(~(1 << transceiverInfos[transceiver].index));\n        // ensure that this actually changed the bitmap\n        assert(updatedEnabledTransceiverBitmap < _enabledTransceiverBitmap.bitmap);\n        _enabledTransceiverBitmap.bitmap = updatedEnabledTransceiverBitmap;\n\n        bool removed = false;\n\n        uint256 numEnabledTransceivers = _enabledTransceivers.length;\n        for (uint256 i = 0; i < numEnabledTransceivers; i++) {\n            if (_enabledTransceivers[i] == transceiver) {\n                _enabledTransceivers[i] = _enabledTransceivers[numEnabledTransceivers - 1];\n                _enabledTransceivers.pop();\n                removed = true;\n                break;\n            }\n        }\n        assert(removed);\n\n        _checkTransceiversInvariants();\n        // we call the invariant check on the transceiver here as well, since\n        // the above check only iterates through the enabled transceivers.\n        _checkTransceiverInvariants(transceiver);\n    }\n\n    function _getEnabledTransceiversBitmap() internal view virtual returns (uint64 bitmap) {\n        return _getTransceiverBitmapStorage().bitmap;\n    }\n\n    /// @notice Returns the Transceiver contracts that have been enabled via governance.\n    function getTransceivers() external pure returns (address[] memory result) {\n        result = _getEnabledTransceiversStorage();\n    }\n\n    /// @notice Returns the info for all enabled transceivers\n    function getTransceiverInfo() external view returns (TransceiverInfo[] memory) {\n        address[] memory enabledTransceivers = _getEnabledTransceiversStorage();\n        uint256 numEnabledTransceivers = enabledTransceivers.length;\n        TransceiverInfo[] memory result = new TransceiverInfo[](numEnabledTransceivers);\n\n        for (uint256 i = 0; i < numEnabledTransceivers; ++i) {\n            result[i] = _getTransceiverInfosStorage()[enabledTransceivers[i]];\n        }\n\n        return result;\n    }\n\n    // ============== Invariants =============================================\n\n    /// @dev Check that the transceiver nttManager is in a valid state.\n    /// Checking these invariants is somewhat costly, but we only need to do it\n    /// when modifying the transceivers, which happens infrequently.\n    function _checkTransceiversInvariants() internal view {\n        _NumTransceivers storage _numTransceivers = _getNumTransceiversStorage();\n        address[] storage _enabledTransceivers = _getEnabledTransceiversStorage();\n\n        uint256 numTransceiversEnabled = _numTransceivers.enabled;\n        assert(numTransceiversEnabled == _enabledTransceivers.length);\n\n        for (uint256 i = 0; i < numTransceiversEnabled; i++) {\n            _checkTransceiverInvariants(_enabledTransceivers[i]);\n        }\n\n        // invariant: each transceiver is only enabled once\n        for (uint256 i = 0; i < numTransceiversEnabled; i++) {\n            for (uint256 j = i + 1; j < numTransceiversEnabled; j++) {\n                assert(_enabledTransceivers[i] != _enabledTransceivers[j]);\n            }\n        }\n\n        // invariant: numRegisteredTransceivers <= MAX_TRANSCEIVERS\n        assert(_numTransceivers.registered <= MAX_TRANSCEIVERS);\n    }\n\n    // @dev Check that the transceiver is in a valid state.\n    function _checkTransceiverInvariants(address transceiver) private view {\n        mapping(address => TransceiverInfo) storage transceiverInfos = _getTransceiverInfosStorage();\n        _EnabledTransceiverBitmap storage _enabledTransceiverBitmap = _getTransceiverBitmapStorage();\n        _NumTransceivers storage _numTransceivers = _getNumTransceiversStorage();\n        address[] storage _enabledTransceivers = _getEnabledTransceiversStorage();\n\n        TransceiverInfo memory transceiverInfo = transceiverInfos[transceiver];\n\n        // if an transceiver is not registered, it should not be enabled\n        assert(\n            transceiverInfo.registered || (!transceiverInfo.enabled && transceiverInfo.index == 0)\n        );\n\n        bool transceiverInEnabledBitmap =\n            (_enabledTransceiverBitmap.bitmap & uint64(1 << transceiverInfo.index)) != 0;\n        bool transceiverEnabled = transceiverInfo.enabled;\n\n        bool transceiverInEnabledTransceivers = false;\n\n        for (uint256 i = 0; i < _numTransceivers.enabled; i++) {\n            if (_enabledTransceivers[i] == transceiver) {\n                transceiverInEnabledTransceivers = true;\n                break;\n            }\n        }\n\n        // invariant: transceiverInfos[transceiver].enabled\n        //            <=> enabledTransceiverBitmap & (1 << transceiverInfos[transceiver].index) != 0\n        assert(transceiverInEnabledBitmap == transceiverEnabled);\n\n        // invariant: transceiverInfos[transceiver].enabled <=> transceiver in _enabledTransceivers\n        assert(transceiverInEnabledTransceivers == transceiverEnabled);\n\n        assert(transceiverInfo.index < _numTransceivers.registered);\n    }\n}\n"
      },
      "lib/openzeppelin-contracts/contracts/token/ERC20/extensions/IERC20Metadata.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (token/ERC20/extensions/IERC20Metadata.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../IERC20.sol\";\n\n/**\n * @dev Interface for the optional metadata functions from the ERC20 standard.\n *\n * _Available since v4.1._\n */\ninterface IERC20Metadata is IERC20 {\n    /**\n     * @dev Returns the name of the token.\n     */\n    function name() external view returns (string memory);\n\n    /**\n     * @dev Returns the symbol of the token.\n     */\n    function symbol() external view returns (string memory);\n\n    /**\n     * @dev Returns the decimals places of the token.\n     */\n    function decimals() external view returns (uint8);\n}\n"
      },
      "src/libraries/external/ContextUpgradeable.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.0.1) (utils/Context.sol)\n\n// COPIED FROM OPENZEPPELIN v5.0.1\n// COPIED TO CHANGE SOLC FROM ^0.8.20 TO ^0.8.19\n\npragma solidity ^0.8.19;\n\nimport {Initializable} from \"./Initializable.sol\";\n\n/**\n * @dev Provides information about the current execution context, including the\n * sender of the transaction and its data. While these are generally available\n * via msg.sender and msg.data, they should not be accessed in such a direct\n * manner, since when dealing with meta-transactions the account sending and\n * paying for execution may not be the actual sender (as far as an application\n * is concerned).\n *\n * This contract is only required for intermediate, library-like contracts.\n */\nabstract contract ContextUpgradeable is Initializable {\n    function __Context_init() internal onlyInitializing {}\n\n    function __Context_init_unchained() internal onlyInitializing {}\n\n    function _msgSender() internal view virtual returns (address) {\n        return msg.sender;\n    }\n\n    function _msgData() internal view virtual returns (bytes calldata) {\n        return msg.data;\n    }\n\n    function _contextSuffixLength() internal view virtual returns (uint256) {\n        return 0;\n    }\n}\n"
      },
      "src/libraries/external/Initializable.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.0.0) (proxy/utils/Initializable.sol)\n\n// COPIED FROM OPENZEPPELIN v5.0.1\n// COPIED TO CHANGE SOLC FROM ^0.8.20 TO ^0.8.19\n\npragma solidity ^0.8.19;\n\n/**\n * @dev This is a base contract to aid in writing upgradeable contracts, or any kind of contract that will be deployed\n * behind a proxy. Since proxied contracts do not make use of a constructor, it's common to move constructor logic to an\n * external initializer function, usually called `initialize`. It then becomes necessary to protect this initializer\n * function so it can only be called once. The {initializer} modifier provided by this contract will have this effect.\n *\n * The initialization functions use a version number. Once a version number is used, it is consumed and cannot be\n * reused. This mechanism prevents re-execution of each \"step\" but allows the creation of new initialization steps in\n * case an upgrade adds a module that needs to be initialized.\n *\n * For example:\n *\n * [.hljs-theme-light.nopadding]\n * ```solidity\n * contract MyToken is ERC20Upgradeable {\n *     function initialize() initializer public {\n *         __ERC20_init(\"MyToken\", \"MTK\");\n *     }\n * }\n *\n * contract MyTokenV2 is MyToken, ERC20PermitUpgradeable {\n *     function initializeV2() reinitializer(2) public {\n *         __ERC20Permit_init(\"MyToken\");\n *     }\n * }\n * ```\n *\n * TIP: To avoid leaving the proxy in an uninitialized state, the initializer function should be called as early as\n * possible by providing the encoded function call as the `_data` argument to {ERC1967Proxy-constructor}.\n *\n * CAUTION: When used with inheritance, manual care must be taken to not invoke a parent initializer twice, or to ensure\n * that all initializers are idempotent. This is not verified automatically as constructors are by Solidity.\n *\n * [CAUTION]\n * ====\n * Avoid leaving a contract uninitialized.\n *\n * An uninitialized contract can be taken over by an attacker. This applies to both a proxy and its implementation\n * contract, which may impact the proxy. To prevent the implementation contract from being used, you should invoke\n * the {_disableInitializers} function in the constructor to automatically lock it when it is deployed:\n *\n * [.hljs-theme-light.nopadding]\n * ```\n * /// @custom:oz-upgrades-unsafe-allow constructor\n * constructor() {\n *     _disableInitializers();\n * }\n * ```\n * ====\n */\nabstract contract Initializable {\n    /**\n     * @dev Storage of the initializable contract.\n     *\n     * It's implemented on a custom ERC-7201 namespace to reduce the risk of storage collisions\n     * when using with upgradeable contracts.\n     *\n     * @custom:storage-location erc7201:openzeppelin.storage.Initializable\n     */\n    struct InitializableStorage {\n        /**\n         * @dev Indicates that the contract has been initialized.\n         */\n        uint64 _initialized;\n        /**\n         * @dev Indicates that the contract is in the process of being initialized.\n         */\n        bool _initializing;\n    }\n\n    // keccak256(abi.encode(uint256(keccak256(\"openzeppelin.storage.Initializable\")) - 1)) & ~bytes32(uint256(0xff))\n    bytes32 private constant INITIALIZABLE_STORAGE =\n        0xf0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00;\n\n    /**\n     * @dev The contract is already initialized.\n     */\n    error InvalidInitialization();\n\n    /**\n     * @dev The contract is not initializing.\n     */\n    error NotInitializing();\n\n    /**\n     * @dev Triggered when the contract has been initialized or reinitialized.\n     */\n    event Initialized(uint64 version);\n\n    /**\n     * @dev A modifier that defines a protected initializer function that can be invoked at most once. In its scope,\n     * `onlyInitializing` functions can be used to initialize parent contracts.\n     *\n     * Similar to `reinitializer(1)`, except that in the context of a constructor an `initializer` may be invoked any\n     * number of times. This behavior in the constructor can be useful during testing and is not expected to be used in\n     * production.\n     *\n     * Emits an {Initialized} event.\n     */\n    modifier initializer() {\n        // solhint-disable-next-line var-name-mixedcase\n        InitializableStorage storage $ = _getInitializableStorage();\n\n        // Cache values to avoid duplicated sloads\n        bool isTopLevelCall = !$._initializing;\n        uint64 initialized = $._initialized;\n\n        // Allowed calls:\n        // - initialSetup: the contract is not in the initializing state and no previous version was\n        //                 initialized\n        // - construction: the contract is initialized at version 1 (no reininitialization) and the\n        //                 current contract is just being deployed\n        bool initialSetup = initialized == 0 && isTopLevelCall;\n        bool construction = initialized == 1 && address(this).code.length == 0;\n\n        if (!initialSetup && !construction) {\n            revert InvalidInitialization();\n        }\n        $._initialized = 1;\n        if (isTopLevelCall) {\n            $._initializing = true;\n        }\n        _;\n        if (isTopLevelCall) {\n            $._initializing = false;\n            emit Initialized(1);\n        }\n    }\n\n    /**\n     * @dev A modifier that defines a protected reinitializer function that can be invoked at most once, and only if the\n     * contract hasn't been initialized to a greater version before. In its scope, `onlyInitializing` functions can be\n     * used to initialize parent contracts.\n     *\n     * A reinitializer may be used after the original initialization step. This is essential to configure modules that\n     * are added through upgrades and that require initialization.\n     *\n     * When `version` is 1, this modifier is similar to `initializer`, except that functions marked with `reinitializer`\n     * cannot be nested. If one is invoked in the context of another, execution will revert.\n     *\n     * Note that versions can jump in increments greater than 1; this implies that if multiple reinitializers coexist in\n     * a contract, executing them in the right order is up to the developer or operator.\n     *\n     * WARNING: Setting the version to 2**64 - 1 will prevent any future reinitialization.\n     *\n     * Emits an {Initialized} event.\n     */\n    modifier reinitializer(uint64 version) {\n        // solhint-disable-next-line var-name-mixedcase\n        InitializableStorage storage $ = _getInitializableStorage();\n\n        if ($._initializing || $._initialized >= version) {\n            revert InvalidInitialization();\n        }\n        $._initialized = version;\n        $._initializing = true;\n        _;\n        $._initializing = false;\n        emit Initialized(version);\n    }\n\n    /**\n     * @dev Modifier to protect an initialization function so that it can only be invoked by functions with the\n     * {initializer} and {reinitializer} modifiers, directly or indirectly.\n     */\n    modifier onlyInitializing() {\n        _checkInitializing();\n        _;\n    }\n\n    /**\n     * @dev Reverts if the contract is not in an initializing state. See {onlyInitializing}.\n     */\n    function _checkInitializing() internal view virtual {\n        if (!_isInitializing()) {\n            revert NotInitializing();\n        }\n    }\n\n    /**\n     * @dev Locks the contract, preventing any future reinitialization. This cannot be part of an initializer call.\n     * Calling this in the constructor of a contract will prevent that contract from being initialized or reinitialized\n     * to any version. It is recommended to use this to lock implementation contracts that are designed to be called\n     * through proxies.\n     *\n     * Emits an {Initialized} event the first time it is successfully executed.\n     */\n    function _disableInitializers() internal virtual {\n        // solhint-disable-next-line var-name-mixedcase\n        InitializableStorage storage $ = _getInitializableStorage();\n\n        if ($._initializing) {\n            revert InvalidInitialization();\n        }\n        if ($._initialized != type(uint64).max) {\n            $._initialized = type(uint64).max;\n            emit Initialized(type(uint64).max);\n        }\n    }\n\n    /**\n     * @dev Returns the highest version that has been initialized. See {reinitializer}.\n     */\n    function _getInitializedVersion() internal view returns (uint64) {\n        return _getInitializableStorage()._initialized;\n    }\n\n    /**\n     * @dev Returns `true` if the contract is currently initializing. See {onlyInitializing}.\n     */\n    function _isInitializing() internal view returns (bool) {\n        return _getInitializableStorage()._initializing;\n    }\n\n    /**\n     * @dev Returns a pointer to the storage namespace.\n     */\n    // solhint-disable-next-line var-name-mixedcase\n    function _getInitializableStorage() private pure returns (InitializableStorage storage $) {\n        assembly {\n            $.slot := INITIALIZABLE_STORAGE\n        }\n    }\n}\n"
      },
      "src/interfaces/IOwnableUpgradeable.sol": {
        "content": "// SPDX-License-Identifier: Apache 2\n//\npragma solidity >=0.8.8 <0.9.0;\n\ninterface IOwnableUpgradeable {\n    function owner() external view returns (address);\n}\n"
      },
      "src/libraries/PausableUpgradeable.sol": {
        "content": "// SPDX-License-Identifier: Apache 2\npragma solidity >=0.8.8 <0.9.0;\n\n/**\n * @dev Contact Module that allows children to implement logic to pause and unpause the contract.\n * This is based on the OpenZeppelin Pausable contract but makes use of deterministic storage slots\n * and the EVM native word size to optimize gas costs.\n *\n * The `whenPaused` and `whenNotPaused` modifiers are used to\n * execute code based on the current state of the contract.\n *\n */\nimport {Initializable} from \"./external/Initializable.sol\";\n\nabstract contract PausableUpgradeable is Initializable {\n    /*\n     * @custom:storage-location erc7201:openzeppelin.storage.Pausable.\n     * @dev Storage slot with the pauser account, this is managed by the `PauserStorage` struct\n    */\n    struct PauserStorage {\n        address _pauser;\n    }\n\n    // @dev Storage slot with the pause flag, this is managed by the `PauseStorage` struct\n    struct PauseStorage {\n        uint256 _pauseFlag;\n    }\n\n    /// NOTE: use uint256 to save on gas because it is the native word size of the EVM\n    /// it is cheaper than using a bool because modifying a boolean value requires an extra SLOAD\n    uint256 private constant NOT_PAUSED = 1;\n    uint256 private constant PAUSED = 2;\n\n    event PauserTransferred(address indexed oldPauser, address indexed newPauser);\n\n    /**\n     * @dev Contract is not paused, functionality is unblocked\n     */\n    error RequireContractIsNotPaused();\n    /**\n     * @dev Contract state is paused, blocking\n     */\n    error RequireContractIsPaused();\n\n    /**\n     * @dev the pauser is not a valid pauser account (e.g. `address(0)`)\n     */\n    error InvalidPauser(address account);\n\n    // @dev Emitted when the contract is paused\n    event Paused(bool paused);\n    event NotPaused(bool notPaused);\n\n    bytes32 private constant PAUSE_SLOT = bytes32(uint256(keccak256(\"Pause.pauseFlag\")) - 1);\n    bytes32 private constant PAUSER_ROLE_SLOT = bytes32(uint256(keccak256(\"Pause.pauseRole\")) - 1);\n\n    function _getPauserStorage() internal pure returns (PauserStorage storage $) {\n        uint256 slot = uint256(PAUSER_ROLE_SLOT);\n        assembly (\"memory-safe\") {\n            $.slot := slot\n        }\n    }\n\n    /**\n     * @dev Returns the current pauser account address.\n     */\n    function pauser() public view returns (address) {\n        return _getPauserStorage()._pauser;\n    }\n\n    function _getPauseStorage() private pure returns (PauseStorage storage $) {\n        uint256 slot = uint256(PAUSE_SLOT);\n        assembly (\"memory-safe\") {\n            $.slot := slot\n        }\n    }\n\n    function _setPauseStorage(uint256 pauseFlag) internal {\n        _getPauseStorage()._pauseFlag = pauseFlag;\n    }\n\n    function __Paused_init(address initialPauser) internal onlyInitializing {\n        __Paused_init_unchained(initialPauser);\n    }\n\n    function __Paused_init_unchained(address initialPauser) internal onlyInitializing {\n        // set pause flag to false initially\n        PauseStorage storage $ = _getPauseStorage();\n        $._pauseFlag = NOT_PAUSED;\n\n        // set the initial pauser\n        PauserStorage storage $_role = _getPauserStorage();\n        $_role._pauser = initialPauser;\n    }\n\n    /**\n     * @dev Modifier to make a function callable only when the contract is not paused.\n     * Calling a function when this flag is set to `PAUSED` will cause the transaction to revert.\n     */\n    modifier whenNotPaused() {\n        if (isPaused()) {\n            revert RequireContractIsNotPaused();\n        }\n        _;\n    }\n\n    /**\n     * @dev Modifier to make a function callable only when the contract is not paused.\n     * Calling a function when this flag is set to `PAUSED` will cause the transaction to revert.\n     */\n    modifier whenPaused() {\n        if (!isPaused()) {\n            revert RequireContractIsPaused();\n        }\n        _;\n    }\n\n    /*\n     * @dev Modifier to allow only the Pauser to access pausing functionality\n     */\n    modifier onlyPauser() {\n        _checkPauser();\n        _;\n    }\n\n    /*\n     * @dev Modifier to allow only the Pauser to access some functionality\n     */\n    function _checkPauser() internal view {\n        if (pauser() != msg.sender) {\n            revert InvalidPauser(msg.sender);\n        }\n    }\n\n    /**\n     * @dev pauses the function and emits the `Paused` event\n     */\n    function _pause() internal virtual whenNotPaused {\n        // this can only be set to PAUSED when the state is NOTPAUSED\n        _setPauseStorage(PAUSED);\n        emit Paused(true);\n    }\n\n    /**\n     * @dev unpauses the function\n     */\n    function _unpause() internal virtual whenPaused {\n        // this can only be set to NOTPAUSED when the state is PAUSED\n        _setPauseStorage(NOT_PAUSED);\n        emit NotPaused(false);\n    }\n\n    /**\n     * @dev Returns true if the method is paused, and false otherwise.\n     */\n    function isPaused() public view returns (bool) {\n        PauseStorage storage $ = _getPauseStorage();\n        return $._pauseFlag == PAUSED;\n    }\n}\n"
      },
      "lib/openzeppelin-contracts/contracts/proxy/ERC1967/ERC1967Upgrade.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.5.0) (proxy/ERC1967/ERC1967Upgrade.sol)\n\npragma solidity ^0.8.2;\n\nimport \"../beacon/IBeacon.sol\";\nimport \"../../interfaces/draft-IERC1822.sol\";\nimport \"../../utils/Address.sol\";\nimport \"../../utils/StorageSlot.sol\";\n\n/**\n * @dev This abstract contract provides getters and event emitting update functions for\n * https://eips.ethereum.org/EIPS/eip-1967[EIP1967] slots.\n *\n * _Available since v4.1._\n *\n * @custom:oz-upgrades-unsafe-allow delegatecall\n */\nabstract contract ERC1967Upgrade {\n    // This is the keccak-256 hash of \"eip1967.proxy.rollback\" subtracted by 1\n    bytes32 private constant _ROLLBACK_SLOT = 0x4910fdfa16fed3260ed0e7147f7cc6da11a60208b5b9406d12a635614ffd9143;\n\n    /**\n     * @dev Storage slot with the address of the current implementation.\n     * This is the keccak-256 hash of \"eip1967.proxy.implementation\" subtracted by 1, and is\n     * validated in the constructor.\n     */\n    bytes32 internal constant _IMPLEMENTATION_SLOT = 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc;\n\n    /**\n     * @dev Emitted when the implementation is upgraded.\n     */\n    event Upgraded(address indexed implementation);\n\n    /**\n     * @dev Returns the current implementation address.\n     */\n    function _getImplementation() internal view returns (address) {\n        return StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value;\n    }\n\n    /**\n     * @dev Stores a new address in the EIP1967 implementation slot.\n     */\n    function _setImplementation(address newImplementation) private {\n        require(Address.isContract(newImplementation), \"ERC1967: new implementation is not a contract\");\n        StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value = newImplementation;\n    }\n\n    /**\n     * @dev Perform implementation upgrade\n     *\n     * Emits an {Upgraded} event.\n     */\n    function _upgradeTo(address newImplementation) internal {\n        _setImplementation(newImplementation);\n        emit Upgraded(newImplementation);\n    }\n\n    /**\n     * @dev Perform implementation upgrade with additional setup call.\n     *\n     * Emits an {Upgraded} event.\n     */\n    function _upgradeToAndCall(\n        address newImplementation,\n        bytes memory data,\n        bool forceCall\n    ) internal {\n        _upgradeTo(newImplementation);\n        if (data.length > 0 || forceCall) {\n            Address.functionDelegateCall(newImplementation, data);\n        }\n    }\n\n    /**\n     * @dev Perform implementation upgrade with security checks for UUPS proxies, and additional setup call.\n     *\n     * Emits an {Upgraded} event.\n     */\n    function _upgradeToAndCallUUPS(\n        address newImplementation,\n        bytes memory data,\n        bool forceCall\n    ) internal {\n        // Upgrades from old implementations will perform a rollback test. This test requires the new\n        // implementation to upgrade back to the old, non-ERC1822 compliant, implementation. Removing\n        // this special case will break upgrade paths from old UUPS implementation to new ones.\n        if (StorageSlot.getBooleanSlot(_ROLLBACK_SLOT).value) {\n            _setImplementation(newImplementation);\n        } else {\n            try IERC1822Proxiable(newImplementation).proxiableUUID() returns (bytes32 slot) {\n                require(slot == _IMPLEMENTATION_SLOT, \"ERC1967Upgrade: unsupported proxiableUUID\");\n            } catch {\n                revert(\"ERC1967Upgrade: new implementation is not UUPS\");\n            }\n            _upgradeToAndCall(newImplementation, data, forceCall);\n        }\n    }\n\n    /**\n     * @dev Storage slot with the admin of the contract.\n     * This is the keccak-256 hash of \"eip1967.proxy.admin\" subtracted by 1, and is\n     * validated in the constructor.\n     */\n    bytes32 internal constant _ADMIN_SLOT = 0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103;\n\n    /**\n     * @dev Emitted when the admin account has changed.\n     */\n    event AdminChanged(address previousAdmin, address newAdmin);\n\n    /**\n     * @dev Returns the current admin.\n     */\n    function _getAdmin() internal view returns (address) {\n        return StorageSlot.getAddressSlot(_ADMIN_SLOT).value;\n    }\n\n    /**\n     * @dev Stores a new address in the EIP1967 admin slot.\n     */\n    function _setAdmin(address newAdmin) private {\n        require(newAdmin != address(0), \"ERC1967: new admin is the zero address\");\n        StorageSlot.getAddressSlot(_ADMIN_SLOT).value = newAdmin;\n    }\n\n    /**\n     * @dev Changes the admin of the proxy.\n     *\n     * Emits an {AdminChanged} event.\n     */\n    function _changeAdmin(address newAdmin) internal {\n        emit AdminChanged(_getAdmin(), newAdmin);\n        _setAdmin(newAdmin);\n    }\n\n    /**\n     * @dev The storage slot of the UpgradeableBeacon contract which defines the implementation for this proxy.\n     * This is bytes32(uint256(keccak256('eip1967.proxy.beacon')) - 1)) and is validated in the constructor.\n     */\n    bytes32 internal constant _BEACON_SLOT = 0xa3f0ad74e5423aebfd80d3ef4346578335a9a72aeaee59ff6cb3582b35133d50;\n\n    /**\n     * @dev Emitted when the beacon is upgraded.\n     */\n    event BeaconUpgraded(address indexed beacon);\n\n    /**\n     * @dev Returns the current beacon.\n     */\n    function _getBeacon() internal view returns (address) {\n        return StorageSlot.getAddressSlot(_BEACON_SLOT).value;\n    }\n\n    /**\n     * @dev Stores a new beacon in the EIP1967 beacon slot.\n     */\n    function _setBeacon(address newBeacon) private {\n        require(Address.isContract(newBeacon), \"ERC1967: new beacon is not a contract\");\n        require(\n            Address.isContract(IBeacon(newBeacon).implementation()),\n            \"ERC1967: beacon implementation is not a contract\"\n        );\n        StorageSlot.getAddressSlot(_BEACON_SLOT).value = newBeacon;\n    }\n\n    /**\n     * @dev Perform beacon upgrade with additional setup call. Note: This upgrades the address of the beacon, it does\n     * not upgrade the implementation contained in the beacon (see {UpgradeableBeacon-_setImplementation} for that).\n     *\n     * Emits a {BeaconUpgraded} event.\n     */\n    function _upgradeBeaconToAndCall(\n        address newBeacon,\n        bytes memory data,\n        bool forceCall\n    ) internal {\n        _setBeacon(newBeacon);\n        emit BeaconUpgraded(newBeacon);\n        if (data.length > 0 || forceCall) {\n            Address.functionDelegateCall(IBeacon(newBeacon).implementation(), data);\n        }\n    }\n}\n"
      },
      "lib/openzeppelin-contracts/contracts/proxy/beacon/IBeacon.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (proxy/beacon/IBeacon.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev This is the interface that {BeaconProxy} expects of its beacon.\n */\ninterface IBeacon {\n    /**\n     * @dev Must return an address that can be used as a delegate call target.\n     *\n     * {BeaconProxy} will check that this address is a contract.\n     */\n    function implementation() external view returns (address);\n}\n"
      },
      "lib/openzeppelin-contracts/contracts/interfaces/draft-IERC1822.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.5.0) (interfaces/draft-IERC1822.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev ERC1822: Universal Upgradeable Proxy Standard (UUPS) documents a method for upgradeability through a simplified\n * proxy whose upgrades are fully controlled by the current implementation.\n */\ninterface IERC1822Proxiable {\n    /**\n     * @dev Returns the storage slot that the proxiable contract assumes is being used to store the implementation\n     * address.\n     *\n     * IMPORTANT: A proxy pointing at a proxiable contract should not be considered proxiable itself, because this risks\n     * bricking a proxy that upgrades to it, by delegating to itself until out of gas. Thus it is critical that this\n     * function revert if invoked through a proxy.\n     */\n    function proxiableUUID() external view returns (bytes32);\n}\n"
      },
      "lib/openzeppelin-contracts/contracts/utils/StorageSlot.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.7.0) (utils/StorageSlot.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Library for reading and writing primitive types to specific storage slots.\n *\n * Storage slots are often used to avoid storage conflict when dealing with upgradeable contracts.\n * This library helps with reading and writing to such slots without the need for inline assembly.\n *\n * The functions in this library return Slot structs that contain a `value` member that can be used to read or write.\n *\n * Example usage to set ERC1967 implementation slot:\n * ```\n * contract ERC1967 {\n *     bytes32 internal constant _IMPLEMENTATION_SLOT = 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc;\n *\n *     function _getImplementation() internal view returns (address) {\n *         return StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value;\n *     }\n *\n *     function _setImplementation(address newImplementation) internal {\n *         require(Address.isContract(newImplementation), \"ERC1967: new implementation is not a contract\");\n *         StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value = newImplementation;\n *     }\n * }\n * ```\n *\n * _Available since v4.1 for `address`, `bool`, `bytes32`, and `uint256`._\n */\nlibrary StorageSlot {\n    struct AddressSlot {\n        address value;\n    }\n\n    struct BooleanSlot {\n        bool value;\n    }\n\n    struct Bytes32Slot {\n        bytes32 value;\n    }\n\n    struct Uint256Slot {\n        uint256 value;\n    }\n\n    /**\n     * @dev Returns an `AddressSlot` with member `value` located at `slot`.\n     */\n    function getAddressSlot(bytes32 slot) internal pure returns (AddressSlot storage r) {\n        /// @solidity memory-safe-assembly\n        assembly {\n            r.slot := slot\n        }\n    }\n\n    /**\n     * @dev Returns an `BooleanSlot` with member `value` located at `slot`.\n     */\n    function getBooleanSlot(bytes32 slot) internal pure returns (BooleanSlot storage r) {\n        /// @solidity memory-safe-assembly\n        assembly {\n            r.slot := slot\n        }\n    }\n\n    /**\n     * @dev Returns an `Bytes32Slot` with member `value` located at `slot`.\n     */\n    function getBytes32Slot(bytes32 slot) internal pure returns (Bytes32Slot storage r) {\n        /// @solidity memory-safe-assembly\n        assembly {\n            r.slot := slot\n        }\n    }\n\n    /**\n     * @dev Returns an `Uint256Slot` with member `value` located at `slot`.\n     */\n    function getUint256Slot(bytes32 slot) internal pure returns (Uint256Slot storage r) {\n        /// @solidity memory-safe-assembly\n        assembly {\n            r.slot := slot\n        }\n    }\n}\n"
      }
    },
    "settings": {
      "remappings": [
        "forge-std/=lib/forge-std/src/",
        "openzeppelin-contracts/=lib/openzeppelin-contracts/",
        "wormhole-solidity-sdk/=lib/wormhole-solidity-sdk/src/"
      ],
      "optimizer": {
        "enabled": true,
        "runs": 200
      },
      "metadata": {
        "useLiteralContent": false,
        "bytecodeHash": "ipfs",
        "appendCBOR": true
      },
      "outputSelection": {
        "*": {
          "*": [
            "evm.bytecode",
            "evm.deployedBytecode",
            "devdoc",
            "userdoc",
            "metadata",
            "abi"
          ]
        }
      },
      "evmVersion": "london",
      "viaIR": true,
      "libraries": {
        "src/libraries/TransceiverStructs.sol": {
          "TransceiverStructs": "0xEd288A6564797f63aaFb388243fA2C3Ac11dD5a8"
        }
      }
    }
  }}