How Do Cross-Chain Bridges Work?
A Case on Wormhole (Part 1)
January 9, 2023

It might be a bit surprising to our readers that crypto hacks caused over $3 billion lost of funds in 2022. However, a majority of the lost was on cross-chain bridges (e.g., Ronin Network, Wormhole, Nomad, BNB Token Hub, Horizon, Qubit).

Why are cross-chain bridges so vulnerable? Are they not designed or implemented carefully? On the contrary, due to their high value they are developed with the highest possible standards by some of the best engineers (e.g., leoluk). The real reason is that cross-chain bridges are just too complex to get right, involving too many technical subtleties.

In this article series, we will elaborate the internals of cross-chain bridges, how they are implemented and what their caveats are from the user’s perspective. We will use a state-of-the-art bridge Wormhole as an example.

At a High Level, What’s a Cross-Chain Bridge?

A cross-chain bridge is just a (virtual) link between two blockchains for message communication. The message can essentially be any bit sequence (such as transferring a token or an NFT from Chain A to Chain B).

Suppose you want to transfer a bitcoin from Ethereum to Solana, you need to do at least two operations:

  1. Debit a bitcoin from a source account on Ethereum
  2. Credit a bitcoin to a target account on Solana

However, because these two chains do not directly communicate (in a technical term: there is no way to touch both chains in a single transaction), you need a man-in-the-middle who owns bitcoins on both chains and who can help you with two steps:

  1. Receive a bitcoin from your source account to their account on Ethereum
  2. Send a bitcoin (or an equivalent) to your target account from their account on Solana

A cross-chain bridge is such a man-in-the-middle. There are several challenges here:

  • How does a bridge ensure that these two steps happen atomically (i.e., either they both succeed or they both fail)? If any one of them succeeds but the other fails, then either you or the bridge will lose money.
  • How does a bridge ensure that the same message is delivered (i.e., only one bitcoin, not one Dogecoin, or any other coin, or two bitcoins, and to your target account, not to anyone else’s account)?
  • How does a bridge ensure that the same message is delivered exactly once (e.g., their account on Solana will never double-send to your target account)?

Web3 researchers have developed multiple different solutions to address these challenges (with different trade-offs). For example, multi-sig validators, multi-party computation (MPC), rollup and optimistic bridges, etc. See the Interoperability Trilemma for a nice summary.

We will focus on explaining a representative solution based on guardians (i.e., a type of multi-sig validators) used by Wormhole.

At a High Level, How Does Wormhole Work?

As of Jan 2023, Wormhole bridges 20 different chains including Ethereum, Solana, Binance Smart Chain, Polygon, Aptos, and so on.

It achieves this by operating a network of 19 nodes called guardians (see all the 19 guardian addresses), and a number of smart contracts deployed on each chain (including a core bridge contract, a token bridge contract and an NFT bridge contract). The core bridge contract provides functions for emitting messages, verifying guardian signatures, and so on. The token and NFT bridge contracts are responsible for transferring tokens and NFT, respectively.

The 19 guardians each observe messages emitted by the Wormhole core bridge contracts continuously, and sign on the messages (e.g., a message like “Alice just sent a bitcoin to Wormhole on Ethereum, and she wanted Wormhole to send a bitcoin to Bob on Solana).

The guardians each hold equal weight. When a super-majority (2/3) of them sign a message, the guardian network produces a Validator Action Approval (VAA), which serves as a proof for Wormhole to deliver the same message on the target chain (e.g., send a bitcoin to Bob on Solana).

VAA: A Core Technical Component of Wormhole

VAAs are at the heart of all Wormhole technical details. There are a number of questions on VAAs that keen readers may wonder:

  • What information does a VAA contain? What exactly is the format of VAA?
  • How are the VAAs used? Where are they stored? How to get them?
  • What’s the end-to-end workflow of a cross-chain message from a user’s perspective? How many transactions are needed to complete a message (i.e., from sending on the source chain to receiving on the target chain)?
  • How are the guardian signatures verified (to prevent fake VAAs)? What if a (malicious) guardian signs the same message multiple times and produces multiple signatures?
  • How to ensure the tokens are the same (or equivalent) on the bridged two chains? What if Wormhole does not have the same token (or enough amount) on the target chain as the user sent on the source token?
  • Who will perform the message delivery steps on the target chain (since it requires paying transaction fees)?
  • How to prevent the same VAA used twice on the target chain?

Next, we will answer these questions one by one (with code examples whenever necessary).

The VAA Format and Internals

Each VAA is encoded as a byte array with two parts - a header and a body.

  • Header. The header contains information about the guardians and their signatures:
Type Field Description
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
  • Body. The body contains detailed information about the message (e.g., timestamp of the source transaction, emitter_chain, emitter_address, sequence, and the message payload):
Type Field Description
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 and chain
u8 consistency_level What finality level was reached before emitting this message
[]byte payload VAA message content

In particular, sequence is an important piece of information to ensure that each VAA is unique for a message (i.e., any two different messages would have different VAAs even if they have the same message content).

The sequence number is incremented by 1 in the useSequence function for every publishMessage call:

This is critical to guarantee the same message will never be delivered twice. We will elaborate this point further in the next section.

The payload byte array contains the message content. For example, for a token Transfer, it includes the transfer amount, token address, token chain, the recipient address, the target chain ID, transfer fee, etc:

How Are the VAAs Used? Where Are They Stored?

Once a VAA is produced (i.e., a message that has been signed by 2/3 guardians), it will be stored in the guardian network (likely for a long time or even permanently).

Each VAA is uniquely indexed by its emitterChain, emittedAddress and sequence, and can be obtained by querying a guardian node (via an RPC API) with this information:

For example, an RPC query with

returns the following VAA bytes:

corresponding to a transfer of 0.1 WETH from Ethereum to Solana ($128.15):

Figure 1. a token transfer of 0.1 WETH from Ethereum to Solana, see the Wormhole transaction

The End-To-End Workflow of a Cross-Chain Message

Anyone can query a guardian node, and the returned VAA bytes can be submitted by anyone to the target chain to complete the message (e.g., mint a bitcoin to the recipient address encoded in the VAA).

Consider the message in Figure 1 “a token transfer of 0.1 WETH from Ethereum to Solana”. From the user’s perspective, there are actually five on-chain transactions involved (one on Ethereum and four on Solana) in the following order:

Tx1 (0x6539) wrapAndTransferETH on Ethereum

The user 0x4f98 sends 0.1 WETH to the Wormhole Token Bridge 0x3ee1 by calling wrapAndTransferETH with parameters specifying the recipient chain (Solana 0x01), recipient (0xfdca, base58 encode as 7vfC on Solana), arbiterFee (i.e., the relayer fee if used) and nonce:

Tx1 0x6539 wrapAndTransferETH on Ethereum

Tx1 invokes Wormhole Core Bridge 0x98f3 internally and emits a message containing sequence, nonce, payload and consistencyLevel as below:

The guardians observe the message shown above and produce a VAA (AQAA…) as shown in Figure 1.

Next, the VAA is retrieved from the guardian network and used to call Wormhole core bridge contract on Solana

Tx2 (5CVY) and Tx3 (46tG) VerifySignatures on Solana

The VerifySignatures function on the Solana Wormhole core bridge is invoked by a signer HZBb with the VAA to create a SignatureSet 58Ui:

This transaction also invokes the precompiled Secp256k1 SigVerify program to verify the guardian signatures in the VAA

The VAA contains 13 signatures in total. Due to the compute limit on Solana, Wormhole splits verifying these signatures into two transactions.

  • Tx2 (5CVY) verifies seven signatures:
  • Tx3 (46tG): update SignatureSet 58Ui by verifying the other six signatures:

Tx4 (5AoD) PostVAA on Solana

After all signatures in the VAA are verified, the PostVAA function can be invoked to create a message account 31Np, which uniquely identifies transferred message:

Two other transactions 3goi and ZpYN also invoke PostVAA successfully, however, because the message account is a PDA, it is only initialized once by Tx4 (5AoD)

The 2/3 quorum is checked in the PostVAA function:

Tx5 (4p4q) CompleteWrapped on Solana

Finally, the CompleteWrapped function on the Wormhole Token Bridge (wormDTUJ) is invoked to complete the transfer.

The recipient 0xfdca to receive the corresponding WETH token (ETH — Ether (Portal) 7vfC) is actually an associated token account (PDA) on Solana owned by 4Kt8. If the recipient does not exist yet, then it has to be created because Tx5 can be executed. The account 0xfdca was created in Tx sSjG on Solana.

How Are the Guardian Signatures Verified (To Prevent Fake VAAs)?

Verifying the guardian signatures is absolutely critical for the security of any cross-chain bridges and not surprisingly it is a complex task. We will elaborate in Part 2.

Who Performs the Downstream Transactions on the Target Chain?

Anyone can retrieve VAAs and perform the downstream transactions. It would be straightforward for the message sender to do so (e.g., the users who initiate the token transfer on the source chain). However, what if a user does not have an account on the target chain or a user has insufficient balances to pay for the transaction fees?

To address this issue, Wormhole allows bridgerelayers to deliver the messages and earn fees. The fee can be specified in the source tranaction, and is encoded into the VAA payload:

How to Ensure the Bridged Token and Amount Are Correct?

The transferred token on the target chain must be the same or equivalent to the token transferred on the source chain. For example, either both are USDC, or one is Wrapped Ether (WETH) on Ethereum and the other is ETH — Ether (Portal) on Solana. But it could not be WETH on Ethereum and USDC on Solana. We will discuss this part in Part 3.

How to Prevent Double-Delivery of the Same Message (VAA Replay)?

This is a subtle point and entails a careful design on the target chain. Essentially, a global state is required to flag each delivered message and reject transactions that attempt to re-deliver the same message. We will explain this part further in Part 4.

About sec3 (Formerly Soteria)

sec3 is a security research firm that prepares Solana projects for millions of users. sec3’s Launch Audit is a rigorous, researcher-led code examination that investigates and certifies mainnet-grade smart contracts; sec3’s continuous auditing software platform, X-ray, integrates with Github to progressively scan pull requests, helping projects fortify code before deployment; and sec3’s post-deployment security solution, WatchTower, ensures funds stay safe. sec3 is building technology-based scalable solutions for Web3 projects to ensure protocols stay safe as they scale.

To learn more about sec3, please visit