cross-chain messaging
Early bridges only moved tokens. Cross-chain messaging generalizes that to arbitrary data: a contract on chain A can send a payload to a contract on chain B that triggers any logic — vote in a governance contract, open a position, deploy something, update a setting — not just credit a balance. This is often called general message passing (GMP), and it is what turns a set of separate chains into something closer to one composable application surface.
The shape is consistent across providers. A source contract calls a messaging endpoint with (destination chain, destination address, payload). Some verification layer attests that the message was genuinely emitted and final on the source. A relayer delivers it, and a destination endpoint calls the target contract's receive function with the payload, usually exposing the verified origin chain and sender so the receiver can authorize it. The receiving contract must treat the source identity as a security boundary, exactly like checking msg.sender, or anyone could spoof a message.
The deep question is, again, who verifies. Native verification (IBC-style light clients, zk proofs) inherits the chains' security; external verification (LayerZero's configurable DVNs, Axelar's validator set, Wormhole's guardians, Chainlink CCIP's committee) trusts an off-chain group. Messaging also forces hard design choices a token bridge can dodge: ordering and replay protection, what happens if the destination call reverts, gas payment on the far chain, and idempotency so a re-delivered message is not executed twice.
function lzReceive(uint32 srcChain, bytes32 sender, bytes calldata payload) external {
require(msg.sender == endpoint, "only endpoint");
require(srcChain == ETH && sender == govContract, "unauthorized origin");
_execute(payload);
}Receiving a cross-chain message: trust the endpoint, then authorize the origin — both checks are mandatory.