Implementation Guide
Hyperlane Implementation Guide
A Hyperlane implementation for a new chain architecture is comprised of the following:
Contracts: expose the interface for application developers to send and receive messages with
Agents: operate the protocol by adding security and relaying messages
Applications: applications that use the protocol and demonstrate its capabilities
Before getting started here, it is recommended to review the protocol documentation.
1. Contracts
Below describes the onchain contract spec for the Hyperlane protocol. It uses solidity types for familiarity but everything should be generalizable to other languages.
address
should be interpreted as the local chain's address typepayable
describes a function that allows callers to pass native tokens
Message
The message is the core data structure used by the Hyperlane protocol. It is a packed data structure that contains all the information needed to route a message from one domain to another.
The mailbox is the entrypoint for developers to send and receive messages from.
dispatch
Dispatches a message to the destination domain and recipient.
process
Attempts to deliver message
to its recipient. Verifies message
via the recipient's ISM using the provided metadata
.
count
Returns the number of messages dispatched
root
Returns root of merkle tree which contains all dispatched message IDs as leaves.
Message Recipient
A contract that wants to receive a message must expose the following handler.
They may optionally specify a security module to verify messages before they are handled.
After implementing these three contracts, you can reach your first milestone to test, mocking a message transfer, by calling a Mailbox
's dispatch
function to send a message to a recipient and assert that the recipient received the message. See a Foundry test case here.
Interchain security modules are used to verify messages before they are processed.
moduleType
Returns an enum that represents the type of security model encoded by this ISM.
Relayers infer how to fetch and format metadata from this type.
verify
Defines a security model responsible for verifying interchain messages based on the provided metadata.
Validator Announce
Validators announce their signature storage location so that relayers can fetch and verify their signatures.
announce
Announces a validator signature storage location
getAnnouncedStorageLocations
Returns a list of all announced storage locations
Multisig ISM
Implements a security module that checks if the metadata provided to verify satisfies a quorum of signatures from a set of configured validators.
Metadata
To be used with the MESSAGE_ID_MULTISIG module type implementation in the relayer, the metadata must be formatted as follows:
validatorsAndThreshold
Returns the set of validators responsible for verifying message and the number of signatures required
Can change based on the content of _message
After implementing the MultisigISM, you reach the second milestone to test that your Mailbox only processes after a recipient's ISM returns true. You can test that with a TestISM
that you can statically set to accept or reject any message. See a Hardhat test case here.
The gas paymaster is used to pay for the gas required in message processing on the destination chain. This is not strictly required if relayers are willing to subsidize message processing.
payForGas
Deposits msg.value as a payment for the relaying of a message to its destination chain.
Overpayment will result in a refund of native tokens to the refundAddress. Callers should be aware that this may present reentrancy issues.
Gas Payment
Emitted when a payment is made for a message's gas costs.
2. Agents
Below describes the agent spec for a new chain implementation. The rust implementations hope to support all chains, but the spec is intended to be chain agnostic.
Message Indexing
All agents must index messages from the origin mailbox. In the solidity mailbox, we emit an event for each message dispatched. Other chains may have different ways of surfacing this information, but the agent must be able to get message content reliably and with consistent ordering -- see the message indexer trait.
In addition to indexing messages dispatched from the mailbox, validators produce attestations for the messages they observe to be used on the destination chain for security.
Checkpoint
Validators produce attestations called checkpoints from the mailbox which commit via merkle root to all dispatched message IDs.
Validators use the latest checkpoint method on the mailbox trait to get the latest checkpoint from the mailbox and submit signatures to some highly available storage using the checkpoint syncer trait.
Checkpoint with Message ID
Validators use indexed messages to join the checkpoint with the corresponding message ID emitted from the mailbox.
They also publish these augmented checkpoints on their syncer.
You can test your validator by configuring it with a chain with the above contracts and observe that it creates valid signatures.
In addition to indexing messages dispatched from the mailbox, relayers process messages on the destination chain. This requires building metadata that satisfies the message recipient's ISM verification requirements, and signing transactions that process the message on the destination mailbox.
Metadata Builders
Each module type implies a different metadata format for message verification to succeed. Relayers need each module trait (eg multisig) to be implemented.
Message Processor
The relayer will attempt to process messages on the destination mailbox (see message processor). If
the message recipient ISM returns an unknown module type
module type is known but metadata fails to verify
metadata verifies but dry running (gas estimation) message processing fails
then the message will be kicked to an exponential backoff retry queue. The relayer relies on implementations of the mailbox and ism traits for these checks.
Gas Payment Enforcement
Relayers may also require gas payment for a specific message ID on the origin chain before processing the message on the destination chain. To do this, they must have an IGP deployed with their address set as beneficiary and index gas payment events. See gas payment enforcement trait. We recommend to start with no gas payment enforcement policy and then gradually support more restrictive ones.
Once you implemented the MVP of the relayer, you can create an end-to-end test that \
Spins up local origin and destination chain
Deploys your contracts onto both
Run validators for the origin chain
Run a relayer between both chains
Observe that upon dispatch of a message of the origin chain, the validator observes the message, creates a signature and the relayer appropriately processes your message via the ISM that specifies the validator on the destination chain.
See this end-to-end test on the Rust codebase for inspiration.
3. Applications
Token router application that routes tokens between domains on demand.
transferRemote
Transfers amountOrId
token to recipient
on destination
domain.
Transfer Message
To be interoperable with warp routes on other chains, the body
of a transfer message must be a byte packed TransferMessage
struct.
Last updated