Free 30-min Web3 Consultation
Book Consultation
Smart Contract Security Audits
View Audit Services
Custom DeFi Protocol Development
Explore DeFi
Full-Stack Web3 dApp Development
View App Services
Free 30-min Web3 Consultation
Book Consultation
Smart Contract Security Audits
View Audit Services
Custom DeFi Protocol Development
Explore DeFi
Full-Stack Web3 dApp Development
View App Services
Free 30-min Web3 Consultation
Book Consultation
Smart Contract Security Audits
View Audit Services
Custom DeFi Protocol Development
Explore DeFi
Full-Stack Web3 dApp Development
View App Services
Free 30-min Web3 Consultation
Book Consultation
Smart Contract Security Audits
View Audit Services
Custom DeFi Protocol Development
Explore DeFi
Full-Stack Web3 dApp Development
View App Services
LABS
Guides

Setting Up Cross-Chain Messaging for Payment Instructions

A technical guide for developers implementing secure cross-chain messaging protocols to relay payment instructions and settlement confirmations between blockchains.
Chainscore © 2026
introduction
FUNDAMENTALS

Introduction to Cross-Chain Payment Messaging

Cross-chain payment messaging enables smart contracts on one blockchain to securely instruct payments on another. This guide explains the core concepts and setup.

Cross-chain payment messaging is a specialized subset of interoperability that allows a dApp or smart contract on a source chain (like Ethereum) to send payment instructions to a destination chain (like Polygon). Unlike simple asset transfers via bridges, this involves sending structured data—such as recipient addresses, token amounts, and payment conditions—that a target contract can execute. Protocols like Axelar, LayerZero, and Wormhole provide the generalized messaging layer that makes this possible, abstracting away the underlying complexity of consensus and validation between heterogeneous chains.

The architecture typically involves three core components: the source application contract, the cross-chain messaging protocol, and the destination executor contract. Your source contract calls the messenger's API (e.g., send()), which is then observed by the protocol's decentralized network of validators or relayers. These actors attest to the message's validity and deliver it to the destination chain. A pre-deployed Gateway or Endpoint contract on the destination verifies the attestation and forwards the payload to your specified target address, which finally executes the logic, such as minting tokens or releasing funds.

Setting up a basic cross-chain payment starts with choosing a protocol. For developers, key considerations include security model (validators vs. light clients), supported chains, cost, and latency. Using Axelar as an example, you would first fund your source chain contract with the protocol's native gas token (e.g., AXL). Your contract then calls callContract on the Axelar Gateway, passing the destination chain name, destination contract address, and the encoded payment instruction payload. The payload is arbitrary bytes, often an ABI-encoded function call like transfer(address to, uint256 amount).

Here is a simplified Solidity example for a source contract using a hypothetical cross-chain messenger. This contract instructs a payment on another chain.

solidity
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

interface ICrossChainMessenger {
    function sendMessage(
        string calldata destinationChain,
        address targetContract,
        bytes calldata payload
    ) external payable;
}

contract PaymentInitiator {
    ICrossChainMessenger public immutable messenger;

    constructor(address messengerAddress) {
        messenger = ICrossChainMessenger(messengerAddress);
    }

    function instructPayment(
        string calldata destChain,
        address destVault,
        address recipient,
        uint256 amount
    ) external payable {
        // Encode the function call for the destination contract
        bytes memory payload = abi.encodeWithSignature(
            "releasePayment(address,uint256)",
            recipient,
            amount
        );
        // Send the cross-chain message
        messenger.sendMessage{value: msg.value}(destChain, destVault, payload);
    }
}

The destination contract must have a function, like releasePayment, that can be called by the protocol's secure relayer to fulfill the instruction.

Security is paramount. You must validate all incoming messages on the destination chain. Ensure the caller is the authenticated relayer contract from your chosen protocol, not any random address. Also implement replay protection, as the same message could be delivered multiple times. Use nonces or processed message IDs. Finally, design for message failure; protocols may offer retry mechanisms or you need to implement a manual override for stuck payments. Always audit the trust assumptions of the underlying messaging protocol, as it becomes a critical dependency in your system's security.

Use cases extend beyond simple transfers. This pattern enables cross-chain payroll, where an Ethereum DAO pays contributors on Arbitrum; conditional payments released upon verification of an event on another chain; and multi-chain treasury management. By leveraging generalized messaging, developers can build cohesive application logic that operates across the fragmented blockchain ecosystem, moving value and triggering actions wherever they are most efficient or necessary.

prerequisites
CROSS-CHAIN MESSAGING

Prerequisites and Setup

This guide outlines the essential tools and configurations required to build a cross-chain payment system using modern interoperability protocols.

To implement cross-chain payment instructions, you need a foundational setup. This includes a development environment with Node.js (v18+), a package manager like npm or yarn, and a code editor. You will also require blockchain access, which means setting up RPC endpoints for the source and destination chains (e.g., Ethereum Sepolia, Polygon Amoy). Securely manage these endpoints and your private keys using environment variables with a .env file. Finally, you'll need testnet tokens for gas fees on all involved networks, which can be obtained from official faucets.

The core of cross-chain messaging is the interoperability protocol. We will use the Axelar General Message Passing (GMP) service as our primary example, as it provides a standardized, secure way to call contracts across chains. You must install the Axelar SDK (@axelar-network/axelarjs-sdk) and potentially the axelar-local-dev package for local testing. Alternatively, for a more direct but complex approach, you could use LayerZero's Endpoint interface or Wormhole's Token Bridge and Core Bridge contracts. Each protocol has its own SDK and smart contract interfaces that must be integrated.

On the smart contract side, you need to understand and deploy two key components: the source chain sender and the destination chain executor. The sender contract on Chain A initiates the cross-chain call using the chosen protocol's gateway. The executor contract on Chain B receives the validated message and executes the payment logic. Both contracts must be written in Solidity (>=0.8.0) and use the official interfaces provided by your chosen interoperability protocol (e.g., IAxelarExecutable). You will use development frameworks like Hardhat or Foundry to compile, test, and deploy these contracts.

A critical prerequisite is funding the cross-chain gas fee. When a message is sent, the executor contract on the destination chain needs gas to run. With Axelar GMP, you can pay for this gas on the source chain in its native token, a feature called Gas Express. You must estimate this cost and ensure your sender contract calls the payNativeGasForContractCall function. With LayerZero, you typically send native gas for the destination chain's executor as part of the message payload. Incorrect gas estimation is a common point of failure, so testing with small amounts first is essential.

Before going to production, comprehensive testing is mandatory. Use local development networks like Axelar Local Dev or the LayerZero Testnet to simulate the entire flow without spending real gas. Write unit tests for your sender and executor contracts, and integration tests that simulate the full cross-chain transaction. Monitor for events like Executed on the destination chain to confirm success. Always start with testnets (e.g., Sepolia, Amoy, BNB Testnet) and use small, fractional amounts to validate the entire pipeline—from user initiation on Chain A to fund reception on Chain B—before committing significant value.

key-concepts-text
CROSS-CHAIN MESSAGING

Core Concepts: Relayers, Packets, and Verification

A technical breakdown of the fundamental components required to send payment instructions across blockchains using IBC.

Cross-chain messaging for payments requires a standardized framework to ensure secure, verifiable, and trust-minimized value transfer. The Inter-Blockchain Communication (IBC) protocol provides this by defining three core abstractions: relayers, packets, and verification. Relayers are permissionless off-chain processes that transport data, while packets are the structured data units containing your payment instructions. Verification is the on-chain mechanism that allows a destination chain to cryptographically prove a packet was sent and committed on the source chain, without trusting the relayer.

An IBC packet is the atomic unit of communication. For a payment instruction, it contains essential data in its packet data field, such as the sender, receiver, denomination, and amount. This data is serialized, often using Protocol Buffers. The packet header includes critical metadata: the source and destination channel/port identifiers and a sequence number for ordering. The packet is hashed and this commitment is stored on the source chain's state. A relayer cannot alter the packet; it can only submit proof of its existence.

Relayers (like Hermes or Go Relayer) are not trusted intermediaries. Their role is operational: they scan the event logs of chains, fetch the proof that a packet commitment exists on the source chain, and submit the packet data along with this proof to the destination chain. They also perform the reverse path for acknowledgments. Since they do not custody funds or dictate state changes, their failure only causes delay, not loss of funds. Running a relayer requires access to RPC endpoints for both chains and a funded account to pay for transaction fees.

Verification is the security heart of IBC. The destination chain does not take the relayer's word. Instead, it uses a light client to verify the submitted proof. This light client maintains a minimal, up-to-date header of the source chain. The proof demonstrates that the packet commitment is included in a block that has been finalized according to the source chain's consensus rules. Common verification patterns include ICS-23 for Merkle proof verification and ICS-02 for client state validation. This creates a trust assumption only in the security of the connected chains, not the relayer.

To set up a payment channel, you first establish an IBC client on both chains, which tracks the other chain's consensus state. Next, you create a connection over which multiple channels can run. Finally, you open a channel on a specific port (like transfer for fungible tokens). The relayer software executes the handshake transactions for these steps. Once the channel is OPEN, you can send packets. The entire flow—from packet creation on Chain A, to commitment, relaying, verification, and execution on Chain B—ensures payment instructions are carried out exactly as intended.

PROTOCOL SELECTION

Cross-Chain Messaging Protocol Comparison

A technical comparison of leading protocols for sending payment instructions between blockchains, focusing on security, cost, and finality.

Feature / MetricLayerZeroWormholeAxelar

Security Model

Decentralized Verifier Network

Guardian Multisig (19/20)

Threshold Signature (8/13)

Message Finality

< 1 min

~15 sec (Solana)

~6 min (Ethereum)

Supported Chains

50+

30+

55+

Gas Abstraction

Average Cost (Simple TX)

$2-5

$0.25-1

$0.50-2

Programmability

Omnichain Contracts

Cross-Chain Query

General Message Passing

Native Token Required

Time to Finality (Optimistic)

~20 min

Instant

~6 min

message-format-deep-dive
CROSS-CHAIN MESSAGING

Designing Payment Instruction Packets

A payment instruction packet is the structured data payload that defines a cross-chain transaction, containing all necessary information for execution on the destination chain.

A payment instruction packet is the core data structure in cross-chain messaging. It is a serialized object, typically in JSON or a binary format like Protobuf, that contains the essential parameters for a transaction on a target blockchain. This packet is created by the source chain application, transmitted via a secure messaging protocol like Axelar, LayerZero, or Wormhole, and then decoded and executed by a smart contract on the destination chain. Its design directly impacts the security, cost, and interoperability of the cross-chain application.

The packet's structure must be deterministic and unambiguous. Key fields include a unique identifier (like a nonce or UUID) to prevent replay attacks, the destination chain ID and contract address, the target function selector (e.g., a 4-byte function signature), and the calldata payload containing the function arguments. It should also include a gas limit or payment for relayer services and a timestamp or expiry block to ensure the instruction is not executed after a certain period. Standardizing these fields, perhaps using formats like the Inter-Blockchain Communication (IBC) packet, improves compatibility.

Here is a conceptual example of a payment instruction packet in JSON format for a cross-chain token transfer:

json
{
  "version": "1.0",
  "id": "0xabc123...",
  "srcChain": "ethereum-1",
  "dstChain": "avalanche-43114",
  "dstContract": "0x742d35Cc6634C0532925a3b844Bc9e...",
  "function": "swapAndBridge",
  "payload": {
    "tokenIn": "0xA0b86991c6218b36c1d19D4a2e9...",
    "amountIn": "1000000000",
    "minAmountOut": "950000000",
    "recipient": "0xRecipientAddress..."
  },
  "gasLimit": "250000",
  "expiry": 19283746
}

The receiving contract parses this packet, validates the sender and signature, and executes the encoded logic.

Security is paramount in packet design. The packet must be authenticated to prove it originated from a trusted source chain contract. This is typically done by having the source contract emit the packet as a verifiable event or by having a relayer attest to its validity. The destination contract must verify this proof before execution. Furthermore, the packet data should be validated on-chain: checking expiry, ensuring the destination contract is the intended recipient, and verifying that the payload adheres to expected formats to prevent malicious calldata injection.

To implement this, you would first deploy a sender contract on the source chain (e.g., Ethereum) and a receiver contract on the destination chain (e.g., Polygon). The sender contract constructs the packet, often hashing its contents to create a unique identifier, and calls the messaging layer's gateway. For instance, using Axelar, you would call callContract on the AxelarGateway with the destination chain and address. The receiver contract implements the execute function specified by the protocol, which receives the packet's payload and source chain metadata, allowing it to reconstruct and process the original instruction.

relayer-network-setup
CROSS-CHAIN INFRASTRUCTURE

Configuring and Running a Relayer

A relayer is a critical off-chain service that listens for events on a source chain, packages messages, and submits transactions to deliver them to a destination chain. This guide covers the setup for a payment instruction workflow.

A relayer acts as the messenger between blockchains. In a cross-chain payment system, when a user initiates a payment on Chain A, a smart contract emits an event containing the payment instruction. The relayer's primary job is to detect this event, fetch the necessary proof (like a Merkle proof), and call a function on the destination chain's smart contract (Chain B) to execute the instruction. This requires the relayer to maintain RPC connections to both networks and hold private keys for funding gas fees on the destination chain.

Configuration starts with environment variables. You must define endpoints for the source and destination chain RPCs (e.g., https://eth-mainnet.g.alchemy.com, https://polygon-rpc.com), the address of the messaging contracts on both sides, and the private key for the relayer wallet. This wallet must hold native tokens on the destination chain to pay for transaction gas. For production, use a secure secret management service and fund the wallet appropriately. Tools like Axelar, Wormhole, or LayerZero provide SDKs that abstract some of this logic.

The core logic involves subscribing to events. Using a library like ethers.js, you create a contract instance and listen for the specific event, such as PaymentInstructionCreated. When the event is caught, the relayer must fetch the transaction receipt and generate a proof. For optimistic rollup bridges, this means waiting for a challenge period. For light client or zk-based bridges, it involves fetching a validity proof. The relayer then constructs the payload and calls the execute function on the destination contract.

Error handling and monitoring are essential. Your relayer should log all attempts, successes, and failures. Implement retry logic for transient RPC errors and gas price fluctuations. Use a block confirmation threshold (e.g., 15 blocks) on the source chain before processing to avoid chain reorganizations. For high availability, run multiple relayers in different regions and use a queueing system like RabbitMQ or a database to prevent double-spending of the same message.

To run the service, containerize it with Docker for easy deployment. A basic docker-compose.yml can orchestrate the relayer alongside a PostgreSQL instance for state tracking. Use PM2 or systemd to keep the process running. Finally, set up alerting via PagerDuty or Discord webhooks to notify you of stalled message queues or wallet balance issues, ensuring reliable cross-chain payment execution 24/7.

verification-mechanisms
SETTING UP CROSS-CHAIN MESSAGING

Implementing Verification: Light Clients & Optimistic Models

This guide explains how to implement secure cross-chain messaging for payment instructions using two primary verification models: light clients for cryptographic proofs and optimistic models for cost efficiency.

Cross-chain messaging protocols enable smart contracts on one blockchain to securely send data, like payment instructions, to another. The core challenge is verification: how does the destination chain trust that a message from a foreign chain is valid? Two dominant architectural models solve this: light client bridges and optimistic bridges. Light clients verify the cryptographic proof of the source chain's state directly, while optimistic models assume validity unless challenged within a dispute window. The choice depends on your application's security requirements and cost tolerance.

Light client bridges implement a simplified version of the source chain's consensus on the destination chain. For example, the IBC protocol uses this model. A smart contract on Chain B (the destination) maintains a light client of Chain A (the source). This client tracks the chain's block headers and validator set. When a message is sent, the relayer submits a Merkle proof that the transaction and its event were included in a proven Chain A block. The on-chain light client verifies this proof cryptographically, providing strong, instant finality. This model is highly secure but can be gas-intensive on EVM chains due to the cost of signature and proof verification.

Optimistic bridges, like those used by Optimism's cross-chain messaging, trade instant finality for lower cost. They rely on a set of trusted attesters or a single optimistic oracle. A message is initially assumed to be valid when relayed. However, there is a challenge period (e.g., 30 minutes) during which any watcher can submit fraud proof if the message is invalid. If unchallenged, the message is executed. This model is significantly cheaper for frequent, lower-value payments but introduces a delay and depends on the liveness of at least one honest watcher to flag fraud.

To implement a basic payment instruction flow, you need contracts on both the source and destination chains. On the source chain, a Sender contract emits a standardized event containing the payment details (recipient, amount, unique ID) when a user initiates a transfer. A relayer service (off-chain) watches for this event. For a light client model, the relayer fetches the Merkle proof and submits it to the destination chain's Receiver contract, which verifies it against the on-chain light client state. For an optimistic model, the relayer submits the message data directly, and the Receiver contract queues it for execution after the challenge window passes.

Here is a simplified code snippet for a destination chain receiver contract using an optimistic verification model, assuming a trusted oracle provides the final attestation:

solidity
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.19;

contract OptimisticReceiver {
    address public immutable ORACLE;
    uint256 public constant CHALLENGE_WINDOW = 30 minutes;

    struct CrossChainPayment {
        address recipient;
        uint256 amount;
        uint256 nonce;
        uint256 timestamp;
        bool executed;
    }

    mapping(bytes32 => CrossChainPayment) public pendingPayments;

    event PaymentReceived(address indexed recipient, uint256 amount, uint256 nonce);
    event PaymentExecuted(bytes32 indexed messageHash);

    constructor(address _oracle) {
        ORACLE = _oracle;
    }

    // Called by relayer after source chain event
    function receivePaymentInstruction(
        address _recipient,
        uint256 _amount,
        uint256 _nonce,
        bytes memory _oracleSignature
    ) external {
        bytes32 messageHash = keccak256(abi.encodePacked(_recipient, _amount, _nonce));
        require(pendingPayments[messageHash].timestamp == 0, "Payment already pending");
        require(_verifyOracleSignature(messageHash, _oracleSignature), "Invalid attestation");

        pendingPayments[messageHash] = CrossChainPayment({
            recipient: _recipient,
            amount: _amount,
            nonce: _nonce,
            timestamp: block.timestamp,
            executed: false
        });
        emit PaymentReceived(_recipient, _amount, _nonce);
    }

    // Called after challenge window elapses
    function executePayment(bytes32 _messageHash) external {
        CrossChainPayment storage payment = pendingPayments[_messageHash];
        require(payment.timestamp > 0, "Payment not found");
        require(!payment.executed, "Already executed");
        require(block.timestamp >= payment.timestamp + CHALLENGE_WINDOW, "Challenge window active");

        payment.executed = true;
        // Transfer logic here (simplified)
        // payable(payment.recipient).transfer(payment.amount);
        emit PaymentExecuted(_messageHash);
    }

    function _verifyOracleSignature(bytes32 _hash, bytes memory _signature) internal view returns (bool) {
        (uint8 v, bytes32 r, bytes32 s) = abi.decode(_signature, (uint8, bytes32, bytes32));
        return ecrecover(_hash, v, r, s) == ORACLE;
    }
}

When choosing a model, consider your application's security profile and latency tolerance. For high-value institutional payments where every transaction must be cryptographically guaranteed, a light client bridge is preferable despite higher gas costs. For micro-payments or frequent, lower-value transactions in consumer dApps, an optimistic model offers a practical balance. Always audit the specific bridge implementation's trust assumptions—whether it's the cryptographic security of the light client, the economic security of bonded validators, or the social consensus around oracle signers. Testing with tools like Foundry or Hardhat on local forked networks is essential before deploying cross-chain payment systems to production.

conclusion
IMPLEMENTATION SUMMARY

Conclusion and Next Steps

You have successfully configured a cross-chain messaging system for payment instructions. This guide covered the core setup using a generalized relayer architecture.

Your system now enables a source chain smart contract to send a structured message payload—containing payment details like recipient, amount, and token address—to a destination chain contract. The key components you implemented are the sendMessage function for dispatch, a secure relayer service (like Axelar, Wormhole, or LayerZero) for attestation and transmission, and a receiveMessage function with access control to execute the instruction on the target chain. This decouples payment logic from asset transfer, enabling complex conditional settlements.

For production deployment, several critical next steps are required. First, implement comprehensive error handling and retry logic in your relayer configuration to manage network congestion and temporary failures. Second, add gas estimation and payment mechanisms, as the destination chain execution requires gas; consider using gas abstraction or having the relayer prepay and be reimbursed. Third, integrate monitoring and alerting using services like Tenderly or OpenZeppelin Defender to track message status, failures, and latency across chains.

To extend functionality, explore advanced patterns. You could implement arbitrary message passing to trigger complex DeFi operations (e.g., swapping a received token on a destination DEX). Adding time-locks or multi-sig approvals to the receiveMessage function can enhance security for high-value instructions. For higher throughput, research optimistic verification models used by protocols like Hyperlane, which can reduce latency and cost compared to immediate consensus.

Finally, rigorously audit your contract's cross-chain logic, focusing on the validation of the message sender (the relayer) and the prevention of replay attacks. Test extensively on testnets for all supported chains (e.g., Sepolia, Amoy, BNB Testnet) using the relayer's testnet infrastructure. The cross-chain ecosystem evolves rapidly; stay updated on new security best practices from the Inter-Blockchain Communication (IBC) protocol, Chainlink CCIP, and other major interoperability providers to future-proof your implementation.

How to Set Up Cross-Chain Messaging for Payments | ChainScore Guides