Wormhole Relayer
Introduction
The Wormhole-deployed relayers provide a mechanism for contracts on one blockchain to send messages to contracts on another without requiring off-chain infrastructure. Through the Wormhole relayer module, developers can use an untrusted delivery provider to transport VAAs, saving the need to build and maintain custom relaying solutions. The option to run a custom relayer is available for more complex needs.
This section covers the components and interfaces involved in using the Wormhole relayer module, such as message sending and receiving, delivery guarantees, and considerations for building reliable and efficient cross-chain applications. Additionally, you'll find details on how to handle specific implementation scenarios and track message delivery progress using the Wormhole CLI tool.
Get Started with the Wormhole Relayer
Before getting started, it's important to note that the Wormhole-deployed relayer configuration is currently limited to EVM environments. The complete list of EVM environment blockchains is on the Supported Networks page.
To interact with the Wormhole relayer, you'll need to create contracts on the source and target chains to handle the sending and receiving of messages. No off-chain logic needs to be implemented to take advantage of Wormhole-powered relaying.
Wormhole Relayer Interfaces
There are three relevant interfaces to discuss when utilizing the Wormhole relayer module:
IWormholeRelayer
- the primary interface by which you send and receive messages. It allows you to request the sending of messages and VAAsIWormholeReceiver
- this is the interface you are responsible for implementing. It allows the selected delivery provider to deliver messages/VAAs to your contractIDeliveryProvider
- this interface represents the delivery pricing information for a given relayer network. Each delivery provider implements this on every blockchain they support delivering from
Interact with the Wormhole Relayer
To start interacting with the Wormhole relayer in your contracts, you'll need to import the IWormholeRelayer
interface and set up a reference using the contract address to the Wormhole-deployed relayer on the supported network of your choice.
To easily integrate with the Wormhole relayer interface, you can use the Wormhole Solidity SDK.
To retrieve the contract address of the Wormhole relayer, refer to the Wormhole relayer section on the Contract Addresses reference page.
Your initial set up should resemble the following:
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.26;
import "wormhole-solidity-sdk/interfaces/IWormholeRelayer.sol";
contract Example {
IWormholeRelayer public wormholeRelayer;
constructor(address _wormholeRelayer) {
wormholeRelayer = IWormholeRelayer(_wormholeRelayer);
}
}
The code provided sets up the basic structure for your contract to interact with the Wormhole relayer using the address supplied to the constructor. By leveraging methods from the IWormholeRelayer
interface, you can implement message sending and receiving functionalities. The following sections will detail the specific methods you need to use for these tasks.
Send a Message
To send a message to a contract on another EVM chain, you can call the sendPayloadToEvm
method provided by the IWormholeRelayer
interface.
function sendPayloadToEvm(
// Chain ID in Wormhole format
uint16 targetChain,
// Contract Address on target chain we're sending a message to
address targetAddress,
// The payload, encoded as bytes
bytes memory payload,
// How much value to attach to the delivery transaction
uint256 receiverValue,
// The gas limit to set on the delivery transaction
uint256 gasLimit
) external payable returns (
// Unique, incrementing ID, used to identify a message
uint64 sequence
);
The sendPayloadToEvm
method is marked payable
to receive fee payment for the transaction. The value to attach to the invocation is determined by calling the quoteEVMDeliveryPrice
, which provides an estimate of the cost of gas on the target chain.
function quoteEVMDeliveryPrice(
// Chain ID in Wormhole format
uint16 targetChain,
// How much value to attach to delivery transaction
uint256 receiverValue,
// The gas limit to attach to the delivery transaction
uint256 gasLimit
) external view returns (
// How much value to attach to the send call
uint256 nativePriceQuote,
uint256 targetChainRefundPerGasUnused
);
This method should be called before sending a message, and the value returned for nativePriceQuote
should be attached to the call to send the payload to cover the transaction's cost on the target chain.
In total, sending a message across EVM chains can be as simple as getting a fee quote and sending the message as follows:
// Get a quote for the cost of gas for delivery
(cost, ) = wormholeRelayer.quoteEVMDeliveryPrice(
targetChain,
valueToSend,
GAS_LIMIT
);
// Send the message
wormholeRelayer.sendPayloadToEvm{value: cost}(
targetChain,
targetAddress,
abi.encode(payload),
valueToSend,
GAS_LIMIT
);
Receive a Message
To receive a message using a Wormhole relayer, the target contract must implement the IWormholeReceiver
interface, as shown in the previous section.
function receiveWormholeMessages(
bytes memory payload, // Message passed by source contract
bytes[] memory additionalVaas, // Any additional VAAs that are needed (Note: these are unverified)
bytes32 sourceAddress, // The address of the source contract
uint16 sourceChain, // The Wormhole chain ID
bytes32 deliveryHash // A hash of contents, useful for replay protection
) external payable;
The logic inside the function body may be whatever business logic is required to take action on the specific payload.
Delivery Guarantees
The Wormhole relayer protocol is intended to create a service interface whereby mutually distrustful integrators and delivery providers can work together to provide a seamless dApp experience. You don't trust the delivery providers with your data, and the delivery providers don't trust your smart contract. The primary agreement between integrators and delivery providers is that when a delivery is requested, the provider will attempt to deliver the VAA within the provider's stated delivery timeframe.
This creates a marketplace whereby providers can set different price levels and service guarantees. Delivery providers effectively accept the slippage risk premium of delivering your VAAs in exchange for a set fee rate. Thus, the providers agree to deliver your messages even if they do so at a loss.
Delivery providers should set their prices such that they turn a profit on average but not necessarily on every single transfer. Thus, some providers may choose to set higher rates for tighter guarantees or lower rates for less stringent guarantees.
Delivery Statuses
All deliveries result in one of the following four outcomes before the delivery provider's delivery timeframe. When they occur, these outcomes are emitted as EVM events from the Wormhole relayer contract. The four possible outcomes are:
- (0) Delivery Success
- (1) Receiver Failure
- (2) Forward Request Success
- (3) Forward Request Failure
A receiver failure is a scenario in which the selected provider attempted the delivery but it could not be completely successfully. The three possible causes for a delivery failure are:
- The target contract does not implement the
IWormholeReceiver
interface - The target contract threw an exception or reverted during the execution of
receiveWormholeMessages
- The target contract exceeded the specified
gasLimit
while executingreceiveWormholeMessages
All three of these scenarios can be avoided with correct design by the integrator, and thus, it is up to the integrator to resolve them. Any other scenario that causes a delivery to not be performed should be considered an outage by some component of the system, including potentially the blockchains themselves.
Forward Request Success
and Forward Failure
represent when the delivery succeeded and the user requested a forward during the delivery. If the user has enough funds left over as a refund to complete the forward, the forward will be executed, and the status will be Forward Request Success
. Otherwise, it will be Forward Request Failure
.
Other Considerations
Some implementation details should be considered during development to ensure safety and a pleasant UX. Ensure that your engineering efforts have appropriately considered each of the following areas:
- Receiving a message from a relayer
- Checking for expected emitter
- Calling
parseAndVerify
on any additional VAAs - Replay protection
- Message ordering (no guarantees on order of messages delivered)
- Forwarding and call chaining
- Refunding overpayment of
gasLimit
- Refunding overpayment of value sent
Track the Progress of Messages with the Wormhole CLI
While no off-chain programs are required, a developer may want to track the progress of messages in flight. To track the progress of messages in flight, use the Wormhole CLI tool's status
subcommand. As an example, you can use the following commands to track the status of a transfer by providing the environment, origin network, and transaction hash to the worm status
command:
See the Wormhole CLI tool docs for installation and usage.
Step-by-Step Tutorial
For detailed, step-by-step guidance on creating cross-chain contracts that interact with the Wormhole relayer, refer to the Create Cross-Chain Contracts tutorial.