You are on page 1of 132

Wormhole Development Book https://book.wormhole.com/print.

html

Introduction

Welcome to the Wormhole


xDapp Book!
This guide aims to help you in your journey as a
cross-chain developer by explaining the core
concepts of Wormhole and xDapp development.

We'll start by outlining the most important


aspects of Wormhole and the considerations
which must be taken when developing an xDapp.
After that, the second portion of the book helps
you set up a development environment and get
started writing actual code. By the end of this
guide, you should be ready to build and deploy
your first xDapp.

While this document doesn't assume you have


experience with any particular technologies, a
general understanding of blockchain
development will help you get up to speed.

Ready to step into the wormhole?

For additional resources, see the Reference


section.

1 of 132 11/24/22, 17:55


Wormhole Development Book https://book.wormhole.com/print.html

An Introduction to
xDapps
This chapter aims to give you a clear
understanding of what xDapps are and why
they're gaining traction in the blockchain
development community.

To start, let's go over the current state of the


decentralized finance (De-Fi) ecosystem, the
emerging role of xDapps and the advantages
they have over conventional Dapps.

2 of 132 11/24/22, 17:55


Wormhole Development Book https://book.wormhole.com/print.html

Ecosystem Basics
Since the launch of Bitcoin in 2009, the
cryptocurrency and decentralized computing
ecosystem has rapidly evolved and expanded.
The ecosystem now includes hundreds of
blockchains, often also referred to as Layer 1s.

Prior to 2015, blockchain transactions were


limited in their capacities, typically being used to
transfer funds from one user to another. This
changed with the intoduction of Ethereum and
smart contracts. Smart contracts allowed
developers to perform arbitrary on-chain
computation as part of a blockchain transaction,
opening the door for blockchain technology to
become a global computing platform. These
innovations laid the groundwork for the creation
of Decentralized Applications or Dapps.

Now, a rich ecosystem of Dapps exists across an


array of smart-contract-enabled blockchains.
These Dapps provide a number of services
across categories like:

• Decentralized Exchanges (DEXs)


• Decentralized Autonomous Organizations
(DAOs)
• Borrow-Lend Platforms
• Decentralized Games
• NFT Protocols
• Metaverse Platforms
• and more

However, Dapps are not without limitations,


many of which are tied to their underlying
blockchains.

Two notable limitations are that blockchains have


no access to off-chain data and no mechanism to
interact with other blockchains. These limitations
have lead to a fractured ecosystem where each
blockchain is closed off from the others by
default. That means assets native to one chain

3 of 132 11/24/22, 17:55


Wormhole Development Book https://book.wormhole.com/print.html

are not accessible on another, and some services


can't be leveraged on particular chains
altogether.

Blockchain developers are now aiming to solve


these interoperability problems to create a
unified ecosystem. In this new cross-chain
ecosystem, people can move beyond being users
of individual blockchains and take advantage of
Web3 on a broader scale.

In the next section, we'll discuss the history and


challenges of cross-chain interoperability, as well
as introduce the role Wormhole plays in the
future of this space.

4 of 132 11/24/22, 17:55


Wormhole Development Book https://book.wormhole.com/print.html

Blockchain
Interoperability
Because blockchains are siloed by nature,
individual cryptocurrencies being bound to their
own chains has been a longtime limitation of
blockchain technology. The first attempt at
solving this problem was the creation of
cryptocurrency exchanges like Coinbase and
Binance. Today these are refered to as
centralized exchanges (CEXs).

Centralized exchanges play an important role in


cryptocurrency, but they are not a complete
solution for blockchain interoperability for two
primary reasons: (1) they're centralized, which is
counterproductive to creating a decentralized
platform, and (2) they deal only with tokens.

To solve the centralization problems with CEXs,


decentralized exchanges (DEXs) were created. A
DEX operates inside a smart contract runtime
and can be as decentralized as the blockchain it
runs on. Unfortunately, a DEX is only able to
utilize the tokens on its native blockchain. In
order to obtain a token which is not native to
that chain, the DEX must be used in combination
with a bridge.

Bridges are complex and will be discussed at


length in a later section. For now, we can
categorize bridges as applications which 'lock'
assets on one chain in exchange for wrapped
assets on another chain. The wrapped assets
can then be exchanged for the original 'backing'
asset.

There are some other essential things you should


know about bridges before going further:

• Bridges are capable of being decentralized


in theory, but are often quite centralized in
practice.
• Bridges are currently the only way to hold a

5 of 132 11/24/22, 17:55


Wormhole Development Book https://book.wormhole.com/print.html

token on a chain other than its 'native'


chain. If you're holding ETH on a chain
other than Ethereum, it is, by definition, a
wrapped token.
• Bridges are all mutually incompatible with
eachother. Using multiple bridges just
makes 'double wrapped' tokens.
• If tokens have become double wrapped
after traversing multiple bridges or
blockchains, there can be a complex
unwrapping process to get back to the
original token.

This explains how the ecosystem arrived at its


current state -- CEXs are a solution to siloed
blockchains, DEXs are a simple response to CEXs,
and DEXs have created a demand for bridges.
Each solution in this timeline is an ad-hoc patch
to the previous problem, and the current
landscape of fractured liquidity, double wrapped
tokens, isolated userbases and wallet
incompatibilities is the result.

Adding to this complexity are blockchains moving


toward being general-purpose computing
platforms. As such, interoperability will require
data structures that are more complex than
tokens and operations that are more
sophisticated than transfers.

More ad-hoc solutions would only be short-term


fixes for long-term problems, so it's critical to
design new primatives and core infrastructure
that will allow the next generation of
decentralized applications to move beyond these
lingering limitations.

This is why Wormhole exists. Wormhole


proposes a new way of developing applications
which leverages the strengths of each blockchain
while mitigating the problems of the current
ecosystem.

Rethinking the next generation of decentralized


applications means dethroning the token as the

6 of 132 11/24/22, 17:55


Wormhole Development Book https://book.wormhole.com/print.html

fundamental atomic unit of blockchains. We'll


expand on this change in the next section.

7 of 132 11/24/22, 17:55


Wormhole Development Book https://book.wormhole.com/print.html

xData and xAssets


High on the wishlist of blockchain features is the
ability to detach tokens from their native chains.
It is a tremendous limitation that ETH only exists
on Ethereum, MATIC only exists on Polygon and
SOL only exists on Solana. It would be far more
useful if those assets were able to move freely,
independent of their native blockchains.

That thought underpins the idea of an xAsset,


which could be considered a next-generation
wrapped token. In a sense, xAssets exist on a
layer outside of the blockchain ecosystem, and so
are able to transact on a variety of blockchains.
An xAsset is chain- and path- agnostic, so it
retains fungibility regardless of where it travels.
xAssets can also move fluidly around the
blockchain ecosystem without ever becoming
double-wrapped.

Now that we've established the idea of an xAsset,


you might think they're an excellent atomic unit
for solving interoperability challenges. However,
xAssets are just one step short of the real
solution. Let's take a step back: blockchains now
process arbitrary data, and some of that data just
happens to represent assets. The full solution
then, is to create xData.

xData is akin to an xAsset in that it exists in its


own layer independent of any blockchain, which
makes xData accessible by all blockchains. The
difference is that xData represents arbitrary data
rather the token information represented by an
xAsset.

Cross-chain interoperability then becomes a


matter of creating, consuming and managing
xData. Once blockchains have the ability to read
and write data into a shared, global reservior,
application design can take on innovative new
dimensions.

8 of 132 11/24/22, 17:55


Wormhole Development Book https://book.wormhole.com/print.html

Later in this document, we'll delve deeper into


how Wormhole implements this xData layer (also
referred to as the 'Core' layer of Wormhole), but
for now let's talk about how xData can be used to
create xDapps.

9 of 132 11/24/22, 17:55


Wormhole Development Book https://book.wormhole.com/print.html

What is an xDapp?
The term xDapp is short for "Cross-Chain
Decentralized Application". At first glance, this
might give the impression that xDapps are simply
Dapps that do cross-chain things. However, once
you start building decentralized products
designed to operate across a variety of
blockchains and runtimes, it becomes clear that
these applications are architected in a
fundamentally different way than traditional
Dapps.

xDapps have the capacity to perform all the


operations of traditional Dapps, but they are also
able to utilize xData. xData allows xDapp
developers to build from a top-down, message-
passing approach, rather than the bottom-up
world of Dapp development. The Wormhole Core
Layer implements xData, which acts as a shared
repository of data across the entire Wormhole
ecosystem.

Something we'll explore further in the upcoming


xDapp Architecture chapter is the philosophy of
Protocol-First Design. Protocol First Design is an
approach to building decentralized applications
where the first order of business is to lay out
your application into a series of data structures,
APIs and message payloads. Once you've laid out
your application into a high-level protocol, the
protocol acts as an agreement to which all
components must adhere. From there, the smart
contracts underlying the protocol can be
considered an implementation detail.

If you're familiar with web2 development, you


might notice that this philosophy is analogous to
microservice architecture. This is no coincidence,
as similar problems should expect to be solved
by similar solutions, and the Wormhole Core
Layer has a number of parallels to the OSI
Network Model.

10 of 132 11/24/22, 17:55


Wormhole Development Book https://book.wormhole.com/print.html

Thus, a more fitting depiction of xDapps might be


to see them as Distributed Decentralized
Applications with multiple, specialized
components working in unison to deliver a
smooth, unified user experience across a variety
of layer 1 ecosystems.

In the next section, we'll summarize the concrete


advantages which xDapps built on Wormhole
have over traditional Dapps today.

11 of 132 11/24/22, 17:55


Wormhole Development Book https://book.wormhole.com/print.html

Advantages of xDapps
Here are a few xDapp features that are making
an impact across blockchain technologies:

• Expanded User Base - Rather than being


limited to the users of one blockchain, any
user on any blockchain in the ecosystem
can interact with an xDapp.

• Unified Liquidity - Liquidity fragmentation


is a major problem in the current
ecosystem. Unlike traditional tokens,
xAssets can be pooled and moved
anywhere.

• Decentralization - Cross-chain solutions


today usually involve centralized exchanges
or bridges. However, Wormhole has been
designed to be decentralized from day one,
and eventually totally trustless.

• Increased Performance - xDapps are able


to utilize the strengths of each blockchain.
With xDapps, expensive computations can
be offloaded onto high-performance
platforms, final settlement can take place
on a preferred chain, and data can be
stored wherever is cheapest.

• Broader Market Reach - Because xAssets


move freely through the ecosystem, they
can be listed on a variety of exchanges and
custodied on any blockchain.

• Increased Extensibility and


Composability - xDapps can utilize
anything across the ecosystem, including
other xDapps, expanding upon the
composability and openness of smart
contracts.

• Futureproofing - As new environments and


protocols join the decentralized ecosystem,
the connected nature of the Wormhole

12 of 132 11/24/22, 17:55


Wormhole Development Book https://book.wormhole.com/print.html

ecosystem allows existing protocols to


expand and support them.

Now that you have an understanding of what


xDapps are and the advantages they offer, let's
move on to the next chapter where we will delve
into how Wormhole works and how it enables
the creation of these next-generation protocols.

13 of 132 11/24/22, 17:55


Wormhole Development Book https://book.wormhole.com/print.html

Wormhole
In the previous chapter, we established concepts
like xDapps, xData and xAssets. In this chapter,
we'll focus on the inner workings of the
Wormhole ecosystem and how they power these
ideas.

By the end of this chapter, you'll have a clear


understanding of what Wormhole is, what its key
components are and how each component
comes together to create a powerful, new cross-
chain ecosystem.

14 of 132 11/24/22, 17:55


Wormhole Development Book https://book.wormhole.com/print.html

What is Wormhole?
Wormhole V1 was introduced in 2020 by Certus
One, and was initially conceived as a traditional
token bridge between Ethereum and Solana. It
served as the first bridge on Solana and was
responsible for bootstrapping a large amount of
the liquidity in the early Solana and Serum
ecosystems.

However, despite its beginnings as a token


bridge, Wormhole quickly grew beyond Solana
and token transfers.

Wormhole v2 launched in August 2021 as a


decentralized generic interoperability protocol
for multiple blockchain ecosystems with initial
support for Solana, Terra, Ethereum and Binance
Smart Chain.

Over the past year, Wormhole has evolved to


support an ever-growing list of blockchains
across an unrivaled number of smart contract
runtimes.

While Wormhole is a generic interoperability


protocol, it is also an ecosystem and platform for
developers to grow the decentralized computing
space. Wormhole consists of multiple modular
swap-in components that can be leveraged
independently and supports an increasing
number of composable applications built by
numerous teams.

In the next section, we'll go over the major


components of the Wormhole ecosystem and
how they fit together to enable the cross-chain
functionality required to develop xDapps.

15 of 132 11/24/22, 17:55


Wormhole Development Book https://book.wormhole.com/print.html

Architecture Overview
Wormhole is a complex ecosystem with several
noteworthy components. Before we go into each
component in depth, let's talk about the names
of the major pieces and how they fit together.

On-Chain Components

• xDapp Contracts - Contracts developed by


xDapp developers. They receive
transactions from the end user and then
interact with other xDapp contracts and
Wormhole Ecosystem Contracts in order to
provide their service.

• Ecosystem Contracts - Contracts subject to


Wormhole governance which live inside the
Wormhole Ecosystem. Their job is to
provide the feature suite of Wormhole to
xDapp developers.

◦ Core Contracts - Primary ecosystem


contracts. These are the contracts
which the Guardians observe and
which fundamentally allow for cross-
chain communication.

16 of 132 11/24/22, 17:55


Wormhole Development Book https://book.wormhole.com/print.html

◦ xAsset Contracts - Contracts that


allow normal tokens to be converted
to xAssets and enable these xAssets to
be bridged.

◦ Relay Contracts - in development* -


Contracts that allow xDapps to send
messages to a specific blockchain via
the decentralized Generic Relayer
network.

◦ Gas Oracle - in development* - Oracle


for recommended fair gas prices
across the ecosystem.

◦ Worm Router Contracts - in


development* - Contracts that allow
developers to make their Dapp an
xDapp that users on any Wormhole
supported chain can interac with
purely through clientside code.

Off-Chain Components

• Guardian Network - Validators that exist in


their own p2p network. Guardians observe
the Core Contract on each supported chain
and produce VAAs (signed messages) when
those contracts receive an interaction.

• Guardian - One of 19 validators in the


Guardian Network that contributes to the
VAA multisig.

• Spy - Validators on the Guardian Network


which are not part of the Guardian set. A
spy can observe and forward network
traffic, which helps scale up VAA
distribution.

• VAAs - Verifiable Action Approvals (VAAs)


are the key piece of data in the Wormhole
ecosystem, containing the messages
emitted by xDapps along with information
such as what contract emitted the message.

17 of 132 11/24/22, 17:55


Wormhole Development Book https://book.wormhole.com/print.html

The VAAs are signed by the Guardians and


need 13/19 signatures to be considered
authentic.

• Specialized Relayers - Relayers that only


handle VAAs for a specific protocol or
xDapp. They can execute custom logic off-
chain, which can reduce gas costs and
increase cross-chain compatibility.
Currently, xDapp developers are
responsible for developing and hosting
specialized relayers.

• Generic Relayers - in development* - A


decentralized relayer network which
delivers messages that are requested on-
chain via the Wormhole Relay Contract.

• Wormchain - in development* - A purpose-


built cosmos blockchain which aids the
Guardian Network and allows for formal
interaction with the Guardians.

*Features listed as in development are not yet


available.

In the next section, we'll give an overview of how


the Wormhole Guardian network creates VAAs
along with a look at the key design
considerations that underpin the network.

18 of 132 11/24/22, 17:55


Wormhole Development Book https://book.wormhole.com/print.html

Core Contracts
The Core Contracts are the mechanism by which
all Wormhole messages are emitted. All xDapps
either interact directly with the Core Contract or
interact with another contract that does. There is
one Core Contract on each blockchain in the
ecosystem, and this is the contract which the
Guardians are required to observe.

The Wormhole Core Contracts are one of the


most pivotal pieces of the Wormhole ecosystem.
They serve as a great place to start when learning
about how data flows through the ecosystem.

In general, Core Contracts are simple and can be


broken down to a sending and receiving side,
which we'll define next.

Sending

Below is the mechanism by which Wormhole


messages (aka Verified Action Approval, VAA) are
emitted:

publishMessage(
int nonce,
byte[] payload,
int consistencyLevel
) returns int sequenceNumber

Let's break it down a bit:

• payload - The content of the emitted


message and an arbitrary byte array. It may
be capped to a certain maximum length
due to the constraints of individual
blockchains.

• consistencyLevel - The level of finality to


reach before emitting the Wormhole VAA.
This is a defense against reorgs and
rollbacks.

• nonce - An index number for the message

19 of 132 11/24/22, 17:55


Wormhole Development Book https://book.wormhole.com/print.html

that is used to produce Batch VAAs. How


this is generated is elaborated in the
CoreLayer section.

• sequenceNumber - A unique index


number for the message. When combined
with the emitter contract address and
emitter chain ID, the corresponding VAA
can be retrieved from a guardian network
node.

The implementation strategy for publishMessage


differs by chain, but the general strategy consists
of the Core Contract posting the emitterAddress
(the contract which called publishMessage),
sequenceNumber, and consistencyLevel into the
blockchain logs. Once the desired
consistencyLevel has been reached and the
message passes all of the Guardians' optional
checks, the Guardian Network will produce the
requested VAAs.

Currently there are no fees to publish a message


(with the exception of publishing on Solana) but
this is not guaranteed to always be the case in
the future.

Receiving

Below is the mechanism by which VAAs are


received:

parseAndVerifyVAA( byte[] VAA )

When passed a VAA, this function will either


return the payload and associated metadata for
the VAA or throw an exception. An exception
should only ever throw if the VAA fails signature
verification, indicating the VAA is invalid or
inauthentic in some form.

20 of 132 11/24/22, 17:55


Wormhole Development Book https://book.wormhole.com/print.html

Multicasting
Let's take a moment to point out that there is no
destination address or chain in these functions.

VAAs simply attest that "this contract on this


chain said this thing." Therefore, VAAs are
multicast by default and will be verified as
authentic on any chain they are brought to.

This multicast-by-default model is integral to the


design. Having this multicast capacity makes it
easy to synchronize state across the entire
ecosystem, because a single blockchain can
make its data available to every chain in a single
action with low latency. This reduces the
complexity of the n^2 problems encountered by
routing data to a large number of blockchains.

Use cases where the message has an intended


recipient or is only meant to be consumed a
single time must be handled in logic outside the
Core Contract. There are standard practices for
accomplishing these features later on in the code
examples, and some ecosystem contracts
(namely Token Bridge & the Relaying contract)
handle this on behalf of downstream consumers.

Lastly, because the VAA creation is separate from


relaying, there is no additional cost to the
multicast model when a single chain is being
targetted. If the data isn't needed on a certain
blockchain, don't relay it there, and it won't cost
anything.

In our next section, we'll dive into the technical


specfications of the VAA.

21 of 132 11/24/22, 17:55


Wormhole Development Book https://book.wormhole.com/print.html

VAAs (Verified Action


Approvals)
VAAs are the core messaging primitive in
Wormhole. You can think of them as packets of
xData that are emitted any time an xDapp
contract interacts with the Core Contract.

The basic VAA has two components--a Header


and a Body.

Header

byte version (VAA


Version)
u32 guardian_set_index
(Indicates which guardian set is signing)
u8 len_signatures
(Number of signatures stored)
[][66]byte signatures
(Collection of ecdsa signatures)

The Header is used by the Core Contract to


determine the authenticity of the VAA, but can
generally be ignored by other consumers.

Body

22 of 132 11/24/22, 17:55


Wormhole Development Book https://book.wormhole.com/print.html

u32 timestamp
(Timestamp of the block where the source
transaction occurred)
u32 nonce (A
grouping number)
u16 emitter_chain
(Wormhole ChainId of emitter contract)
[32]byte emitter_address
(Emitter contract address, in Wormhole
format)
u64 sequence
(Strictly increasing sequence, tied to
emitter address & chain)
u8 consistency_level
(What finality level was reached before
emitting this message)
[]byte payload (VAA
message content)

The Body is the relevant information for


consumers and is handed back from
parseAndVerifyVAA. Because the emitterAddress
is included as part of the Body, the developer is
able to tell if this VAA originated from a trusted
contract.

VAAs are uniquely indexed by their emitterChain,


emittedAddress and sequence. They can be
obtained by querying a node in the Guardian
Network with this information.

Because baseline VAAs have no destination, they


are effectively multicast. They will be verified as
authentic by any Core Contract on any chain in
the network. If a VAA has a specific destination, it
is entirely the responsibility of relayers to
complete that delivery appropriately.

Batch VAAs
Certain blockchains support version 2 VAAs, also
referred to as Batch VAAs which are designed to
provide an easier paradigm for composability
and better gas efficiency when multiple cross-
chain actions are involved in a single transaction.

Batch VAAs are designed to be automatically

23 of 132 11/24/22, 17:55


Wormhole Development Book https://book.wormhole.com/print.html

generated for all messages that come from a


single transaction.

In an extreme composability scenario or


advanced integration, there may be some
messages in a transaction that may not be
relevant to one another. To control the create of
additional batches, some messages can be
created with the same nonce to additionally
group them.

It is of note that Single VAAs will always be


emitted for each message generated, regardless
of it they are contained in a Batch VAA or not.

Go here for a more detailed description of how


Batch VAAs are generated.

Note: Batch VAAs are not currently live on mainnet,


but will have initial support on all EVM chains when
they launch.

How to leverage Batch VAAs

Imagine a transaction generates three


messages (A, B, C) that a consuming
contract needs to know about.

If each message is independent of each


other, the consuming contract can handle
and validate each of these VAAs individually
like [A], [B], [C].

If all of the messages are related to each


other, the consuming contract can handle
and validate the Batch VAA of the entire
transaction that is automatically generated
like [A, B, C].

If only two of the messages are related to


each other, say A and C, the same nonce
can be used for those two messages to
generate an additional Batch VAA and the
consuming contract can then handle and
validate two sets of VAAs like [A, C] and [B].

24 of 132 11/24/22, 17:55


Wormhole Development Book https://book.wormhole.com/print.html

In the next section, we'll give an overview of how


the Wormhole Guardian network creates VAAs
along with a look at the key design
considerations that underpin the network.

25 of 132 11/24/22, 17:55


Wormhole Development Book https://book.wormhole.com/print.html

Guardian Network
The Guardian Network is designed to serve as
Wormhole's oracle component, and the entire
Wormhole ecosystem is founded on its technical
underpinnings. It is the most critical element of
the Wormhole ecosystem, and represents the
single most important component to learn about
if you want a deep understanding of Wormhole.

To understand not just how the Guardian


Network works, but why it works the way it does,
let's first take a step back and go over the key
design considerations. To become the best-in-
class interoperability platform, there were five
critical features Wormhole needed to have:

1. Decentralization - Control of the network


needs to be distributed amongst many
parties.
2. Modularity - Disparate parts of the
ecosystem such as the oracle, relayer,
applications, etc, should be kept as
separate and modular as possible so they
can be designed, modified and upgraded
independently.
3. Chain Agnosticism - Wormhole should be
able to support not only EVM, but also
chains like Solana, Algorand, Cosmos, and
even platforms that haven't been created
yet. It also should not have any one chain as
a single point of failure.
4. Scalablity - Wormhole should be able to
secure a large amount of value immediately
and be able to handle the large transaction
volume.
5. Upgradeability - As the decentralized
computing ecosystem evolves, Wormhole
will need to be able to change the
implementation of its existing modules
without breaking integrators.

Next, let's go into how Wormhole achieves these


one at a time.

26 of 132 11/24/22, 17:55


Wormhole Development Book https://book.wormhole.com/print.html

Decentralization
Decentralization is the biggest concern. Previous
interoperability solutions have largely been
entirely centralized, and even newer solutions
utilizing things like adversarial relayers still tend
to have single points of failure or collusion
thresholds as low as 1 or 2.

When designing a decentralized oracle network,


the first option to consider is likely a Proof-of-
Stake (PoS) system-but this turns out to be a
suboptimal solution. PoS is designed for
blockchain consensus in smart-contract enabled
environments, so it's less suitable when the
network is verifying the output of many
blockchains and not supporting its own smart
contracts. While it looks appealing from a
decentralization perspective, the network
security remains unclear, and it can make some
other outlined goals more difficult to achieve.
Let's explore other options.

The next option would be to rush straight for the


finish line and use zero-knowledge proofs to
secure the network. This would be a good
solution from a decentralization perspective, as
it's literally trustless. However, zero-knowledge
proofs are still a nascent technology and it's not
really feasible to verify them on-chain, especially
on chains with limited computational
environments. That means a form of multisig will
be needed to secure the network.

If we step back and look at the current De-Fi


landscape, most of the top blockchains are
secured by the same handful of validator
companies. Currently, there are a limited number
of companies in the world with the skills and
capital to run top-notch validator companies.

If a protocol could unite a large number of those


validator companies into a purpose-built
consensus mechanism that's optimized for chain
interoperability, that design would likely be more

27 of 132 11/24/22, 17:55


Wormhole Development Book https://book.wormhole.com/print.html

performant and secure than a network


bootstrapped by a tokenomics model. Assuming
the validators would be on board, how many
could Wormhole realistically utilize?

If Wormhole were to use threshold signatures,


the answer would basically be 'as many as are
willing to participate.' However, threshold
signatures have spotty support across the
blockchain world, meaning it would be difficult
and expensive to verify the signatures, ultimately
limiting scalability and chain agnosticism. Thus, a
t-schnorr multisig presents itself as the best
option: cheap and well supported, despite the
fact that its verification costs increases linearly
with the number of signatures included.

All these things considered, 19 seems to be the


maximum number and a good tradeoff. If 2/3 of
the signatures are needed for consensus, then
13 signatures need to be verified on-chain, which
remains reasonable from a gas-cost perspective.

Rather than securing the network with


tokenomics, it is better to initially secure the
network by involving robust companies which
are heavily invested in the success of De-Fi as a
whole. The 19 Guardians are not anonymous or
small--they are many of the largest and most
widely-known validator companies in
cryptocurrency. The current list of Guardians can
be viewed here

That's how we end up with the network of 19


Guardians, each with an equal stake and joined
in a purpose-built Proof of Authority consensus
mechanism. As threshold signatures become
better supported, the Guardian set can expand,
and once ZKPs are ubiquitous, the Guardian
Network will become fully trustless.

With our perspective on Decentralization laid out,


the remaining elements fall into place.

28 of 132 11/24/22, 17:55


Wormhole Development Book https://book.wormhole.com/print.html

Modularity
The Guardian Network is robust and trustworthy
by itself, so there's no need for components like
the relayer to contribute to the security model.
That makes Wormhole able to have simple
components that are very good at the one thing
they do. That way, Guardians only need to verify
on-chain activity and produce VAAs while
Relayers only need to interact with blockchains
and deliver messages.

The signing scheme of the VAAs can be changed


without affecting downstream users, and
multiple relay mechanisms can exist
independently. xAssets can be implemented
purely at the application layer and xDapps can
utilize whatever components suit them.

Chain Agnosticism
Today, Wormhole supports a wider range of
ecosystems than any other interoperability
protocol because it uses simple tech (t-schnorr
signatures), an adaptable, heterogenous relayer
model, and a robust validator network.

Wormhole can expand to new ecosystems as


quickly as a Core Contract can be developed for
the smart contract runtime. Relayers don't need
to be factored into the security model--they just
need to be able to upload messages to the
blockchain. The Guardians are able to observe
every transaction on every chain, without taking
shortcuts.

Scalability
Wormhole scales well, as demonstrated by its
ability to handle huge TVL and transaction

29 of 132 11/24/22, 17:55


Wormhole Development Book https://book.wormhole.com/print.html

volume--even during tumultuous events.

The requirements for running a Guardian are


relatively heavy, as they need to run a full node
for every single blockchain in the ecosystem. This
is another reason why a limited number of
robust validator companies are beneficial for this
design.

However, once all the full nodes are running, the


actual computation and network overheads of
the Guardian Network become lightweight. The
performance of the blockchains themselves
tends to be the bottleneck in Wormhole, rather
than anything happening inside the Guardian
Network.

Upgradability
Over time, the Guardian Set can be expanded
beyond 19 with the use of threshold signatures.
A variety of relaying models will emerge, each
with their own strengths and weaknesses. ZKPs
can be used on chains where they are well
supported. The xDapp ecosystem will grow, and
xDapps will become increasingly intermingled
with eachother. There are very few APIs in
Wormhole, and most items are implementation
details from the perspective of an integrator. This
creates a clear pathway towards a fully
trustlessness interoperability layer which spans
the entirety of decentralized computing.

In the next section, we will talk about the role


and responsbilities of relayers in the Wormhole
ecosystem.

30 of 132 11/24/22, 17:55


Wormhole Development Book https://book.wormhole.com/print.html

Relayers
All simple cross-chain processes on Wormhole
essentially boil down to a three-step process:

1. Perform an action on chain A.


2. Retrieve the resulting VAA from the
Guardian Network.
3. Perform an action on chain B using the VAA.

Relayers play a key role in the final step of the


process -- they can be thought of as the 'write'
portion of interoperability, complementing the
'read' portion that Guardians provide.

The definition of a Relayer in the context of


Wormhole is: Any process which delivers VAAs to
a destination.

Unlike other interoperability protocols,


Wormhole does not have a required relaying
methodology.

In most designs there is a dedicated relaying


mechanism which operates inside the protocol's
trust boundaries. This means that the relayer
either has an adversarial relationship to the
oracle, or the relayer has trust assumptions and
contributes to the protocol's security model.
Relayers are usually a trusted party, are often
also privileged, and developers are typically
forced to use the relayer model built into the
protocol.

In Wormhole, relayers are neither trusted nor


privileged. This means relayers cannot
jeopardize security, only liveness. Because
Wormhole is designed to have a firm trust
boundary at the level of the VAA, relayers have
exactly the same capabilities as any regular,
untrusted blockchain user.

From this perspective, relayers are just delivery


trucks that deliver VAAs to their destination, and
have no capacity to tamper with the delivery

31 of 132 11/24/22, 17:55


Wormhole Development Book https://book.wormhole.com/print.html

outcome. VAAs either get delivered or don't,


which makes relayers analagous to the off-chain
'crank turners' of traditional Dapps.

As a result, Wormhole is able to facilitate a


variety of heterogeneous relaying mechanisms,
and the developer is able to choose whatever
best suit their needs.

Next, we'll go over a few of the most common


relaying strategies.

Client-side Relaying
Client-side relaying relies on the user-facing
frontend, like a webpage or a wallet, to perform
all three steps of the cross-chain process.

There are two major benefits of this approach:

• Low cost. Users pay exactly the transaction


fee for the second transaction.
• No backend relaying infrastructure.

However, client-side relaying also has two


notable drawbacks:

• Users must sign all transactions required


with their own wallet.
• Users must have funds to pay the
transaction fees on every chain involved.

Overall, client-side relaying is a simple solution,


but can make the user experience cumbersome.
It's generally not recommended if your goal is a
highly-polished user experience but can be
useful to getting an MVP up and running.

Specialized Relayers
Specialized relayers solve the UX problems of
client-side relayers by adding a backend

32 of 132 11/24/22, 17:55


Wormhole Development Book https://book.wormhole.com/print.html

component which can handle steps 2 and 3 on


behalf of the user.

In this model, relayers either listen directly to the


Guardian Network via a spy (called Spy
Relaying), or will simply provide a REST endpoint
to accept a VAA which should be relayed (called
REST Relaying). Once a relayer has the VAA, it
simply performs any necessary off-chain
calculations and submits the VAA to the required
destination.

An important consideration when developing a


specialized relayer is that the relayer is still
considered untrusted. VAAs are public and can
be submitted by anyone, so developers should
not rely on off-chain relayers to perform any
computation which is considered "trusted."
However, things that do not impact security like
deterministic data transforms, waiting for gas
prices to drop, or various forms of 'batching' can
be very useful cost-reduction strategies.

Specialized Relayers have the following


advantages:

- They simplify user experience


- They allow off-chain calculations to be
performed in the relayer, reducing gas
costs
- They are generally easy to develop

However, they also have a couple notable


downsides

- They add a backend relaying component


which is responsible for liveness
- They can complicate fee-modeling, as
relayers are responsible for paying target
chain fees.

Due to specialized relayers being such a common


solution, an extensible relayer (called the plugin
relayer) has been provided in the main
Wormhole repository. The plugin relayer stands
up most of the requisite infrastructure for
relaying, so that you only need to implement the

33 of 132 11/24/22, 17:55


Wormhole Development Book https://book.wormhole.com/print.html

logic which is specific to your application.

If you plan to develop a specialized relayer,


consider starting from the plugin relayer found
here.

Because relayers are responsible for liveness,


they become another dependency component
(similar to the frontend, blockchain nodes,
blockchains, third party APIs, etc.) for the xDapp.
If the relayers are all down, your application has
an outage.

To mitigate this, multiple relayers can be run in


order to provide redundancy either by (1) the
xDapp team or (2) a decentralized network based
off economic incentives. However, creating a
robust model for decentralized relaying is generally
application-specific and complex.

Overall, Specialized Relayers add a backend


component that is responsible for liveness, but
can simplify the user experience. It's generally
recommend if your goal is a highly-polished user
experience, and you want to have better control
over message delivery.

Generic Relayers
Note: this feature is not yet available in mainnet

Because relaying is such an integral component


to xDapps, Wormhole has built a protocol which
allows developers to utilize a decentralized
network of untrusted relayers to deliver their
messages, removing the specialized relayer as an
infrastructure responsibility.

In order to utilize the generic relayer network,


developers must request delivery from the
Wormhole Relay Ecosystem Contract and must
also implement a "receiveRelay" function in their
contracts, which will be called by the relayer.
Once a delivery has been requested, the VAA is
guaranteed to be delivered within a certain

34 of 132 11/24/22, 17:55


Wormhole Development Book https://book.wormhole.com/print.html

timeframe. The specifics of this vary by


blockchain and smart contract runtime.

Generic relayers have the following benefits:

- They feature simplified UX


- There are no relayer infrastructure
requirements for the developer

And potential downsides:

- They require all calculations to be done


on-chain
- They sometimes have less gas efficiency
- They may not be supported on all chains

Overall, Generic Relayers simplify both the


developer and user experience. They're a great
choice if they cover all your usecases.

In the next section, we'll discuss the xAsset


module, which allows xAssets to be created and
moved freely around the ecosystem.

35 of 132 11/24/22, 17:55


Wormhole Development Book https://book.wormhole.com/print.html

xAsset Layer
There is a set of ecosystem contracts that
provision Wormhole's xAsset layer which allow
tokens to be bridged around the Wormhole
Ecosystem in a path-independent fashion, and
are easily composable with other functions in the
Wormhole ecosystem.

This section provides a high-level overview of


how to interact with two smart contract modules
that implement xAssets: (1) Token Bridge module
and (2) NFT Bridge Module.

If you're looking to interact with the Token Bridge


directly from a typescript client or backend, you
should start with the Wormhole Typescript SDK.

Creating xAssets
xAssets always have an origin chain. This is
where the token is initially minted via the
standard of that chain (ERC-20, SPL, etc for
tokens; ERC-721, Metaplex, etc for NFTs).

xAssets are all fungible with each other. This


means the Wormhole-wrapped asset can be
exchanged for the original asset or a wrapped
asset from other chains.

Tokens

To convert tokens into an xAsset, an attestation


must first be created. To create an attestation,
simply call the attest function on the token
bridge contract of the origin chain.

function attestToken(
address tokenAddress,
uint32 nonce)
returns (uint64 sequence)

The Guardian Network will then produce an

36 of 132 11/24/22, 17:55


Wormhole Development Book https://book.wormhole.com/print.html

attestation VAA, which can be retrieved using


the sequence number returned by the
attestToken function.

The attestation VAA must then be submitted to


the createWrapped function of every other
chain, referred to as foreign chains for this
token.

function createWrapped(
bytes memory encodedVm)
returns (address token)

Calling this function will deploy a new contract


for the token on the foreign chain, creating a
Wormhole-Wrapped Token. The wrapped token
will use the same symbol as the origin asset, and
will append (Wormhole) to the end of the name.

NFTs

NFTs do not need to be attested before they can


be created into a xAsset.

Transferring xAssets
Initiating xAsset transfers is a straightforward
affair. Once the transfer is initiated, the
Guardians will produce a transfer VAA when
finality has been reached on the source chain.
The VAA must then be relayed to the target
chain.

All tokens managed by the Token Bridge are


backed by the origin asset, allowing assets to be
transferred in a path-independent fashion.
Regardless of what chain the assets are passed
to, a 'double-wrapped' asset will never be
created for a single backing asset. Additionally,
there are no liquidity limitations.

Tokens

37 of 132 11/24/22, 17:55


Wormhole Development Book https://book.wormhole.com/print.html

function transferTokens(
address token,
uint256 amount,
uint16 recipientChain,
bytes32 recipient,
uint256 arbiterFee,
uint32 nonce) returns (uint64
sequence)

NFTs

function transferNFT(
address token,
uint256 tokenID,
uint16 recipientChain,
bytes32 recipient,
uint32 nonce) returns (uint64
sequence)
)

Contract-Controlled Transfers
Basic transfers are intended to transfer xAssets
from one wallet to another, whereas Contract
Controlled Transfers (CCTs) are meant to transfer
xAssets from one smart contract to another. If
you're writing an xDapp, CCTs will likely be a
large component.

CCTs allow xDapp contracts to easily perform


simple xAsset transfers, but have two additional
features:

• An arbitrary byte array can be appended to


the transfer and can be used to easily pass
additional information to the recipient
contract.
• The CCT VAA redeem can only be
performed by the recipient contract, as
opposed to basic transfers, which can be
performed by any caller. This ensures that
any additional operations which the
contract wants to perform as part of the
redeem transaction must be executed.

38 of 132 11/24/22, 17:55


Wormhole Development Book https://book.wormhole.com/print.html

In the next section, we'll discuss Wormchain and


some upcoming features it will enable.

39 of 132 11/24/22, 17:55


Wormhole Development Book https://book.wormhole.com/print.html

Wormchain
Wormchain is a purpose-built cosmos blockchain
for the Wormhole ecosystem. It has two primary
functions:

1. Provide a public and auditable mechanism


for users to interact with the Guardian
Network.
2. Create a robust platform for on-chain
infrastructure which would be infeasible to
build elsewhere.

Wormchain is built to provide things like:

- Redundant security checks


- Governance
- Interactions with 'legacy' chains like
Bitcoin

Wormchain is less relevant to xDapp developers


than some other parts of the ecosystem, but it
will become an increasingly important
component as Wormhole matures and features
are added.

In the next section, we'll get into the key concepts


that underpin xDapp design.

40 of 132 11/24/22, 17:55


Wormhole Development Book https://book.wormhole.com/print.html

xDapp Design
Now that we've established the major concepts
and components underlying xDapps, let's dive
into the process of designing one. This chapter
will guide you through the considerations you
should make before developing an xDapp,
including topics like network topology, protocol
design and more.

By the end of this chapter, you will have all the


tools you need to lay out a design for your xDapp
and start building.

41 of 132 11/24/22, 17:55


Wormhole Development Book https://book.wormhole.com/print.html

Key Considerations
Before we get started, we should outline the key
considerations that will shape your xDapp.
Below, we'll show how each of the decisions you
make about these key considerations can impact
the structure of your application as a whole.

Why?

The reason you're building an xDapp is the


foremost consideration. Think about the
advantages of cross-chain development -- which
of these are most important to you? Are you
building a brand new application and you want
the widest reach? Are you trying to increase the
performance of an existing Dapp? Are you
interested in composing on top of protocols that
only exist in certain ecosystems? Determining
your key priorities will help you make better
technical decisions and tradeoffs when designing
your xDapp.

Target Ecosystems & Languages

Which blockchains do you intend to support?


Because different blockchains utilize different
virtual machines, supporting more blockchains
often requires writing smart contracts in more
than one language.

Data Flows

Think about where your data originates and


where it needs to go. Does all your data come
from user-initiated transactions? Do you have
governance messages that need to be emitted
from a central governance contract? Do you have
automated actions which need to happen
periodically to synchronize your data?

42 of 132 11/24/22, 17:55


Wormhole Development Book https://book.wormhole.com/print.html

Liquidity & Tokens

Not all xDapps deal with tokens, but many do. If


your app is centered around tokens, you'll have
to decide which tokens will be utilized, where
liquidity is aggregated (or fractured), and how
this liquidity can be best utilized across your
application.

43 of 132 11/24/22, 17:55


Wormhole Development Book https://book.wormhole.com/print.html

Ecosystems
At present, there are 6 ecosystems supported by
Wormhole, though the number of supported
ecosystems is always growing.

EVM

EVM is the most popular ecosystem, and most


xDapps will have some support for this platform.
These contracts are written in Solidity -- a 'jack of
all trades' style of computation environment. A
common strategy for xDapps is to develop one
single contract in Solidity, and then deploy that
contract to all the supported EVM blockchains.

Example chains:

- Ethereum
- Polygon
- BNB Chain
- Avalanche (C Chain)
- Aurora (Near Network)
- Karura (Polkadot Network)
- Acala (Polkadot Network)
- Celo
- Fantom
- Oasis (Emerald)

Solana

Solana is characterized by its high transaction


throughput, increased computation power and
cheap data storage when compared to EVM
environments. These contracts are written in
Rust.

Cosmos

Cosmos is a network of blockchains that share a


common ecosystem. Cosmos is a general
purpose environment, but excels in certain areas

44 of 132 11/24/22, 17:55


Wormhole Development Book https://book.wormhole.com/print.html

like application-specific blockchains and the use


of Cosmos-wide standards via its sdk 'modules.'
It uses CosmWasm for its smart contract
runtime, which is based in Rust.

Algorand

Algorand is a leading blockchain on the state


proof front and repesents the bleeding edge of
trustlessness. These contracts are written in
Python.

Aptos

Aptos is characterized by its optimisitic approach


to computation parallelization to bring increased
performance. These contracts are written in
Move.

NEAR

NEAR is characterized by its sharding technology


that may allow for greater transaction capacity
and security. These contracts are written in Rust.

Read-Only Chains

Some chains in the Wormhole ecosystem are


'Read-Only.' These chains are able to verify
messages emitted from other chains in the
network, but are not able to emit messages
themselves. For information about these chains,
check the contracts page.

45 of 132 11/24/22, 17:55


Wormhole Development Book https://book.wormhole.com/print.html

Protocol Design
They key feature of Wormhole is bringing
message passing to the world of blockchain, so
it's worthwhile to take some inspiration from
other areas of software development that are
based on similar principles.

Much of the traditional web stack is based on


distributed systems that rely on message passing
to create interfaces and boundaries for disparate
systems to work together. We can think of
xDapps as web3 distributed systems founded on
similar paradigms.

Protocol First Design


Protocol first design is a design philosophy where
you initially lay out your data types, message
formats and supported operations into a well-
defined protocol. This creates a solid protocol
layer which can serve as the foundation for your
application. This way, the code instantiating that
protocol can be treated as an implementation
detail when reasoning about the protocol itself.

At this stage in the design, you should also


consider the incentive structures surrounding
your protocol. What is the incentive for each
party to engage? Are there economic attack
vectors in your application which might
jeopardize its security? Do certain market
conditions result in perverse outcomes?

Depending on your goals, this stage of the


process can be as simple as stating "people will
want my NFT" or as difficult as designing an
entire ecosystem with multiple competing
interested parties.

Once you have a clear idea of your core product,


incentives and users, you can begin to lay out

46 of 132 11/24/22, 17:55


Wormhole Development Book https://book.wormhole.com/print.html

your data model. From there, you can define


your message types and operations.

Common Strategies and


Conventions

Address Space

Because there are many different formats for


addresses across the different supported
blockchains, a compatibility format is necessary.
Wormhole uses its own address format
(generally referred to as Wormhole format) in
order to solve this issue. These addresses
correspond 1 to 1 with native addresses on each
chain.

A Wormhole address is a tuple containing the 2


byte Wormhole chain ID and a 32 byte shim
address, totalling 34 bytes.

Because EVM addresses are only 20 bytes in


length, to convert this to a Wormhole address,
the address is left-padded with zeros until it's
length 32. To transmit as this as a single item, the
Wormhole chain ID is usually appended to the
front, resulting in a 34 byte address.

When dealing with addresses inside your


messages, it's recommended to always convert
to Wormhole format and transmit in that format.
You will regularly encounter addresses in the
Wormhole format when interacting with other
parts of the ecosystem, and adopting the format
in your protocol will enhance your forward
compatibility as you add more chains.

Trusted Contract Network

Typically, the first check performed when

47 of 132 11/24/22, 17:55


Wormhole Development Book https://book.wormhole.com/print.html

receiving a message is to validate that it


originates from a trusted source. If your protocol
has smart contracts deployed to multipe chains,
it will be important for your contracts to know
which other contracts are 'in network' for your
protocol.

Generally, this list of trusted contracts is stored


in the state of each contract individually.
Updating the trusted contracts is tied into the
governance mechanism of the protocol.

48 of 132 11/24/22, 17:55


Wormhole Development Book https://book.wormhole.com/print.html

Topology
Topology describes how data flows through your
application and defines the responsibilities of
each component. In terms of overall xDapp
topology, the primary decision is determining
where your smart contracts will live and the
responsibilities each contract will hold.

Ultra-light Clients

Ultra-light Clients are often the best option when


designing an MVP for your xDapp. The defining
feature of an Ultra-light Client is that you are able
to support users from every chain in the
Wormhole ecosystem while only having smart
contracts on a single chain (!!!).

xDapps with this structure work by having a hub


chain that all application contract logic is
deployed to and entrypoints which receive and
send Wormhole messages to remote chains. The
network of Wormhole contracts deployed on
other chains across the ecosystem provide the
rest of the heavy lifting to send messages across
chains.

You can think of the data flow across a xDapp


with a Ultra-light Client as follows:

49 of 132 11/24/22, 17:55


Wormhole Development Book https://book.wormhole.com/print.html

1. The end user's wallet interacts with


Wormhole contracts on remote chain.
2. The Wormhole contracts on remote chain
generate a VAA which is received by your
xDapp contract on the hub chain.
3. Your xDapp contract on the hub chain
performs all necessary operations.
4. Your xDapp contract interacts with
Wormhole contracts on the hub chain.
5. The Wormhole contracts on hub chain
generate a VAA which is sent back to the
end user's wallet on the remote chain.

Advantages:

• Very little added smart contract risk.


• Simple to develop.
• Easiest way to get heterogenous ecosystem
support.

Disadvantages:

• Latency: Transactions incur latencies


associated with bridging into and out of
both the remote and hub chain.
• Transaction Fees: There are always a grand
total of three transactions. Two on the
remote chain, and one on the hub chain.
• Use cases: There is no place to perform
trusted computation on the remote chain,
so some use cases are more difficult to
implement (or potentially not possible).

Hub-and-Spoke

50 of 132 11/24/22, 17:55


Wormhole Development Book https://book.wormhole.com/print.html

Hub and Spoke models can somewhat be


thought of as the natural evolution of the ultra-
light client. There is still a hub contract which
handles all transactions, but there is now also a
contract deployed to all the remote chains that is
capable of performing some trusted
computation.

You can think of the data flow across a Hub-and-


Spoke system as follows:

1. The end user's wallet interacts with your


(lightweight) remote contracts.
2. The remote contracts perform any
necessary trusted computation.
3. The remote contracts use Wormhole to
generate a VAA, which is consumed by the
hub contract.
4. The hub contract performs all necessary
operations.
5. The hub contract uses Wormhole to send a
message back to the original remote
contract.
6. The remote contract takes whatever action
is needed to finish the process.

Advantages:

51 of 132 11/24/22, 17:55


Wormhole Development Book https://book.wormhole.com/print.html

• Remote contracts are lightweight and don't


carry large amounts of risk.
• Can perform trusted checks on the remote
chain. (Such as validating wallet balance, or
any other piece of blockchain state)

Disadvantages:

• Latency (same as ultra-light clients)


• Transaction Fees
• Managing multiple contracts

Mesh

Mesh topologies can somewhat be thought of as


the next evolution of the Hub and Spoke model.
There are now contracts capable of handling all
transactions for an application are deployed on
all supported chains. Each contract can be
thought of as a peer of other contracts in the
trusted network and can act autonomously.

This is historically the most popular methodology


for going cross-chain. It's very attractive in
ecosystems like EVM or Cosmos, where a single
smart contract can simply be deployed across
many different blockchains.

Advantages:

52 of 132 11/24/22, 17:55


Wormhole Development Book https://book.wormhole.com/print.html

• Latency: Users can often perform their


operation without waiting for other chains.
• Transaction Fees: Does not stack the
transaction fees of multiple chains.

Disadvantages:

• Complexity: there are now quite a few


contracts to manage, especially if they are
implemented multiple times across
different VMs.
• Data desync: because each blockchain acts
independently, each chain will have
independent state. This can open up
unwanted arbitrage opportunities and
other discrepancies.
• Race conditions: In cases where an event is
supposed to propagate through the entire
system at a fixed time (for example, when
closing a governance vote), it can be difficult
to synchronize all the blockchains.

Distributed

Distributed topologies can somewhat be thought


of as the next evolution of the Mesh model.
Instead of contracts that are capable of handling
all transactions for an application on all
supported chain, applications are broken up into

53 of 132 11/24/22, 17:55


Wormhole Development Book https://book.wormhole.com/print.html

separate responsibilities (i.e. data storage, user


interaction, asset custody, governance) and
deployed to different blockchains.

Advantages:

• Power: utilize each blockchain for whatever


is most optimal.

Disadvantages:

• Complexity: requires multiple specialized


smart contracts, and potentially additional
on-chain processes.

Mix & Match


Different use cases have different optimal
topologies, and it's possible to use different
topologies for different workflows in your
application. This means you should not feel
'locked in' to a single topology, and should
instead consider designing each workflow
independently. For example, governance
workflows are generally best implemented using
a Hub and Spoke topology, even if the rest of the
application uses a Mesh architecture. As such,
your contracts will likely evolve over time as your
xDapp evolves and adds additional workflows.

You can also progress through different


topologies. A common strategy is to start off with
an ultra-light client, move to a hub and spoke
configuration, and then add optimizations and
specialties to contracts as the need arises.

54 of 132 11/24/22, 17:55


Wormhole Development Book https://book.wormhole.com/print.html

Relayers
In Chapter 2, we discussed the general concepts
associated with relayers in the Wormhole
ecosystem. In this section, we'll elaborate on the
considerations that should be accounted for
when using relayers in your xDapp.

Fundamentals
It's important to remember that relayers are
untrusted. This means you don't have to trust
them--but it also means you can't trust them.
This is true of both generic and specialized
relayers.

Let's dive into a little more detail about why


relayers are untrusted and what this means for
you.

A few key properties of VAAs:

• They are publicly emitted from the


Guardian Network.
• They need to be signed by the Guardian
Network to be considered authentic.
• They can be verified as authentic by anyone
and any Wormhole Core Contract.

Relayers are untrusted as an inherent


consequence of these properties. Anyone can
pick up a VAA and deliver it anywhere, but no
one can alter the content of the VAA without
invalidating the signatures.

So, when writing your contracts, it's incredibly


important to only trust information which is
either inside your contract or inside a VAA. If you
trust information provided by a relayer, you are
opening yourself up to untrusted input attacks.

The easiest and most secure way to interact with


relayers then is to only accept the VAA as input. If

55 of 132 11/24/22, 17:55


Wormhole Development Book https://book.wormhole.com/print.html

the relayer can't provide any additional args,


then there's no way for them to provide
untrusted input.

More advanced strategies involve having the


relayer perform untrusted off-chain computation
which is passed into the destination contract.
These strategies can optimize gas costs, but can
also create attack vectors if not used correctly.

With this in mind, relayer design becomes a


matter of structuring the messages in your
protocol such that there is a single, deterministic
way that they can be processed. In a well
designed protocol, relayers have a 'correct'
implementation.

Relayers are conceptually quite similar to "crank


turner" processes used elsewhere in blockchain,
in that there is only a single action which can be
taken (pulling the crank), and their sole
responsibility is to initiate this action and pay for
the costs.

Generic Relayers
Generic relayers are a decentralized relayer
network which can deliver arbitrary VAAs as long
as the recipient contract conforms with the
generic relayer API.

Advantages:

• Generic relayers are done purely on-chain,


so there's no need to develop, host or
maintain relayers.

Disadvantages:

• There's less room for optimization via


features like conditional delivery, batching,
off-chain calculations, etc.

56 of 132 11/24/22, 17:55


Wormhole Development Book https://book.wormhole.com/print.html

Specialized Relayers
Specialized Relayers are relayers that are
purpose-built to relay messages for a certain
application. In the future, there may be ways to
customize generic relayers such that they will
gain the advantages of today's specialized
relayers.

Advantages:

• Specialized relayers can perform off-chain


untrusted computation.
• They are highly customizeable and can
perform batching, conditional delivery,
multi-chain deliveries, etc.
• Can home-roll an incentive structure.

Disadvantages

• Requires development work and relayer


hosting.

Relayer Incentives

Relayers have to cover the costs of executing the


downstream transactions resulting from the
original 'source' transaction. Unless the relayers
are running at a loss, there must be a
mechanism for reimbursing the relayer in
exchange for message delivery.

There are many strategies for reimbursement,


and the 'best' strategy for an application is often
dependent on the specifics of that application.
However, a few of the most common strategies
are:

• Pay the relayer with a potion of the tokens


being sent cross-chain.
• Collect a safe amount of gas money from
the end user prior to performing any
actions.

57 of 132 11/24/22, 17:55


Wormhole Development Book https://book.wormhole.com/print.html

• 'Lazy' relaying, where relaying might only be


profitable in certain, potentially rare,
market conditions.

Generic relayers have an incentive model built in


to the network, so you do not need to design an
incentive structure when using them.

58 of 132 11/24/22, 17:55


Wormhole Development Book https://book.wormhole.com/print.html

Environment Setup
The bare minimum Wormhole environment is
just a blockchain linked up to a Guardian node.
There are quite a few ways of accomplishing this,
and if you're just looking to get your feet wet, you
should try whichever sounds easiest.

However, as you get deeper into cross-chain


development, you'll likely find yourself with a
growing number of components, dependencies,
and teammates in the picture making your
development environment more complex. Here
are some of the considerations you should have
in mind when choosing a development
environment which will be well suited for your
xDapp.

What components do I need now?


What components will I need in the
future?

• You may be able to get a lot done with just


an EVM chain and a Guardian. However, as
your application gets more sophisticated,
components like relayers, frontends,
automated tests, databases, explorers, and
other blockchains are likely to get added
into the environment.

What are my dependencies?

• If your smart contracts have no


dependencies, it may be possible for you to
develop in a vacuum.

• If your smart contracts does have


dependencies, there are several options
that range from deploying your
dependencies in Tilt to simulating an
existing testnet/mainnet in Foundry to

59 of 132 11/24/22, 17:55


Wormhole Development Book https://book.wormhole.com/print.html

working directly in testnet alongside other


teams.

How am I going to collaborate?

• You should consider how your teammates


or collaborators are going to work in this
environment from the start. There are
some basic considerations like "how will
they access it", but also some subtler points
such as ensuring that contracts will deploy
deterministically and that automated tests
can be trusted to run reliably. The two
paths to accomplish this are to use a public
environment (testnet), or to ensure the
local environment is well controlled (like
tilt).

In the following sections we'll describe three


different development environments that are
available -- Tilt, Wormhole Local Validator, and
Testnet -- in more details as well as some
additional tools that should be helpful in your
xDapp development.

60 of 132 11/24/22, 17:55


Wormhole Development Book https://book.wormhole.com/print.html

Tilt (Devnet)

What is Tilt?
Tilt is part of the official Docker ecosystem. It's a
tool which allows developers to easily configure a
Kubernetes environment for development.

However, in the context of Wormhole, 'Tilt' refers


to the development environment used by the
Wormhole Core Repository. This environment
stands up docker images for all the tools
necessary to build across multiple blockchains,
including:

• All the Wormhole supported blockchains /


ecosystems
• A Guardian Node
• Relayers
• Databases, Redis
• Utility frontends

The 'Tilt' environment is meant to provide an


entire cross-chain development stack right out of
the box.

Note: Tilt is often referred to as 'Devnet' in the


Wormhole ecosystem so any information that is
labelled as 'devnet' also applies to Tilt.

Is Tilt Right for You?

Tilt is generally a good starting point for most


developers. Here's a succinct list of the pros and
cons of the environment, so you can decide if it's
the right fit for you.

Pros

• Out-of-the-box support for the many


components needed to develop across the
heterogenous blockchain spaces.

61 of 132 11/24/22, 17:55


Wormhole Development Book https://book.wormhole.com/print.html

• Consistent development environment,


where contracts deploy deterministically
and everything is already linked up.
• Ability to easily enable/disable components
as needed.
• Regularly updated as new components join
the Wormhole ecosystem.

Cons

• Relatively high system requirements but


this can be mitigated by disabling
components.
• Most blockchains are 'fresh' and have no
contracts by default. Thus, if your contracts
have any dependencies, you may have to
deploy them yourself or alter the default tilt
configuration.
• Spin-up and rebuild times can be slow
which can result in a slow workflow.

Setting up Tilt
Tilt functions best in a UNIX-style environment.
For Windows users, a WSL environment is
recommended.

In order to run the Tilt environment, make sure


you have Tilt and Go installed.

Once you've installed these two dependencies,


just clone the Wormhole Core Repository and
start Tilt.

git clone --branch dev.v2


https://github.com/wormhole-foundation
/wormhole.git

cd wormhole

tilt up

Be sure to check out the Tiltfile, which has much


of the configuration and arguments for the
development environment. It's relatively

62 of 132 11/24/22, 17:55


Wormhole Development Book https://book.wormhole.com/print.html

straightforward to enable and disable


components.

For example, you can disable blockchains by


setting them to false at startup

tilt up -- --algorand=false --near=false


--solana=false terra_classic=false
terra2=false

Using Tilt
Tilt can pretty much be treated as an external
environment / testnet that you can easily spin up
and tear down.

If you've followed the standard setup, all your


resources will be bound to various ports on
localhost. To see all the endpoints which are
being hosted in your Tilt environment, you
should check the Tilt dashboard, located at
http://localhost:10350/overview.

All the deployed contract addresses can be found


under the 'Devnet / Tilt' section of contracts.

Useful information pertaining to funded wallets


& private keys can also be found in the
devnet.md file of the docs.

Additional helpful resources can be found in the


Tooling page.

Shutting down Tilt


In order to shut down Tilt, simply run

tilt down

63 of 132 11/24/22, 17:55


Wormhole Development Book https://book.wormhole.com/print.html

Troubleshooting
Tilt, Kubernetes, and Docker may be new tools
for developers entering the Wormhole
ecosystem. This section is meant to provide
some additional support when setting up the
Wormhole Tilt environment.

macOS Install

Prerequisites
Install Homebrew if you don't already have it.

You can grab it with:

/bin/bash -c "$(curl -fsSL


https://raw.githubusercontent.com/Homebrew
/install/HEAD/install.sh)"

From there, all the other installs are one-liners.

1. Install Go

brew install go

2. Install Docker

brew install docker

After installation, go into Docker settings and


switch ON kubernetes . Also configure Docker to
have 4 CPUs and ~16GB of RAM.

3. Install Tilt

brew install tilt

64 of 132 11/24/22, 17:55


Wormhole Development Book https://book.wormhole.com/print.html

4. Clone Wormhole Repo and Start Tilt

git clone --branch dev.v2


https://github.com/wormhole-foundation
/wormhole.git
cd wormhole/
tilt up

You'll be able to access the Tilt UI at


localhost:10350

Linux & WSL Install

Script Setup
If you're using a Debian distro, you should run
the dev-setup.sh script. Even if you're not using
Debian, this script still contains the main steps
for setup.

Regular Setup

1. Install Go

wget https://go.dev/dl/go1.18.1.linux-
amd64.tar.gz
rm -rf /usr/local/go && tar -C /usr/local
-xzf go1.18.1.linux-amd64.tar.gz

2. Install Docker

If you're using Linux with a window manager,


consider getting Docker Desktop instead of the
following command. It comes with Kubernetes
built in and you won't need to download
minikube . It's recommended to have at least 4
CPUs and 16GB RAM dedicated to Docker.

65 of 132 11/24/22, 17:55


Wormhole Development Book https://book.wormhole.com/print.html

Also, make absolutely sure that you set up


Docker as a non-root user.

https://docs.docker.com/engine/install/ubuntu
/#installation-methods

3a. (Docker Desktop Install)

Enable Kubernetes by going into Settings >


Kubernetes

3b. (Non Docker Desktop)

Install minikube .

Configure minikube:

minikube start --driver=docker


--kubernetes-version=v1.23.3 --cpus=4
--memory=14G --disk-size=10G
--namespace=wormhole

Minikube needs to be running for tilt to work, so


always make sure to run minikube start before
you bring up tilt.

4. Install Tilt

Install Tilt by copy pasting this into the Terminal:

curl -fsSL
https://raw.githubusercontent.com/tilt-
dev/tilt/master/scripts/install.sh | bash

5. Clone the Wormhole Repo and start


Tilt

git clone --branch dev.v2


https://github.com/wormhole-foundation
/wormhole.git

If you're running Tilt on your machine:

66 of 132 11/24/22, 17:55


Wormhole Development Book https://book.wormhole.com/print.html

cd wormhole/
tilt up

If you're running Tilt in a VM, you'll need to pass


in some extra flags to enable Tilt to listen to
incoming traffic from external addresses:

cd wormhole
tilt up --host=0.0.0.0 --
--webHost=0.0.0.0

You can now access the Tilt UI at either


localhost:10350 or vm_external_ip:10350 .

If the VM's external IP doesn't work, check


firewall and port settings to make sure your VM
allows incoming traffic.

67 of 132 11/24/22, 17:55


Wormhole Development Book https://book.wormhole.com/print.html

Wormhole Local
Validator

What is Wormhole Local


Validator (WLV)?
Wormhole Local Validator is meant to be the
simplest custom environment. It consists only of
a dockerized Guardian image, and some utility
tooling to aid with contract management. This
allows you to set it up with any blockchain you'd
like.

Is WLV Right for You?

Here's a succinct list of the pros and cons of the


environment, so you can decide if it's the right fit
for you.

Pros

• Lightweight, low system resource demand.


• Fast iteration times.
• Can be added into an existing blockchain
development setup.

Cons

• You may end up reinventing the tilt/testnet


environment as you add more components.

Setting up Wormhole Local


Validator
You will need Docker running in order to set up
WLV. If you're on desktop, Docker Desktop is
generally the best choice, though Docker Engine

68 of 132 11/24/22, 17:55


Wormhole Development Book https://book.wormhole.com/print.html

works fine too.

From there, you just need nodes for the


blockchains you're interested in developing on.
There is code to spin up EVM and Solana local
validators included in the WLV project repo, as
well as scripts to deploy the necessary Wormhole
contracts to your local instances.

Further information can be found in the project's


README.

Troubleshooting
Q: Anvil isn't working

• While Foundry's 'forge' tool is the generally


recommended tool for EVM contract
compilation, Anvil isn't currently compatible
with guardiand. Anvil reports block headers
in a way which is non-compliant with go-
ethereum, which means the guardian node
can't correctly read anvil headers.

69 of 132 11/24/22, 17:55


Wormhole Development Book https://book.wormhole.com/print.html

Testnet
Wormhole testnet is spread across many of the
most popular testnet blockchains.

Is Testnet right for you?

The primary reason to use Wormhole testnet is


to simplify the management of your dependent
contracts. This will vary from blockchain to
blockchain.

For example, some blockchain ecosystems have


the standard that their contracts are closed-
source, and there are no tools to fork mainnet.
Other ecosystems, such as EVM, have tools like
foundry, which allow you to hardfork the
mainnet ecosystem into a local development
node.

In short, testnet tends to be the correct choice


only when you have contract dependencies, and
those dependencies are difficult to get working in
a local environment. In most other cases, testnet
tends to be more work than it's worth.

Here's a succinct list of the pros and cons of the


environment, so you can decide if it's the right fit
for you.

Pros

• Many other projects deploy their contracts


to testnet.
• In ecosystems without extensive local
tooling, this may be the preferred
development environment.

Cons

• Many testnets are somewhat unstable and


have outages or partitioning events.
• Wormhole Testnet sometimes misses VAAs
due to testnet instabilities.

70 of 132 11/24/22, 17:55


Wormhole Development Book https://book.wormhole.com/print.html

• Testnet tokens are often difficult to acquire.

Using Testnet
If you elect to use testnet, the Wormhole
contracts addresses can be found in the
Contracts page.

71 of 132 11/24/22, 17:55


Wormhole Development Book https://book.wormhole.com/print.html

Tooling
Regardless of the development environment that
you use, there are a few wormhole-specific tools
you should know about.

Wormhole Core Repository

• Most developers find it useful to clone the


Wormhole Core repository. This repository
provides the Devnet Tilt environment,
plenty of useful code examples and tests,
along with some utilities which do not have
an official release package.

Worm CLI tool

• Swiss-Army Knife Utility CLI tool. Excellent


for creating one-off VAAs, parsing VAAs,
reading Wormhole contract configurations,
and more.

Orchestrator

• Small WIP tool which comes as part of the


Wormhole Local Validator environment.
Used to quickly deploy and redeploy
multiple smart contracts. Will eventually
become part of a larger deployment
management tool.

Wormhole SDKs

• Libraries in various languages to help with


interacting with Wormhole contracts.

Wormhole Typescript SDK

72 of 132 11/24/22, 17:55


Wormhole Development Book https://book.wormhole.com/print.html

• Typescript SDK destributed on npm. Can


greatly aid in writing frontend code for
xDapps and utilizing the Wormhole Token
Bridge directly.

Wormhole Spy SDK

• The Wormhole Spy SDK allows you to listen


to all of the activity on the Guardian
Network.

Reference Bridge UI

• An example GUI which can be used to


perform token transfers around the
ecosystem.

Explorer

• Resource for looking at individual transfers


statuses on mainnet and testnet.

Example Projects

Basic Examples

• Several example projects are bundled here.


They show minimum-code examples for
how to send messages, tokens, and other
common functions.

ICCO

• Productionized, audited xDapp which does


cross-chain token launches. Great example
of what a robust xDapp, written across
multiple ecosystems looks like.

73 of 132 11/24/22, 17:55


Wormhole Development Book https://book.wormhole.com/print.html

Native Swap

• Example cross-chain dex, utilizing the


stablecoin highway model.

Wormhole Examples

• More example components. Has a mix of


relayers, xDapps, NFT projects, and more.

74 of 132 11/24/22, 17:55


Wormhole Development Book https://book.wormhole.com/print.html

Contract Development
This section should help you get off the ground
with contract development in the Wormhole
ecosystem.

It is written in a fashion which assumes


familiarity with smart contract development in
each ecosystem. As such, it doesn't provide
information on smart contract basics, and
instead focuses on how to properly interact with
the provided Wormhole functions.

While the syntax for each programming


environment differs, the general structure of the
code and best practices tend to be quite similar.
You should consider referencing the sections for
environments other than the one you're working
in, as many of the concepts outlined here are
universal to cross-chain development.

75 of 132 11/24/22, 17:55


Wormhole Development Book https://book.wormhole.com/print.html

EVM
Disclaimer: This section is written as a guide for
how to use Wormhole for experienced EVM
developers. If you are new to using the EVM
ecosystem, it's recommended for you to get
started with a tutorial like this.

Within the Wormhole ecosystem, EVM refers to


any blockchain that utilizes EVM contracts of
Wormhole -- this includes blockchains beyond
Ethereum such as Polygon or Avalanche, as well
as EVM+ environments such as Acala.

At certain points, it may be easiest to integrate


simply by referencing the implementation of the
Wormhole contracts. The official implementation
for the Wormhole contracts can be found here.

Recommended Tooling for EVM

Frontend Development

• Ethers an excellent, widely used library for


using web-based wallets to interact with
EVM blockchains.

Contract Development and Testing

• Foundry is the preferred library for the Core


Repository. It has tooling for development,
testing, compilation, and even the ability to
duplicate mainnet environments for
development.
• Truffle and Hardhat are also viable
alternatives.

76 of 132 11/24/22, 17:55


Wormhole Development Book https://book.wormhole.com/print.html

Core Message Layer


This section will explain how to properly interact
with the Wormhome Core Message Layer in an
EVM ecosystem.

Messages in Wormhole take the form of a


Verified Action Approval (VAA) and both terms
can be used interchangably. The rest of this
section will only use the term VAA.

Configuring the Interface


Here is the interface for applications to interact
with Wormhole's Core Contract to publish VAAs
or verify and parse a received VAAs.

Instantiating the interface will depend on the


contract address of your development ecosystem
and blockchain.

Below is an example line of code to instantiate


the interface for mainnet Ethereum:

address private
wormhole_core_bridge_address =
address(0x98f3c9e6E3fAce36bAAd05FE09d375Ef1464288B)
IWormhole core_bridge =
IWormhole(wormhole_core_bridge_address);

Primary functions
The Wormhole Core Layer has two important
interactions -- (1) emit VAAs, and (2) parse and
verify VAAs that originated from other chains.

Emitting a VAA

There are two forms of VAAs that can be emitted:

77 of 132 11/24/22, 17:55


Wormhole Development Book https://book.wormhole.com/print.html

• Single VAA: all messages will be emitted in


this format
• Batch VAA: messages that are generated
from the same transaction will be emitted
in this format. This feature was developed
to provide an easier paradigm for
composability and better gas efficiency for
more involved cross-chain activity.

To emit a VAA, always use publishMessage


which takes in the following arguments:

1. nonce (uint32): a number assigned to each


message
◦ The nonce provides a mechanism by
which to group messages together
within a Batch VAA. How the nonce is
used is described below.
2. Consistency (uint8): the level of finality the
guardians will reach before signing the
message
◦ Consistency should be considered an
enum, not an integer.
◦ On all EVM chains, 200 will result in an
instant message, while all other values
will wait for finality.
◦ On BSC, the consistency denotes how
many block confirmations will be
waited before producing the message.
◦ More information about finality can be
found Here
3. Payload (bytes[]): raw bytes to emit
◦ It is up to the emitting contract to
properly define this arbitrary set of
bytes.

publishMessage will output a sequence (uint64)


that is used in conjunction with emitterChainID
and emitterAddress to retrive the generated
VAA from the Guardian Network.

How Batch VAAs are generated

There are two mechanisms that allow

78 of 132 11/24/22, 17:55


Wormhole Development Book https://book.wormhole.com/print.html

messages to be Batched together that


represent a base and more advanced level
of composability.

1. All messages originating from the


same transaction will be batched
together.
2. Messages that originate from the
same transaction and are assigned the
same nonce are additionally batched
together.

Note: Single VAAs will always be emitted for


each message within a transaction, regardless
of if a message is included in a batch or not.

Here is an example of how messages


generated from the same transaction may
be batched together:

A transaction X that generates 6 messages


[A, B, C, D, E, F] that are assigned nonce [1,
2, 2, 3, 3, 4] respectively will generate the
following VAAs:

• (1) full transaction batch VAA


◦ [A, B, C, D, E, F]
• (2) smaller batch VAA
◦ [B, C]
◦ [D, E]
• (6) single VAA
◦ [A]
◦ [B]
◦ [C]
◦ [D]
◦ [E]
◦ [F]

Parsing and Verifying a VAA

Parsing and Verifying a VAA will depend on the


type of VAA that your application expects: a
Single VAA or a Batch VAA.

79 of 132 11/24/22, 17:55


Wormhole Development Book https://book.wormhole.com/print.html

For either VAA type, remember to collect gas fees


associated with submitting them on-chain after
all VAAs have been verified.

Single VAA

To properly parse and verify a single VAA, always


use parseAndVerifyVM which takes in one
argument: encodedVM (bytes). This function will
return three arguments:

1. vm (VM): Structured data that reflects the


content of the VAA.
◦ A breakdown of this message format
is described in the VAA section. Aside
from the header information, which
can be considered 'trusted', it is up to
the recipient contract to properly
parse the remaining payload, as this
contains the verbatim message sent
from the emitting contract.
2. valid (bool): Boolean that reflects whether
or not the VAA was properly signed by the
Guardian Network
3. reason (string): Explanatory error message
if a VAA is invalid, or an empty string if it is
valid.

Batch VAA

To properly parse and verify a batch VAA, always


use parseAndVerifyBatchVM which takes in two
arguments: encodedVM (bytes) and cache (bool).

In most scenarios, you'll want to set cache equal


to true.

This will return a VM2 object, containing all the


'headless' VAAs contained inside the batch VAA.
These headless VAAs can be verified by
parseAndVerifyVM , which means that modules
which verify messages in an xDapp can be
agnostic as to whether a message came from a
batch VAA or a single VAA.

The Best Practices section goes into more depth

80 of 132 11/24/22, 17:55


Wormhole Development Book https://book.wormhole.com/print.html

of how to interact with the coreLayer.

81 of 132 11/24/22, 17:55


Wormhole Development Book https://book.wormhole.com/print.html

Token Bridge
This section will explain how to properly interact
with the Wormhome Token Bridge Module in an
EVM ecosystem.

Configuring the interface


Here is the interface for applications to interact
with Wormhole's Token Bridge.

Instantiating the interface will depend on your


development ecosystem and blockchain. The
Wormhole Token Bridge contract address is
usually stored in your contract address.

Below is an example line of code to instantiate


the interface for mainnet Ethereum:

address private
wormhole_token_bridge_address =
address(0x3ee18B2214AFF97000D974cf647E7C347E8fa585)
ITokenBridge token_bridge =
ITokenBridge(wormhole_token_bridge_address);

Registering New Tokens


Attesting a token from EVM needs to happen
once per token as it will not be claimable until so.
However, there are no restrictions to reattesting
a token; repeat attestations will update the
metadata.

It is not advised to attest tokens on-chain for


most usecases. To attest a token by an off-chain
process, you can either do it by hand through
one of the Token Bridge UIs (for example Portal)
or using the Typescript SDK.

Here is an example of how to attest a token using


the Typescript SDK.

82 of 132 11/24/22, 17:55


Wormhole Development Book https://book.wormhole.com/print.html

Basic Transfer
Basic transfer should only be used if you are
transferring tokens to an end user wallet. If the
end destination is a contract, you should only use
Contract Controlled Transfers (described below).

It is important to note the transferring native


currency is a special case of the Basic Transfer.
As such, a different function call for initiating and
completing a transfer is provided as a QoL
improvement that will handle the wrapping and
unwrapping of ETH.

To transfer a token, there are four steps:

1. Approve the Token Bridge to spend that


token on our behalf.
◦ Note: Tokens in EVM usually denote up
to 18 decimals places. However.
Wormhole normalizes this to 8 decimals.

contractAddress.approve(token_bridge_address,
amt);

2. Transfer the token to create the transfer


VAA.
◦ This function call will return a
sequence (uint64) that is used in the
VAA retrieval step.
◦ Note: For the recipient address,
Wormhole addresses are 32 bytes for
standardization across the different
blockchains within the Wormhole
ecosystem.

// To initiate transfer of normal ERC-20s


token_bridge.transferTokens(tokenAddress,
amount, recipientChain, recipient,
arbiterFee, nonce);

// To initiate transfer of native currency


token_bridge.wrapAndTransferETH(recipientChain,
recipient, arbiterFee, nonce);

3. Retrieve the emitted VAA.


◦ Basic Transfer VAAs are retrieved from

83 of 132 11/24/22, 17:55


Wormhole Development Book https://book.wormhole.com/print.html

the Guardian Network by the


emitterChainID , emitterAddress ,
and sequence .

const emitterAddr =
getEmitterAddressEth(network.tokenBridgeAddress);
const seq = parseSequenceFromLogEth(tx,
network.bridgeAddress);
const vaaURL =
`${config.wormhole.restAddress}/v1
/signed_vaa/${network.wormholeChainId}
/${emitterAddr}/${seq}`;
let vaaBytes = await (await
fetch(vaaURL)).json();
while (!vaaBytes.vaaBytes) {
console.log("VAA not found, retrying in
5s!");
await new Promise((r) => setTimeout(r,
5000)); //Timeout to let Guardiand pick up
log and have VAA ready
vaaBytes = await (await
fetch(vaaURL)).json();
}

4. Complete the transfer using the VAA.

// To complete transfer of normal ERC-20s


token_bridge.completeTransfer(VAA);

// To complete transfer of native currency


completeTransferAndUnwrapETH(VAA);

Contract Controlled Transfer


For any token transfers where the destination is
a contract, you should always use Contract
Controlled Transfers.

There are a few main differences between


Contract Controlled Transfers and Basic
Transfers:

• messages contains both tokens and an


arbitrary payload
• messages can only be redeemed by a
specified contract address
• messages do not have a relayer fee field

84 of 132 11/24/22, 17:55


Wormhole Development Book https://book.wormhole.com/print.html

because of the redemption restriction


above

As was the case with Basic Transfers, transferring


native currency is a special case for Contract
Controlled Transfers as well. As such, similar QoL
improvement functions are provided that handle
the wrapping and unwrapping of ETH.

The process of sending a Contract Controlled


Transfer is very similar to that of a Basic Transfer:

1. Approve the Token Bridge to spend that


token on our behalf.
◦ Note: Tokens in EVM usually denote up
to 18 decimals places. However.
Wormhole normalizes this to 8 decimals.

contractAddress.approve(token_bridge_address,
amt);

2. Transfer the token to create the transfer


VAA.
◦ This function call will return a
sequence (uint64) that is used in the
VAA retrieval step.
◦ Note: For the recipient addres,
Wormhole addresses are 32 bytes for
standardization across the different
blockchains within the Wormhole
ecosystem.

// To initiate transfer of normal ERC-20s


token_bridge.transferTokesWithPayload(tokenAddress,
amount, recipientChain, recipient, nonce,
payload);

// To initiate transfer of native currency


token_bridge.wrapAndTransferETHWithPayload(recipien
recipient, nonce, payload);

3. Retrieve the emitted VAA.


◦ Contract Controlled Transfer VAAs are
retrieved from the Guardian Network
by the emitterChainID ,
emitterAddress , and sequence .

85 of 132 11/24/22, 17:55


Wormhole Development Book https://book.wormhole.com/print.html

const emitterAddr =
getEmitterAddressEth(network.tokenBridgeAddress);
const seq = parseSequenceFromLogEth(tx,
network.bridgeAddress);
const vaaURL =
`${config.wormhole.restAddress}/v1
/signed_vaa/${network.wormholeChainId}
/${emitterAddr}/${seq}`;
let vaaBytes = await (await
fetch(vaaURL)).json();
while (!vaaBytes.vaaBytes) {
console.log("VAA not found, retrying in
5s!");
await new Promise((r) => setTimeout(r,
5000)); //Timeout to let Guardiand pick up
log and have VAA ready
vaaBytes = await (await
fetch(vaaURL)).json();
}

4. Complete the transfer using the VAA.

// To complete transfer of normal ERC-20s


token_bridge.completeTransferWithPayload(VAA);

// To complete transfer of native currency


completeTransferAndUnwrapETHWithPayload(VAA);

86 of 132 11/24/22, 17:55


Wormhole Development Book https://book.wormhole.com/print.html

NFT Bridge
This section will explain how to properly interact
with the NFT Bridge Module in an EVM
ecosystem.

Configuring the interface


Here is the interface for applications to interact
with Wormhole's NFT Bridge.

Instantiating the interface will depend on the


contract address of your development ecosystem
and blockchain.

Below is an example line of code to instantiate


the interface for mainnet Ethereum:

address private
wormhole_NFT_bridge_address =
address(0x6FFd7EdE62328b3Af38FCD61461Bbfc52F5651fE)
INFTBridge NFT_bridge =
INFTBridge(wormhole_nft_bridge_address);

Transferring a NFT
The Wormhole NFT Bridge only supports tokens
compliant with the ERC-721 interface, and
functions by creating a 'wrapped NFT' with
identical metadata. How this is implemented
varies by ecosystem.

Note: Unlike tokens, there is no attestation


required for bridging NFTs.

To transfer a NFT, there are three steps:

1. Initiate the NFT transfer


◦ This function call will return a
sequence (uint64) that is used in the
VAA retrieval step

87 of 132 11/24/22, 17:55


Wormhole Development Book https://book.wormhole.com/print.html

transferNFT(tokenAddress, tokenID,
recipientChain, recipient, nonce);

2. Retrieve the emitted VAA from the Guardian


Network. (Usually done by a relayer)
◦ NFT Transfer VAAs are retrieved from
the Guardian Network by the
emitterChainID , emitterAddress ,
and sequence .

const emitterAddr =
getEmitterAddressEth(network.NFTBridgeAddress);
const seq = parseSequenceFromLogEth(tx,
network.bridgeAddress);
const vaaURL =
`${config.wormhole.restAddress}/v1
/signed_vaa/${network.wormholeChainId}
/${emitterAddr}/${seq}`;
let vaaBytes = await (await
fetch(vaaURL)).json();
while (!vaaBytes.vaaBytes) {
console.log("VAA not found, retrying in
5s!");
await new Promise((r) => setTimeout(r,
5000)); //Timeout to let Guardiand pick up
log and have VAA ready
vaaBytes = await (await
fetch(vaaURL)).json();
}

3. Complete the NFT transfer by submitting


the resultant VAA to the target chain.

completeTransfer(VAA);

88 of 132 11/24/22, 17:55


Wormhole Development Book https://book.wormhole.com/print.html

Relayer Module
Disclaimer: This module is only available in
devnet, and is subject to change while still in
development.

In order to integrate with the relayer module


(which enables generic relaying), there are two
requirements placed on the integrator.

1. To receive messages, the integrator must


implement the wormholeReceiver
interface, which will be called by the relayer
to deliver the requested messages. If the
recipient contract does not implement this
function on their contract, the delivery will
automatically fail.

2. To request message delivery, the integrator


must call the
requestDelivery(DeliveryInstructions
instructions) function on the relayer
module.

Receiving Messages
Receiving messages through the relayer module
is almost trivial. Simply implement the public
function wormholeReciever in your contract that
the relayer module will invoke.

function wormholeReceiver(
bytes[] memory vaas,
uint16 sourceChain,
bytes32 sourceAddress,
bytes memory payload
)

This is the function takes the following four


inputs:

• vaas : VAAs which were requested for


delivery

89 of 132 11/24/22, 17:55


Wormhole Development Book https://book.wormhole.com/print.html

• sourceChain : Wormhole chain ID of the


chain the messages were sent from
• sourceAddress : address which requested
delivery (In Wormhole format!)
• payload : additional payload which is at the
top level

There are a few noteworthy items here:

• wormholeReceiver function should never


throw an exception. Throwing an exception
here will just cause a delivery failure and
will not revert the transaction(!!!).
• wormholeReceiver will only be called with
as much gas as was specified by the
compute budget specified when the
message delivery was requested.
• Batch VAAs are always used by the relayer
module. vaas is an array of all the headless
VAAs for which delivery was requested.
These VAAs are not verified until you have
VM objects which is obtained by calling
core_bridge.parseAndVerifyVM ! (More on
this in Best Practices)
• The generic relay VAA will be included in the
vaas array you receive. This VAA can be
ignored, but you can use it if it's useful to
you.

Sending Messages
In order to send a message to another contract,
you must call
requestDelivery(DeliveryInstructions
instructions) . There are a few different things
you can accomplish with this call.

First let's lay out the DeliveryInstructions object,


which is part of the relayer module structs.

90 of 132 11/24/22, 17:55


Wormhole Development Book https://book.wormhole.com/print.html

struct DeliveryParameters {
uint16 targetChain;
bytes32 targetAddress;
bytes payload;
VAAId[] deliveryList;
bytes relayParameters;
bytes chainPayload;
uint32 nonce;
uint8 consistencyLevel;
}

• targetChain : chain ID of the chain this


should be delivered to
• targetAddress : contract address to deliver
to (in Wormhole format)
• payload : additional payload which will be
included in the delivery
• deliveryList (optional): mechanism for re-
delivery of already existing VAAs
• relayParameters : information required to
relay to the target env. Contains compute
budget
• chainPayload : information used for
computation efficiency when relaying to
other ecosystems
• nonce (optional): If included, only messages
with this nonce will be relayed
• consistencyLevel : what level of
consistency / finality to reach before
emitting the message
• msg.value : payment in native currency to
relayer that must cover the compute
budget specified in the relayer parameters

Compute Budget
Part of the relay parameters is a
'computeBudget' which specifies the maximum
amount of computation that can be spent
executing delivery on the destination contract.
This is effectively a 'gasLimit' in the EVM
ecosystem, but due to the relayer network
supporting blockchains that don't utilize the

91 of 132 11/24/22, 17:55


Wormhole Development Book https://book.wormhole.com/print.html

concept of gas, we use a more generalizable


concept of 'computation budget'.

When requesting delivery, the caller must specify


and pay for the compute budget upfront.
Compute budget which is not utilized will be
refunded on the target chain. If the compute
budget is exhausted during the execution of the
delivery, a delivery failure occurs. When a
delivery failure occurs, the computation budget
from the source chain is not refunded, as the
relayer used it to process the failed transaction.

The computation 'rate' is specified by the relayer


module and is different for each blockchain. The
quote provided by the relayer module contains
the fee for the requested compute budget AND
the fixed overheads of the computation which is
done by the relayer contract.

Delivery Failures
'Delivery Failure' is a technical term in the case of
the relayer module. It does not mean 'something
went wrong', but rather that the relayer
attempted to deliver the VAA, and was
unsuccessful. There are only 3 causes of a
delivery failure.

• The wormholeReceiver function is either


missing or otherwise uncallable on the
recipient contract.
• The wormholeReceiver function
encountered an exception while processing.
• The wormholeReceiver function exhausted
the computeBudget that was specified by
the delivery requester.

All three of these scenarios are controllable by


the integrator. In order to avoid delivery failures,
the integrators should have a top-level try-catch
such that the wormholeReceiver never reverts,
and should always request a worst-case compute

92 of 132 11/24/22, 17:55


Wormhole Development Book https://book.wormhole.com/print.html

budget since excess budget will be refunded.

Delivery Retries
In the unfortunate scenario of a delivery failure,
the VAAs can be re-delivered by requesting their
delivery a second time. To accomplish this,
simply list their VAA IDs in the deliveryList in
the call.

More info and features to come. This module


is still in development.

93 of 132 11/24/22, 17:55


Wormhole Development Book https://book.wormhole.com/print.html

Best Practices
The Wormhole contracts were designed in a
manner such that composability is the default,
but maximizing composability requires that
xDapp developers follow certain conventions
around the sending and receiving of messages.

Sending Messages
When sending messages, you should follow the
same paradigm as is used by the Wormhole
modules, namely

• Don't couple the message emission to the


message delivery
• Pass through all the optional arguments
(like nonce)
• Always return the sequence

Good Example

94 of 132 11/24/22, 17:55


Wormhole Development Book https://book.wormhole.com/print.html

// This function defines a super simple


Wormhole 'module'.
// A module is just a piece of code which
knows how to emit a composable message
// which can be utilized by other
contracts.
function emitMyMessage(address
intendedRecipient, uint32 nonce)
public payable returns (uint64
sequence) {

// Nonce is passed though to the core


bridge.
// This allows other contracts to
utilize it for batching or processing.

// intendedRecipient is key for


composability!
// This field will allow the
destination contract to enforce
// that the correct contract is
submitting this VAA.

// consistency level 200 means instant


emission
sequence =
core_bridge.publishMessage(nonce, "My
Message to " + intendedRecipient, 200);

// The sequence is passed back to the


caller, which can be useful relay
information.
// Relaying is not done here, because
it would 'lock' others into the same relay
mechanism.
}

// This portion of the code which deals


with composition and delivery.
// Its job is to string together multiple
modules, and ensure they get relayed
// This code can be private or public,
because it's tightly coupled to
application.
// Do whatever you need to here.
function sendMyMessage() private {

// First, emit a message intended for


MY_OTHER_CONTRACT with nonce zero.
// Because processMyMessage enforces
that msg.sender must equal the
intendedRecipient,
// no one but MY_OTHER_CONTRACT will
be able to call processMyMessage
// with the message emitted from this
transaction.

95 of 132 11/24/22, 17:55


Wormhole Development Book https://book.wormhole.com/print.html

// However, another contract could


call emitMyMessage in a different
transaction
// using their own address as the
recipient.

// This allows for composability of


the module logic while still being secure!

emitMyMessage(MY_OTHER_CONTRACT, 0);

// Suppose I also want to send tokens


to my contract on the OTHER_CHAIN
// Because transferTokensWithPayload
is a composable message, I can include it.
// Because the nonce of both these
messages is 0, they will be combined into
a batch VAA.
// NOTE: transferTokens (the basic
transfer) is NOT considered a composable
message

token_bridge.transferTokensWithPayload(SOME_TOKEN,
SOME_AMOUNT, OTHER_CHAIN,
MY_OTHER_CONTRACT,
0, null);

// Lastly, I request that the batch


for nonce 0 be delivered to
MY_OTHER_CONTRACT

relayer_contract.requestDelivery(OTHER_CHAIN,
MY_OTHER_CONTRACT, 0,
getRelayerFeeAmount());
}

Receiving Messages
The best practices for receiving messages
employ similar concepts. You should keep in
mind that other contracts might want to
integrate with your specific logic. As such, you
shouldn't tie your verification logic to the delivery
mechanism of your VAAs, and you should also
give external integrators a safe way to compose
with your module.

Critical!

96 of 132 11/24/22, 17:55


Wormhole Development Book https://book.wormhole.com/print.html

• Always verify that the emitterAddress of the


VAA comes from a contract you trust.

• If the message should not be allowed to be


'replayed', immediately mark its hash as
processed.

• If your VAAs aren't replayable, you almost


always want to include and enforce an
intended recipient. Otherwise anyone can
call your verify function directly with the
single VAA, which will make life much
harder for you and your integrators who
want to process multiple VAAs at once. This
is referred to as a 'scoop' exploit.

Composability

• When processing a VAA, always treat the


messages as single VAAs. Destructuring
batch VAAs is the responsibility of the
integrator.
• Once you have the function written to verify
your message, pretend you are an external
integrator.

Good Example

97 of 132 11/24/22, 17:55


Wormhole Development Book https://book.wormhole.com/print.html

// Verification accepts a single VAA, and


is publicly callable.
function processMyMessage(bytes32 memory
VAA) public {
// This call accepts single VAAs and
headless VAAs
(IWormhole.VM memory vm, bool valid,
string memory reason) =
core_bridge.parseAndVerifyVM(VAA);

// Ensure core contract verification


succeeded.
require(valid, reason);

// Ensure the emitterAddress of this


VAA is a trusted address

require(myTrustedContracts[vm.emitterChainId]
==
vm.emitterAddress, "Invalid
Emitter Address!");

// Check that the VAA hasn't already


been processed (replay protection)
require(!processedMessages[vm.hash],
"Message already processed");

// Check that the contract which is


processing this VAA is the
intendedRecipient
// If the two aren't equal, this VAA
may have bypassed its intended entrypoint.
// This exploit is referred to as
'scooping'.

require(parseIntendedRecipient(vm.payload)
== msg.sender);

// Add the VAA to processed messages


so it can't be replayed
processedMessages[vm.hash] = true

// The message content can now be


trusted.
doBusinessLogic(vm.payload)
}

//This is the function which would receive


the the VAA from the relayer
function receiveVAA(bytes32 memory
batchVAA) public {
// First, call the core bridge to
verify the batchVAA
// All the individual VAAs inside the
batchVAA will be cached,
// and you will receive headless VAAs

98 of 132 11/24/22, 17:55


Wormhole Development Book https://book.wormhole.com/print.html

inside the VM2 object.


// Headless VAAs are verifiable by
parseAndVerifyVM.

(IWormhole.VM2 memory vm2, bool valid,


string memory reason) =

core_bridge.parseAndVerifyBatchVM(batchVAA,
true);

// I know from sendMyMessage that the


first VAA is a token bridge VAA,
// so let's hand that off to the token
bridge module.
bytes vaaData =
token_bridge.completeTransferWithPayload(vm2.payloa

// The second VAA is my message, let's


hand that off to my module.
processMyMessage(vm2.payloads[1]);

// Lastly, uncache the headless VAAs


from the core bridge.
// This refunds a significant amount
of gas.

core_bridge.clearBatchCache(vm2.hashes);
}

99 of 132 11/24/22, 17:55


Wormhole Development Book https://book.wormhole.com/print.html

Specialized Relayers
Rather than home-rolling a relayer, it's
recommended that integrators start from the
existing Spy Relayer provided in the Wormhole
Core Repository.

Additionally there's an extensible relayer (called


the Plugin Relayer) currently in development.

100 of 132 11/24/22, 17:55


Wormhole Development Book https://book.wormhole.com/print.html

Wormhole Typescript
SDK
A Wormhole Typescript SDK provided for
applications that only need to interact with the
Core and Token Bridge contracts off-chain.

It can be installed using npm:

npm i @certusone/wormhole-sdk

The following sections will explain and provide


examples of how to perform key functions with
Wormhole using the Typescript SDK.

For more examples with a more exhaustive


coverage of all the supported blockchains in
Wormhole, be sure to check the official codebase
for the Typescript SDK.

Virtually all functions of the SDK are


demonstrated in the reference bridge UI, which
makes it an excellent source of example code as
well.

101 of 132 11/24/22, 17:55


Wormhole Development Book https://book.wormhole.com/print.html

Registering Tokens
Registering tokens with the token bridge can be
done from any supported blockchain, and only
needs to be done once - globally - per token. This
is is typically done via a UI (such as Portal) rather
than done on-chain.

If you need to do it programmatically, you can


also use the Typescript SDK to attest a token.

There are three steps to registerring a token:

1. Create an AttestMeta VAA by calling


attest() function from the SDK and
passing in the Token Bridge address, and
the address of the Token we want to attest.

For example, here is the code to produce an


attestation VAA using ethers:

const networkTokenAttestation = await


attestFromEth(
network.tokenBridgeAddress, // Token
Bridge Address
signer, //Private Key to sign and pay
for TX + RPC Endpoint
network.testToken //Token Address
);

The attestation transaction will produce a signed


VAA. This signed VAA is necessary in order to
register the tokens on other chains.

2. Retrieve the VAA with the emitterAddress


of the Token Bridge and the sequence from
the logs of the transaction receipt.

With those, you can fetch the VAA from any


Guardian REST endpoint. It could take a moment
(up to 30 seconds) for the Guardian to see and
sign the VAA, so it's a good idea to poll the
Guardian every few seconds until the VAA is
found.

Here is a relatively compact piece of code which


is able to fetch any VAA, given an emitter

102 of 132 11/24/22, 17:55


Wormhole Development Book https://book.wormhole.com/print.html

address and sequence number.

const emitterAddr =
getEmitterAddressEth(network.tokenBridgeAddress);
const seq = parseSequenceFromLogEth(
networkTokenAttestation,
network.bridgeAddress
);
const vaaURL =
`${config.wormhole.restAddress}/v1
/signed_vaa/${network.wormholeChainId}
/${emitterAddr}/${seq}`;
console.log("Searching for: ", vaaURL);
let vaaBytes = await (await
fetch(vaaURL)).json();
while (!vaaBytes.vaaBytes) {
console.log("VAA not found, retrying in
5s!");
await new Promise((r) => setTimeout(r,
5000)); //Timeout to let Guardiand pick up
log and have VAA ready
vaaBytes = await (await
fetch(vaaURL)).json();
}

3. Submit the VAA onto the target chain to


create a wrapped version of the token by
calling createWrapped() .

You can get the new wrapped token address by


calling the wrappedAsset() function of the
TokenBridge.

Here is how this can be accomplished using


Ethers:

103 of 132 11/24/22, 17:55


Wormhole Development Book https://book.wormhole.com/print.html

await targetTokenBridge.createWrapped(
Buffer.from(vaaBytes.vaaBytes,
"base64"),
{
gasLimit: 2000000,
}
);
await new Promise((r) => setTimeout(r,
5000)); //Time out to let block propogate
const wrappedTokenAddress = await
targetTokenBridge.wrappedAsset(
network.wormholeChainId,

Buffer.from(tryNativeToHexString(network.testToken,
"ethereum"), "hex")
);
console.log("Wrapped token created at: ",
wrappedTokenAddress);

104 of 132 11/24/22, 17:55


Wormhole Development Book https://book.wormhole.com/print.html

Token Transfers
Before transferring tokens, you should ensure
that the token is registered on the chain you are
transferring to, and that any necessary
prerequisite steps (such as sending token
approvals or creating associated token accounts)
have already been done.

There are four steps to transferring a token:

1. If not already done, complete a standard


ERC-20 token approval prior to performing
a bridge action if you're in the EVM
ecosystem.

// Here we are approving and transfering


50 tokens. The ERC20 token we are
transfering has 18 decimal places.
const bridgeAmt =
ethers.utils.parseUnits("50", "18");

await
treasury.approveTokenBridge(bridgeAmt, {
gasLimit: 2000000,
});

2. Initate a transfer by calling transfer on


the token bridge module which will create a
transfer VAA.

Note that the target receipient is a Wormhole-


format address (referred to as 'hex' format in the
Typescript SDK).

const targetRecepient = Buffer.from(

tryNativeToHexString(targetDeployment.deployedAddre
"ethereum"),
"hex"
);

const tx = await (
await treasury.bridgeToken(
bridgeAmt,
targetNetwork.wormholeChainId,
targetRecepient
)
).wait();

105 of 132 11/24/22, 17:55


Wormhole Development Book https://book.wormhole.com/print.html

3. Retrieve the VAA with the emitterAddress


of the Token Bridge and the sequence from
the logs of the transaction receipt. (This is
the same code as shown in the previous
section.)

const emitterAddr =
getEmitterAddressEth(network.tokenBridgeAddress);
const seq = parseSequenceFromLogEth(tx,
network.bridgeAddress);
const vaaURL =
`${config.wormhole.restAddress}/v1
/signed_vaa/${network.wormholeChainId}
/${emitterAddr}/${seq}`;
let vaaBytes = await (await
fetch(vaaURL)).json();
while (!vaaBytes.vaaBytes) {
console.log("VAA not found, retrying in
5s!");
await new Promise((r) => setTimeout(r,
5000)); //Timeout to let Guardiand pick up
log and have VAA ready
vaaBytes = await (await
fetch(vaaURL)).json();
}

4. Submit the VAA to the target chain by


calling completeTransfer() .

If you're not using a relayer, you'll have to submit


the target chain transaction yourself. This section
outlines how to use relayers.

const completeTransferTx = await


targetTokenBridge.completeTransfer(
Buffer.from(vaaBytes.vaaBytes, "base64")
);

106 of 132 11/24/22, 17:55


Wormhole Development Book https://book.wormhole.com/print.html

Cross-Ecosystem
Token Transfer
A defining feature of cross chain apps (xDapps) is
the ability to move tokens from one chain to
another, even if those blockchains have radically
different virtual machine models.

To demonstrate, let’s do a simple programmatic


transfer from Ethereum to Solana.

First, determine the address on Solana where


we're sending the tokens. Unlike EVM chains
where the wallet address is used, we need to
send the tokens to the recipient's associated
token account for that token. We'll use a couple
helper functions from the Wormhole Typescript
SDK to make this easier.

107 of 132 11/24/22, 17:55


Wormhole Development Book https://book.wormhole.com/print.html

import {
Token,
ASSOCIATED_TOKEN_PROGRAM_ID,
TOKEN_PROGRAM_ID,
} from "@solana/spl-token";
import {
getForeignAssetSolana,
hexToUint8Array,
nativeToHexString,
CHAIN_ID_ETH,
} from "@certusone/wormhole-sdk";

const SOLANA_TOKEN_BRIDGE_ADDRESS =

"wormDTUJ6AWPNvk59vGQbDvGJmqbDTdgWgAqcLBCgUb"
// determine destination address - an
associated token account
const solanaMintKey = new PublicKey(
(await getForeignAssetSolana(
connection,
SOLANA_TOKEN_BRIDGE_ADDRESS,
CHAIN_ID_ETH,

hexToUint8Array(nativeToHexString(tokenAddress,
CHAIN_ID_ETH) || "")
)) || ""
);
const recipientAddress = await
Token.getAssociatedTokenAddress(
ASSOCIATED_TOKEN_PROGRAM_ID,
TOKEN_PROGRAM_ID,
solanaMintKey,
recipientWalletAddress
);

After we have the receipt token account on


Solana, it's time to submit the transfer message
on Ethereum. This will output a log that contains
a sequence number (a unique number for the
message) and an emitter address (the ETH Token
Bridge Address in Wormhole format). The
sequence number and emitter address will be
used to fetch the VAA after it’s been signed by
Guardians.

108 of 132 11/24/22, 17:55


Wormhole Development Book https://book.wormhole.com/print.html

import {
trasnferFromEth,
parseSequenceFromLogEth,
getEmitterAddressEth,
CHAIN_ID_SOLANA,
} from "@certusone/wormhole-sdk";

const ETH_TOKEN_BRIDGE_ADDRESS =
"0x3ee18B2214AFF97000D974cf647E7C347E8fa585"

// Submit transaction - results in a


Wormhole message being published
const receipt = await transferFromEth(
ETH_TOKEN_BRIDGE_ADDRESS,
signer,
tokenAddress,
amount,
CHAIN_ID_SOLANA,
recipientAddress
);
// Get the sequence number and emitter
address required to fetch the signedVAA of
our message
const sequence =
parseSequenceFromLogEth(receipt,
ETH_BRIDGE_ADDRESS);
const emitterAddress =
getEmitterAddressEth(ETH_TOKEN_BRIDGE_ADDRESS);

Once the Guardians have signed the token


bridge VAA, it needs to be retrieved from the
Guardian Network. This time we'll use the
Guardian GRPC endpoint, though the REST
endpoint used in previous sections works as well.

import { getSignedVAA } from


"@certusone/wormhole-sdk";

// Fetch the signedVAA from the Wormhole


Network (this may require retries while
you wait for confirmation)
const { signedVAA } = await getSignedVAA(
WORMHOLE_RPC_HOST,
CHAIN_ID_ETH,
emitterAddress,
sequence
);

Now, we post the VAA to Solana in order to mint


the wrapped tokens. Because of the compute
limit on Solana, we split the signature verification
and token claim into steps. To do that, verify all

109 of 132 11/24/22, 17:55


Wormhole Development Book https://book.wormhole.com/print.html

the signatures and create a claim account for the


token.

const SOL_BRIDGE_ADDRESS =
"worm2ZoG2kUd4vFXhvjh93UUH596ayRfgQ2MgjNMTth"
await postVaaSolana(
connection, // Solana Mainnet Connection
wallet, //Solana Wallet Signer
SOL_BRIDGE_ADDRESS,
payerAddress,
signedVAA
);

Finally, claim the tokens:

const transaction = await redeemOnSolana(


connection,
SOL_BRIDGE_ADDRESS,
SOL_TOKEN_BRIDGE_ADDRESS,
payerAddress,
signedVAA,
isSolanaNative,
mintAddress
);
const signed = await
wallet.signTransaction(transaction);
const txid = await
connection.sendRawTransaction(signed.serialize());
await connection.confirmTransaction(txid);

110 of 132 11/24/22, 17:55


Wormhole Development Book https://book.wormhole.com/print.html

Using Relayers
In this example, we’ll utilize the token bridge
relayer network to complete a token transfer
from Polygon and to Oasis.

This code is written for a browser environment. If


you're working in node, consider using node-
fetch:

npm i --save @certusone/wormhole-sdk


ethers node-fetch

import { BigNumber, ethers } from


"ethers";
import fetch from "node-fetch";
import {
getEmitterAddressEth,
hexToUint8Array,
nativeToHexString,
parseSequenceFromLogEth,
CHAIN_ID_POLYGON,
CHAIN_ID_OASIS,
transferFromEthNative,
getIsTransferCompletedEth,
setDefaultWasm,
} from "@certusone/wormhole-sdk";

Setup the Polygon and Oasis Wallets

Now, set up the two wallets we’ll be sending and


receiving from. While we are instantiating both
wallets with their private keys, we only need the
Public key of the receiving wallet for this
example.

const EmeraldWallet = new ethers.Wallet(


privatekey_emerald,
new
ethers.providers.JsonRpcProvider("https://emerald.o
);
const PolygonWallet = new ethers.Wallet(
privatekey_polygon,
new
ethers.providers.JsonRpcProvider("https://polygon-
rpc.com/")
);

111 of 132 11/24/22, 17:55


Wormhole Development Book https://book.wormhole.com/print.html

Fetch the fee schedule

Fetch the fee schedule for the token bridge


relayers. This fee schedule outlines the minimum
fee for each recipient chain that relayers will
accept. As long as we attach at least that fee in
the relayer fee, we can expect a relayer pick up
the transaction and relay it to the recipient chain.
The fee will cover the gas cost for the relayer
along with a little extra to make it worth their
time to run the relayer service.

We will also define the transfer amount in this


step. The fee schedule will either return a flat fee
in USD for the recipient chain, or a percentage
fee (usually only for Ethereum). Either way, we’ll
need to calculate the fee in BigNumber format
(no decimals).

const transferAmount =
BigNumber.from("1000000000000000000"); //
We are sending 1 MATIC over the wall to
Oasis
const relayerFeeSchedule = await(
await fetch(
"https://raw.githubusercontent.com
/certusone/wormhole-relayer-list/main
/relayer.json"
)
).json();

The fee schedule has the following interface:

112 of 132 11/24/22, 17:55


Wormhole Development Book https://book.wormhole.com/print.html

export interface RelayerFeeSchedule {


supportedTokens: ChainAddress[];
relayers: Relayer[];
feeSchedule: FeeSchedule;
}

interface ChainAddress {
chainId: number;
address: string;
coingeckoId: string;
}

interface Relayer {
name: string;
url: string;
}

interface FeeSchedule {
[chainId: string]: {
type: "flat" | "percent";
feeUsd?: number;
feePercent?: number;
gasEstimate?: number;
};
}

After fetching the fee schedule, find the fee in


wei that needs to be paid to the Relayer. At the
time of writing, Oasis has a flat fee of $0.50, so to
calculate how much MATIC we need to pay for
the $0.50 fee, we need to fetch the MATIC price.
To do that, use the free CoinGecko api:

113 of 132 11/24/22, 17:55


Wormhole Development Book https://book.wormhole.com/print.html

let feeWei: number;


if
(relayerFeeSchedule.feeSchedule[CHAIN_ID_OASIS].typ
== "flat") {
const feeUsd =
relayerFeeSchedule.feeSchedule[CHAIN_ID_OASIS].feeU
const MATIC_PRICE = await(
await fetch(
"https://api.coingecko.com/api/v3
/simple/token_price/polygon-
pos?contract_addresses=0x0d500b1d8e8ef31e21c99d1db9
vs_currencies=usd"
)
).json()
["0x0d500b1d8e8ef31e21c99d1db9a6444d3adf1270"
["usd"];

feeWei = (feeUsd / MATIC_PRICE) * 1e18;


} else if
(relayerFeeSchedule.feeSchedule[CHAIN_ID_OASIS].typ
== "percent") {
let feeWei =

(relayerFeeSchedule.feeSchedule[CHAIN_ID_OASIS].fee
/ 100) *
transferAmount.toNumber();
}

Overrides & Quirks

Dependent on the specific blockchains you are


working with, you may need to perform special
actions when submitting this transaction.
Because we're dealing with Polygon in this
example, there's an additional step to
overestimate the gas. This is because Ethers
library has some problems with fee estimation
after EIP-1559.

let overrides;
let feeData = await
PolygonWallet.provider.getFeeData();
overrides = {
maxFeePerGas:
feeData.maxFeePerGas?.mul(50) ||
undefined,
maxPriorityFeePerGas:
feeData.maxPriorityFeePerGas?.mul(50) ||
undefined,
};

114 of 132 11/24/22, 17:55


Wormhole Development Book https://book.wormhole.com/print.html

Emit Token Bridge Message

Now we have all the pieces we need to emit a


token bridge message with a relay fee attached.
We do this using the transferFromEthNative()
method. EthNative is used because we’re
transferring the native token of the Polygon
network rather than an ERC20 token.

const POLYGON_TOKEN_BRIDGE =
"0x5a58505a96D1dbf8dF91cB21B54419FC36e93fdE"

const receipt = await


transferFromEthNative(
POLYGON_TOKEN_BRIDGE,
PolygonWallet,
transferAmount,
CHAIN_ID_OASIS,
hexToUint8Array(
nativeToHexString(await
EmeraldWallet.getAddress(),
CHAIN_ID_OASIS) || ""
),
BigNumber.from(feeWei.toString()),
overrides
);
console.log("Receipt: ", receipt);

const POLYGON_CORE_BRIDGE_ADDRESS =

"0x7A4B5a56256163F07b2C80A7cA55aBE66c4ec4d7"
const sequence =
parseSequenceFromLogEth(receipt,
POLYGON_CORE_BRIDGE_ADDRESS);
const emitterAddress =
getEmitterAddressEth(POLYGON_TOKEN_BRIDGE);
console.log("Sequence: ", sequence);
console.log("EmitterAddress: ",
emitterAddress);

Let’s walk through each of the arguments of this


function and what they mean.

POLYGON_TOKEN_BRIDGE is the address of the


token bridge module on the Polygon network.
You can find it and other addresses on the
contracts page.

PolygonWallet is a signer you get from the


Ethers library that holds a private key that can
sign transactions.

115 of 132 11/24/22, 17:55


Wormhole Development Book https://book.wormhole.com/print.html

transferAmount is a BigNumber that contains


the amount to transfer in the smallest unit of the
network.

CHAIN_ID_OASIS is a constant that identifies the


target chain.

hexToUint8Array() translates the target


publickey into a wormhole public key.

BigNumber.from(feeWei.toString()) identifies
the fee in smallest unit of the network for the
relayer.

overrides are used if we need to override the


gas cost, which we need to do for Polygon.

Check VAA was signed

Wait 15 min for finality on Polygon and then


check to see if it was submitted. If successful,
you’ll be able to fetch a base64 encoded
vaaBytes. We need this in the next step where we
check if the transaction was successfully relayed.

await new Promise((r) => setTimeout(r,


900000)); //15m in seconds
const WORMHOLE_RPC = "https://wormhole-v2-
mainnet-api.certus.one";
let vaaBytes = undefined;
while (!vaaBytes) {
try {
vaaBytes = await(
await fetch(
`${WORMHOLE_RPC}/v1/signed_vaa
/${CHAIN_ID_POLYGON}/${emitterAddress}
/${sequence}`
)
).json().vaaBytes;
} catch (e) {
await new Promise((r) => setTimeout(r,
5000));
}
}
console.log("VAA Bytes: ", vaaBytes);

Check if the transfer was completed

116 of 132 11/24/22, 17:55


Wormhole Development Book https://book.wormhole.com/print.html

In the final step, use the


getIsTransferCompletedEth() method to check if
the transfer was completed on the Oasis Emerald
chain. If it’s not, wait 5 seconds and check again.

setDefaultWasm("node"); //only needed if


running in node.js
const EMERALD_TOKEN_BRIDGE =
"0x5848C791e09901b40A9Ef749f2a6735b418d7564"
let transferCompleted = await
getIsTransferCompletedEth(
EMERALD_TOKEN_BRIDGE,
EmeraldWallet.provider,
vaaBytes
);
while (!transferCompleted) {
await new Promise((r) => setTimeout(r,
5000));
transferCompleted = await
getIsTransferCompletedEth(
EMERALD_TOKEN_BRIDGE,
EmeraldWallet.provider,
vaaBytes
);
}

console.log("VAA Relayed!");

Success! You've programmatically relayed a


transaction!

117 of 132 11/24/22, 17:55


Wormhole Development Book https://book.wormhole.com/print.html

Other Resources
Here is a collection of other resources and
reference sources which you're likely to find
helpful.

• Glossary & Terms


• Tools & Helpful Links
• Contract Addresses & Environment
Information
• RPC Info

118 of 132 11/24/22, 17:55


Wormhole Development Book https://book.wormhole.com/print.html

Glossary
Disclaimer: In some instances, Wormhole uses
general terms for decentralized, cross-chain
elements as branded verbiage. In most casese, the
definition of the general term does not differ from
Wormhole's definition though Wormhole's
definitions may be more narrow than general
interpretations.

Guardian - One of the 19 validators in the


Guardian Network that contributes to the VAA
multisig.

Guardian Network - Validators that exist in their


own p2p network that serve as Wormhole's
oracle by observing activity on-chain and
generating signed messages attesting to that
activity.

Relayer - Any process which delivers VAAs to a


destination.

VAA - Verifiable Action Approvals (VAAs) are the


key piece of data in the Wormhole ecosystem,
containing the messages emitted by xDapps
along with information such as what contract
emitted the message. The VAAs are signed by the
Guardians and need 13/19 signatures to be
considered authentic.

Wormchain - A purpose-built cosmos blockchain


which aids the Guardian Network and allows for
formal interaction with the Guardians.

xAssets - Chain-and-path agnostic token that


exists on a layer outside the blockchain
ecosystem, which can be used to conduct
transactions on any blockchain. There are
currently two implemented modules: (1) Token
Bridge Module and (2) NFT Bridge Module

xChain - Term that refers to the full range of


cross-blockchain interoperability.

119 of 132 11/24/22, 17:55


Wormhole Development Book https://book.wormhole.com/print.html

xDapp - Decentralized application that enables


users to create and/or use xData.

xData - Data that exists in a layer outside of


Layer 1 blockchains, which is accessible by all
chains.

120 of 132 11/24/22, 17:55


Wormhole Development Book https://book.wormhole.com/print.html

Tools and Useful Links


Below are a variety of tools and information in
the Wormhole ecosystem that can help you
develop xDapps.

Design Documents

Wormhole's component design specifications


outline the reasoning behind design decisions
with added technical depth.

Testnet

Wormhole has deployed Core Bridge, Token


Bridge and NFT Bridge contracts on various
testnets of the chains connected by Wormhole.
You can see the deployed addresses here.

Note: There's only a single Guardian that oversees


the testnets, so you might experience a higher rate
of missed VAAs than you would on mainnet.

Testnet Bridge UI

An example UI provided to test out attesting and


bridging tokens on testnet.

Tilt

Tilt is a Kubernetes-based tool that runs a copy


of every chain along side a Guardian node to
create a simulated testing environment. Details
on how to set it up and test against it is here.

Wormhole Core Repository

The Wormhole core repository can be found at

121 of 132 11/24/22, 17:55


Wormhole Development Book https://book.wormhole.com/print.html

https://github.com/wormhole-foundation
/wormhole.

Wormhole Explorer

Tool to observe all Wormhole activity and can


help you parse VAAs after they've been picked up
the Guardian network.

Wormhole SDK

The SDK is a set of Javascript tools to help you do


Token Bridge transfers, plus fetch and submit
VAAs from one chain to another. You can install it
via NPM.

122 of 132 11/24/22, 17:55


Wormhole Development Book https://book.wormhole.com/print.html

Contracts
Here you can find the addresses for the deployed
contracts on all the chains that Wormhole
supports, including testnet.

The constants of the Wormhole SDK always has


the most up-to-date contract addresses, along
with additional useful constants. Check there if
something you're looking for isn't found here.

Mainnet

Core Bridge

Chain Wormhole
Network ID
Name Chain ID
mainnet-
Solana 1
beta
Ethereum 2 1
Terra
3 columbus-5
Classic
Binance
Smart 4 56
Chain
Polygon 5 137
Avalanche
6 43114
(C-Chain)
Oasis
7 4262
(Emerald)
Aurora 9 1313161554
Fantom 10 250
Karura 11 686
Acala 12 787
Klaytn 13 8217
Celo 14 42220

123 of 132 11/24/22, 17:55


Wormhole Development Book https://book.wormhole.com/print.html

Chain Wormhole
Network ID
Name Chain ID
NEAR 15
Moonbeam 16 1284
Terra 18 phoenix-1
Aptos 22

Core Bridge - Read Only

These chains can verify Wormhole messages


submitted to them, but cannot emit messages for
other chains.

Chain Wormhole Network


Address
Name Chain ID ID
Arbitrum 23 42161 0xa5f208
Optimism 24 10 0xEe91C
Gnosis 25 100 0xa32144

Token Bridge

Chain Wormhole
Network ID
Name Chain ID
mainnet-
Solana 1
beta
Ethereum 2 1
Terra 3 columbus-5
Binance
Smart 4 56
Chain
Polygon 5 137
Avalanche
6 43114
(C-Chain)
Oasis
7 4262
(Emerald)
Aurora 9 1313161554
Fantom 10 250
Karura 11 686

124 of 132 11/24/22, 17:55


Wormhole Development Book https://book.wormhole.com/print.html

Chain Wormhole
Network ID
Name Chain ID
Acala 12 787
Klaytn 13 8217
Celo 14 42220
NEAR 15
Moonbeam 16 1284
Terra 18 phoenix-1
Aptos 22

NFT Bridge

Chain Wormhole
Network ID
Name Chain ID
mainnet-
Solana 1
beta
Ethereum 2 1
Binance
Smart 4 56
Chain
Polygon 5 137
Avalanche
6 43114
(C-Chain)
Oasis
7 4262
(Emerald)
Aurora 9 1313161554
Fantom 10 250
Karura 11 686
Acala 12 787
Klaytn 13 8217
Moonbeam 16 1284
Celo 14 42220

Testnet

125 of 132 11/24/22, 17:55


Wormhole Development Book https://book.wormhole.com/print.html

Core Bridge

Chain Wormhole
Network ID
Name Chain ID
Solana 1 devnet
Ethereum
2 5
(Goerli)
Ethereum
10001 3
(Ropsten)
Terra 3 bombay-12
Binance
Smart 4 97
Chain
Polygon
5 80001
(Mumbai)
Avalanche
6 43113
(Fuji)
Oasis
(Emerald 7 42261
Testnet)
Algorand
8
(Testnet)
Aurora 9 1313161555
Fantom 10 4002
Karura 11 686
Acala 12 787
Klaytn 13 1001
Celo 14 44787
NEAR 15
Moonbase
16 1287
alpha
Terra 18 pisco-1
Injective 19 testnet
Aptos 22

Token Bridge

126 of 132 11/24/22, 17:55


Wormhole Development Book https://book.wormhole.com/print.html

Chain Wormhole
Network ID
Name Chain ID
Solana 1 devnet
Ethereum
2 5
(Goerli)
Ethereum
10001 3
(Ropsten)
Terra 3 bombay-12
Binance
Smart 4 97
Chain
Polygon
5 80001
(Mumbai)
Avalanche
6 43113
(Fuji)
Oasis
(Emerald 7 42261
Testnet)
Algorand
8
(Testnet)
Aurora 9 1313161555
Fantom 10 4002
Karura 11 686
Acala 12 787
Klaytn 13 1001
Celo 14 44787
Near 15
Moonbase
16 1287
alpha
Injective 19 testnet
Aptos 22

NFT Bridge

Chain Wormhole
Network ID
Name Chain ID
Solana 1 devnet

127 of 132 11/24/22, 17:55


Wormhole Development Book https://book.wormhole.com/print.html

Chain Wormhole
Network ID
Name Chain ID
Ethereum
2 5
(Goerli)
Ethereum
10001 3
(Ropsten)
Binance
Smart 4 97
Chain
Polygon
5 80001
(Mumbai)
Avalanche
6 43113
(Fuji)
Oasis
(Emerald 7 42261
Testnet)
Aurora 9 1313161555
Fantom 10 4002
Karura 11 686
Acala 12 787
Klaytn 13 1001
Celo 14 44787
Moonbase
16 1287
alpha

Devnet / Tilt

Core Bridge

Wormhole Network
Chain Name
Chain ID ID
Solana 1
Ethereum 2
Terra 3
Binance Smart
4
Chain

128 of 132 11/24/22, 17:55


Wormhole Development Book https://book.wormhole.com/print.html

Wormhole Network
Chain Name
Chain ID ID
Algorand 8
NEAR 15
Terra2 18
Aptos 22
Wormholechain 3104

Token Bridge

Wormhole Network
Chain Name
Chain ID ID
Solana 1
Ethereum 2
Terra 3
Binance Smart
4
Chain
Algorand 8
NEAR 15
Terra2 18
Aptos 22
Wormholechain 3104

NFT Bridge

Chain Wormhole Network


Address
Name Chain ID ID
Solana 1
Ethereum 2 0x26b4a
Terra 3 terra1plj
Binance
Smart 4 0x26b4a
Chain

129 of 132 11/24/22, 17:55


Wormhole Development Book https://book.wormhole.com/print.html

Blockchain Finality
Recommendations
The goal of Wormhole is to provide high
confidence that only finalized messages are
observed and attested. Different chains use
different consensus mechanisms and so there
are different finality assumptions with each one.

Below is a table of suggested finality


recommendations for each of the chains
supported by the Wormhole ecosystem to have
the highest confidence of finality.

However, these are just suggestions and


developers are free to define their own finality
windows for their applications. Ultimately, the
tradeoff is between speed and security.

Suggested
Chain Wormhole Number of
Name Chain ID Block
Confirmations
Solana 1 32
Ethereum 2 15
Terra
3 Instant
Classic
Binance
Smart 4 15
Chain
Polygon 5 512
Avalanche
6 1
(C-Chain)
Oasis
7 1
(Emerald)
Aurora 9 1
Fantom 10 1
Karura 11 1
Acala 12 1
Klaytn 13 1

130 of 132 11/24/22, 17:55


Wormhole Development Book https://book.wormhole.com/print.html

Suggested
Chain Wormhole Number of
Name Chain ID Block
Confirmations
Celo 14 1
Terra 18 Instant

131 of 132 11/24/22, 17:55


Wormhole Development Book https://book.wormhole.com/print.html

RPC Nodes
These RPC nodes are maintained by the
Guardians to help fetch VAAs and query the
Wormhole network.

Mainnet Guardian RPC

https://wormhole-v2-mainnet-api.certus.one
https://wormhole.inotel.ro
https://wormhole-v2-mainnet-api.mcf.rocks
https://wormhole-v2-mainnet-
api.chainlayer.network
https://wormhole-v2-mainnet-
api.staking.fund
https://wormhole-v2-mainnet.01node.com

Testnet Guardian RPC

https://wormhole-v2-testnet-api.certus.one

Testnet Guardian Public Key

0x13947Bd48b18E53fdAeEe77F3473391aC727C638

132 of 132 11/24/22, 17:55

You might also like