---
category: Connect
includes_base_categories: true
base_categories:
- basics
- reference
word_count: 80907
token_estimate: 170745
page_count: 43
---

# Begin New Bundle: Connect
Includes shared base categories: basics, reference


---

Page Title: Architecture

- Resolved Markdown: https://wormhole.com/docs/ai/pages/protocol-architecture.md
- Canonical (HTML): https://wormhole.com/docs/protocol/architecture/
- Summary: Overview of Wormhole's architecture, detailing key on-chain and off-chain components like the Core Contract, Guardian Network, and relayers.
- Word Count: 721; Token Estimate: 1127

# Architecture

Wormhole has several noteworthy components. Before discussing each component in depth, this page will provide an overview of how the major pieces fit together.

![Wormhole architecture detailed diagram: source to target chain communication.](/docs/images/protocol/architecture/architecture-1.webp)

The preceding diagram outlines the end-to-end flow of multichain communication through Wormhole's architecture, which is described as follows:

1. **Source chain**: A source contract emits a message by interacting with the [Wormhole Core Contract](/docs/protocol/infrastructure/core-contracts/){target=\_blank} on the source chain, which publishes the message in the blockchain's transaction logs.
2. **Guardian Network**: [Guardians](/docs/protocol/infrastructure/guardians/){target=\_blank} validate these messages and sign them to produce [Verifiable Action Approvals (VAAs)](/docs/protocol/infrastructure/vaas/){target=\_blank}. For delegated chains, a delegated subset performs direct observation while Canonical Guardians wait for delegate quorum before signing. The final VAA remains a standard 13-of-19 multisignature attestation.
3. **Relayers**: Off-chain relayers or applications fetch the VAA and relay it to the target chain. Relayers act as the transport layer of the Wormhole network, responsible for carrying signed messages between chains. In Wormhole’s protocol, this role is fulfilled by the [Executor](/docs/protocol/infrastructure/relayers/executor-framework/){target=\_blank}, a shared, permissionless framework for message delivery. The Executor enables anyone to act as a delivery provider through an open request-and-quote model, removing the need for centralized relayer services.

4. **Target chain**: On the target chain, the message is consumed by the appropriate contract. This contract interacts with the Wormhole Core Contract to verify the VAA and execute the intended multichain operation.

    The flow from the relayer to the target chain involves an entry point contract, which could vary based on the use case:

    - In some applications, the target contract acts as the entry point and performs verification via the Core Contract.
    - In products like Wrapped Token Transfers (WTT), the WTT contract itself interacts with the Core Contract.

## On-Chain Components

- **Emitter**: A contract that calls the publish message method on the Core Contract. To identify the message, the Core Contract will write an event to the transaction logs with details about the emitter and sequence number. This may be your cross-chain dApp or an existing ecosystem protocol.
- **[Wormhole Core Contract](/docs/protocol/infrastructure/core-contracts/){target=\_blank}**: Primary contract, this is the contract which the Guardians observe and which fundamentally allows for multichain communication.
- **Transaction logs**: Blockchain-specific logs that allow the Guardians to observe messages emitted by the Core Contract.

## Off-Chain Components

- **Guardian Network**: Validators that exist in their own P2P network. Guardians observe and validate messages emitted by the Core Contract to produce VAAs. For full Guardian Set chains, all Guardians perform direct on-chain observation. For delegated chains, a delegated subset performs observation and broadcasts signed delegate observations to the rest of the network, after which Canonical Guardians wait for delegate quorum before signing.
- **[Guardian](/docs/protocol/infrastructure/guardians/){target=\_blank}**: One of 19 validators in the Guardian Network that contributes to the VAA multisig.
- **[Spy](/docs/protocol/infrastructure/spy/){target=\_blank}**: A daemon that subscribes to messages published within the Guardian Network. A Spy can observe and forward network traffic, which helps scale up VAA distribution.
- **[API](https://docs.wormholescan.io/){target=\_blank}**: A REST server to retrieve details for a VAA or the Guardian Network.
- **[VAAs](/docs/protocol/infrastructure/vaas/){target=\_blank}**: Verifiable Action Approvals (VAAs) are the signed attestation of an observed message from the Wormhole Core Contract.
- **[Relayer](/docs/protocol/infrastructure/relayers/relayer/){target=\_blank}**: Any off-chain process that relays a VAA to the target chain. Wormhole provides the [Executor framework](/docs/protocol/infrastructure/relayers/executor-framework/){target=\_blank}, a shared execution framework. This framework enables permissionless message delivery through an open marketplace where relay providers compete using a request-and-quote model.

## Next Steps

<div class="grid cards" markdown>

-   :octicons-book-16:{ .lg .middle } **Core Contracts**

    ---

    Discover Wormhole's Core Contracts, enabling multichain communication with message sending, receiving, and multicast features for efficient synchronization.

    [:custom-arrow: Explore Core Contracts](/docs/protocol/infrastructure/core-contracts/)

-   :octicons-tools-16:{ .lg .middle } **Wormhole Dev Arena**

    ---

    A structured learning hub with hands-on tutorials across the Wormhole ecosystem.

    [:custom-arrow: Explore the Dev Arena](https://arena.wormhole.com/ecosystem){target=\_blank}

</div>


---

Page Title: Chain IDs

- Resolved Markdown: https://wormhole.com/docs/ai/pages/products-reference-chain-ids.md
- Canonical (HTML): https://wormhole.com/docs/products/reference/chain-ids/
- Summary: This page documents the Wormhole-specific chain IDs for each chain and contrasts them to the more commonly referenced EVM chain IDs originating in EIP-155.
- Word Count: 2000; Token Estimate: 5559

# Chain IDs

The following table documents the chain IDs used by Wormhole and places them alongside the more commonly referenced [EVM Chain IDs](https://chainlist.org/){target=\_blank}.

!!! note
    Please note, Wormhole chain IDs are different than the more commonly referenced [EVM chain IDs](https://chainlist.org/){target=\_blank}, specified in the Mainnet and Testnet ID columns.

!!!warning
    Wormhole Contributors recommend that all connected chains implement robust security practices including (but not exclusively): open sourcing code and running public bug bounty programs, undergoing security audits and publishing those reports, using version control with adequate access controls and mandatory code review, and high unit and integration test coverage where the results of those tests are available publicly. Connected chains that can't verifiably prove that they've implemented a high percentage of these practices may be noted below with the :warning: symbol. 
    
    Wormhole integrators are encouraged to understand the security assumptions of any chain before trusting messages from it. See the recommended security practices for chains in [Wormhole's security program](https://github.com/wormhole-foundation/wormhole/blob/main/SECURITY.md#chain-integrators){target=\_blank}.



=== "Mainnet"

    <table data-full-width="true" markdown><thead><th>Chain Name</th><th style="width:26%">Wormhole Chain ID</th><th>Network ID</th></thead><tbody><tr><td>Ethereum</td><td><code>2</code></td><td><code>1</code></td></tr><tr><td>Solana</td><td><code>1</code></td><td><code>Mainnet Beta</code> - <code>5eykt4UsFv8P8NJdTREpY1vzqKqZKvdpKuc147dw2N9d</code></td></tr><tr><td>0G (Zero Gravity)</td><td><code>67</code></td><td><code>16661</code></td></tr><tr><td>Algorand</td><td><code>8</code></td><td><code>mainnet-v1.0</code></td></tr><tr><td>Aptos</td><td><code>22</code></td><td><code>1</code></td></tr><tr><td>Arbitrum</td><td><code>23</code></td><td><code>Arbitrum One</code> - <code>42161</code></td></tr><tr><td>Avalanche</td><td><code>6</code></td><td><code>C-Chain</code> - <code>43114</code></td></tr><tr><td>Base</td><td><code>30</code></td><td><code>Base</code> - <code>8453</code></td></tr><tr><td>Berachain</td><td><code>39</code></td><td></td></tr><tr><td>BNB Smart Chain</td><td><code>4</code></td><td><code>56</code></td></tr><tr><td>Celestia</td><td><code>4004</code></td><td><code>celestia</code></td></tr><tr><td>Celo</td><td><code>14</code></td><td><code>42220</code></td></tr><tr><td>Converge</td><td><code>53</code></td><td></td></tr><tr><td>Cosmos Hub</td><td><code>4000</code></td><td><code>cosmoshub-4</code></td></tr><tr><td>CreditCoin</td><td><code>59</code></td><td></td></tr><tr><td>Dymension</td><td><code>4007</code></td><td><code>dymension_1100-1</code></td></tr><tr><td>Evmos</td><td><code>4001</code></td><td><code>evmos_9001-2</code></td></tr><tr><td>Fantom</td><td><code>10</code></td><td><code>250</code></td></tr><tr><td>Fogo</td><td><code>51</code></td><td></td></tr><tr><td>HyperCore</td><td><code>65000</code></td><td><code>20000</code></td></tr><tr><td>HyperEVM :material-alert:{ title='⚠️ The HyperEVM integration is experimental, as its node software is not open source. Use Wormhole messaging on HyperEVM with caution.' }</td><td><code>47</code></td><td></td></tr><tr><td>Injective</td><td><code>19</code></td><td><code>injective-1</code></td></tr><tr><td>Ink</td><td><code>46</code></td><td></td></tr><tr><td>Kaia</td><td><code>13</code></td><td><code>8217</code></td></tr><tr><td>Kujira</td><td><code>4002</code></td><td><code>kaiyo-1</code></td></tr><tr><td>Linea</td><td><code>38</code></td><td><code>59144</code></td></tr><tr><td>Mantle</td><td><code>35</code></td><td><code>5000</code></td></tr><tr><td>MegaETH</td><td><code>64</code></td><td><code>4326</code></td></tr><tr><td>Mezo</td><td><code>50</code></td><td></td></tr><tr><td>Moca</td><td><code>63</code></td><td><code>2288</code></td></tr><tr><td>Monad</td><td><code>48</code></td><td></td></tr><tr><td>Moonbeam</td><td><code>16</code></td><td><code>1284</code></td></tr><tr><td>NEAR</td><td><code>15</code></td><td><code>mainnet</code></td></tr><tr><td>Neutron</td><td><code>4003</code></td><td><code>neutron-1</code></td></tr><tr><td>Noble</td><td><code>4009</code></td><td><code>noble-1</code></td></tr><tr><td>Optimism</td><td><code>24</code></td><td><code>10</code></td></tr><tr><td>Osmosis</td><td><code>20</code></td><td><code>osmosis-1</code></td></tr><tr><td>Plasma</td><td><code>58</code></td><td></td></tr><tr><td>Plume</td><td><code>55</code></td><td><code>98866</code></td></tr><tr><td>Polygon</td><td><code>5</code></td><td><code>137</code></td></tr><tr><td>Provenance</td><td><code>4008</code></td><td><code>pio-mainnet-1</code></td></tr><tr><td>Pythnet</td><td><code>26</code></td><td></td></tr><tr><td>Scroll</td><td><code>34</code></td><td><code>534352</code></td></tr><tr><td>SEDA</td><td><code>4006</code></td><td></td></tr><tr><td>Sei</td><td><code>32</code></td><td><code>pacific-1</code></td></tr><tr><td>SeiEVM</td><td><code>40</code></td><td></td></tr><tr><td>Sonic</td><td><code>52</code></td><td><code>146</code></td></tr><tr><td>Stacks</td><td><code>60</code></td><td><code>1</code></td></tr><tr><td>Stargaze</td><td><code>4005</code></td><td><code>stargaze-1</code></td></tr><tr><td>Sui</td><td><code>21</code></td><td><code>35834a8a</code></td></tr><tr><td>Unichain</td><td><code>44</code></td><td><code></code></td></tr><tr><td>World Chain</td><td><code>45</code></td><td><code>480</code></td></tr><tr><td>X Layer</td><td><code>37</code></td><td><code>196</code></td></tr><tr><td>Xrpl</td><td><code>66</code></td><td></td></tr><tr><td>XRPL-EVM</td><td><code>57</code></td><td><code>1440000</code></td></tr></tbody></table>

=== "Testnet"

    <table data-full-width="true" markdown><thead><th>Chain Name</th><th style="width:26%">Wormhole Chain ID</th><th>Network ID</th></thead><tbody><tr><td>Ethereum Holesky</td><td><code>10006</code></td><td><code>Holesky</code> - <code>17000</code></td></tr><tr><td>Ethereum Sepolia</td><td><code>10002</code></td><td><code>Sepolia</code> - <code>11155111</code></td></tr><tr><td>Solana</td><td><code>1</code></td><td><code>Devnet</code> - <code>EtWTRABZaYq6iMfeYKouRu166VU2xqa1wcaWoxPkrZBG</code></td></tr><tr><td>0G (Zero Gravity)</td><td><code>67</code></td><td><code>16602</code></td></tr><tr><td>Algorand</td><td><code>8</code></td><td><code>testnet-v1.0</code></td></tr><tr><td>Aptos</td><td><code>22</code></td><td><code>2</code></td></tr><tr><td>Arbitrum Sepolia</td><td><code>10003</code></td><td><code>Sepolia</code> - <code>421614</code></td></tr><tr><td>Avalanche</td><td><code>6</code></td><td><code>Fuji</code> - <code>43113</code></td></tr><tr><td>Base Sepolia</td><td><code>10004</code></td><td><code>Base Sepolia</code> - <code>84532</code></td></tr><tr><td>Berachain</td><td><code>39</code></td><td><code>80084</code></td></tr><tr><td>BNB Smart Chain</td><td><code>4</code></td><td><code>97</code></td></tr><tr><td>Celestia</td><td><code>4004</code></td><td><code>mocha-4</code></td></tr><tr><td>Celo</td><td><code>14</code></td><td><code>Alfajores</code> - <code>44787</code></td></tr><tr><td>Converge</td><td><code>53</code></td><td><code>52085145</code></td></tr><tr><td>Cosmos Hub</td><td><code>4000</code></td><td><code>theta-testnet-001</code></td></tr><tr><td>CreditCoin</td><td><code>59</code></td><td></td></tr><tr><td>Dymension</td><td><code>4007</code></td><td></td></tr><tr><td>Evmos</td><td><code>4001</code></td><td><code>evmos_9000-4</code></td></tr><tr><td>Fantom</td><td><code>10</code></td><td><code>4002</code></td></tr><tr><td>Fogo</td><td><code>51</code></td><td><code>9GGSFo95raqzZxWqKM5tGYvJp5iv4Dm565S4r8h5PEu9</code></td></tr><tr><td>HyperCore</td><td><code>65000</code></td><td><code>20000</code></td></tr><tr><td>HyperEVM :material-alert:{ title='⚠️ The HyperEVM integration is experimental, as its node software is not open source. Use Wormhole messaging on HyperEVM with caution.' }</td><td><code>47</code></td><td><code>998</code></td></tr><tr><td>Injective</td><td><code>19</code></td><td><code>injective-888</code></td></tr><tr><td>Ink</td><td><code>46</code></td><td><code>763373</code></td></tr><tr><td>Kaia</td><td><code>13</code></td><td><code>Kairos</code> - <code>1001</code></td></tr><tr><td>Kujira</td><td><code>4002</code></td><td><code>harpoon-4</code></td></tr><tr><td>Linea</td><td><code>38</code></td><td><code>59141</code></td></tr><tr><td>Mantle</td><td><code>35</code></td><td><code>Sepolia</code> - <code>5003</code></td></tr><tr><td>MegaETH</td><td><code>64</code></td><td><code>6343</code></td></tr><tr><td>Mezo</td><td><code>50</code></td><td><code>31611</code></td></tr><tr><td>Moca</td><td><code>63</code></td><td><code>222888</code></td></tr><tr><td>Monad Testnet</td><td><code>10009</code></td><td><code>10143</code></td></tr><tr><td>Moonbeam</td><td><code>16</code></td><td><code>Moonbase-Alphanet</code> - <code>1287</code></td></tr><tr><td>NEAR</td><td><code>15</code></td><td><code>testnet</code></td></tr><tr><td>Neutron</td><td><code>4003</code></td><td><code>pion-1</code></td></tr><tr><td>Noble</td><td><code>4009</code></td><td><code>grand-1</code></td></tr><tr><td>Optimism Sepolia</td><td><code>10005</code></td><td><code>Optimism Sepolia</code> - <code>11155420</code></td></tr><tr><td>Osmosis</td><td><code>20</code></td><td><code>osmo-test-5</code></td></tr><tr><td>Plasma</td><td><code>58</code></td><td></td></tr><tr><td>Plume</td><td><code>55</code></td><td><code>98867</code></td></tr><tr><td>Polygon Amoy</td><td><code>10007</code></td><td><code>Amoy</code> - <code>80002</code></td></tr><tr><td>Provenance</td><td><code>4008</code></td><td></td></tr><tr><td>Pythnet</td><td><code>26</code></td><td></td></tr><tr><td>Scroll</td><td><code>34</code></td><td><code>Sepolia</code> - <code>534351</code></td></tr><tr><td>SEDA</td><td><code>4006</code></td><td><code>seda-1-testnet</code></td></tr><tr><td>Sei</td><td><code>32</code></td><td><code>atlantic-2</code></td></tr><tr><td>SeiEVM</td><td><code>40</code></td><td></td></tr><tr><td>Sonic</td><td><code>52</code></td><td><code>57054</code></td></tr><tr><td>Stacks</td><td><code>60</code></td><td><code>2147483648</code></td></tr><tr><td>Stargaze</td><td><code>4005</code></td><td></td></tr><tr><td>Sui</td><td><code>21</code></td><td><code>4c78adac</code></td></tr><tr><td>Unichain</td><td><code>44</code></td><td><code>Unichain Sepolia</code> - <code>1301</code></td></tr><tr><td>World Chain</td><td><code>45</code></td><td><code>4801</code></td></tr><tr><td>X Layer</td><td><code>37</code></td><td><code>195</code></td></tr><tr><td>Xrpl</td><td><code>66</code></td><td></td></tr><tr><td>XRPL-EVM</td><td><code>57</code></td><td><code>1449000</code></td></tr></tbody></table>


---

Page Title: Compare Wormhole's Cross-Chain Solutions

- Resolved Markdown: https://wormhole.com/docs/ai/pages/products-overview.md
- Canonical (HTML): https://wormhole.com/docs/products/overview/
- Summary: Compare Wormhole’s cross-chain solutions for bridging, native transfers, data queries, and governance to enable seamless blockchain interoperability.
- Word Count: 431; Token Estimate: 907

# Products 

Wormhole provides a comprehensive suite of cross-chain solutions, enabling seamless asset transfers, data retrieval, and governance across blockchain ecosystems.

Wormhole provides multiple options for asset transfers: Connect for a plug-and-play bridging UI, Native Token Transfers (NTT) for moving native assets without wrapped representations, and Wrapped Token Transfers (WTT) for a secure lock-and-mint mechanism.

Beyond transfers, Wormhole extends interoperability with tools for cross-chain data access, decentralized governance, and an intent-based protocol through Wormhole Settlement.

## Transfer Products

Wormhole offers different solutions for cross-chain asset transfer, each designed for various use cases and integration requirements.

- **[Native Token Transfers (NTT)](/docs/products/token-transfers/native-token-transfers/overview/){target=\_blank}**: A mechanism to transfer native tokens cross-chain seamlessly without conversion to a wrapped asset. Best for projects that require maintaining token fungibility and native chain functionality across multiple networks.
- **[Wrapped Token Transfers (WTT)](/docs/products/token-transfers/wrapped-token-transfers/overview/){target=\_blank}**: A bridging solution that uses a lock and mint mechanism. Best for projects that need cross-chain liquidity using wrapped assets and the ability to send messages.
- **[Settlement](/docs/products/settlement/overview/){target=\_blank}**: Intent-based protocols enabling fast multichain transfers, optimized liquidity flows, and interoperability without relying on traditional bridging methods.

<div markdown class="full-width">

::spantable::

|                                | Criteria                              | NTT                | WTT                | Settlement         |
|--------------------------------|---------------------------------------|--------------------|--------------------|--------------------|
| Supported Transfer Types @span | Token Transfers                       | :white_check_mark: | :white_check_mark: | :white_check_mark: |
|                                | Token Transfers with Payloads         | :white_check_mark: | :white_check_mark: | :white_check_mark: |
| Supported Assets @span         | Wrapped Assets                        | :x:                | :white_check_mark: | :white_check_mark: |
|                                | Native Assets                         | :white_check_mark: | :x:                | :white_check_mark: |
| Features @span                 | Out-of-the-Box UI                     | :x:                | :x:                | :white_check_mark: |
|                                | Event-Based Actions                   | :white_check_mark: | :white_check_mark: | :x:                |
|                                | Intent-Based Execution                | :x:                | :x:                | :white_check_mark: |
|                                | Fast Settlement                       | :x:                | :x:                | :white_check_mark: |
| Requirements @span             | Contract Deployment                   | :white_check_mark: | :x:                |:x:                 |

::end-spantable::

</div>

For a deeper dive into how token transfers work and the differences between NTT and WTT, see the [Token Transfers Overview](/docs/products/token-transfers/overview/){target=\_blank}.

Beyond asset transfers, Wormhole provides additional tools for cross-chain data and governance.

## Bridging UI

[**Connect**](/docs/products/connect/overview/){target=\_blank} is a pre-built bridging UI for cross-chain token transfers, requiring minimal setup. Best for projects seeking an easy-to-integrate UI for bridging without modifying contracts.

## Real-time Data

[**Queries**](/docs/products/queries/overview/){target=\_blank} is a data retrieval service to fetch on-chain data from multiple networks. Best for applications that need multichain analytics, reporting and data aggregation.

## Multichain Governance

[**MultiGov**](/docs/products/multigov/overview/){target=\_blank} is a unified governance framework that manages multichain protocol governance through a single mechanism. Best for projects managing multichain governance and protocol updates.


---

Page Title: Connect Data Configuration

- Resolved Markdown: https://wormhole.com/docs/ai/pages/products-connect-configuration-data.md
- Canonical (HTML): https://wormhole.com/docs/products/connect/configuration/data/
- Summary: Configure Wormhole Connect v1 (latest) with custom chains, tokens, routes, and more for enhanced blockchain interoperability.
- Word Count: 2079; Token Estimate: 4229

## Data Configuration

This page explains how to configure Wormhole Connect's core functionality, from choosing supported chains and tokens to bridging routes to setting up wallets and enabling price lookups. By the end, you'll know how to specify custom networks and RPC endpoints, integrate different bridging protocols, add new tokens, and more.

## Get Started

Configure Wormhole Connect by passing a `WormholeConnectConfig` object as the `config` prop.

=== "React integration"

    ```ts
    import WormholeConnect, {
      type config,
    } from '@wormhole-foundation/wormhole-connect';

    const config: config.WormholeConnectConfig = {
      chains: ['Ethereum', 'Polygon', 'Solana'],
      tokens: ['ETH', 'WETH', 'MATIC', 'WMATIC'],
      rpcs: {
        Ethereum: 'https://rpc.ankr.com/eth',
        Solana: 'https://rpc.ankr.com/solana',
      }
    }

    <WormholeConnect config={config} />
    ```

=== "Hosted integration"

    ```ts
    import WormholeConnect, { wormholeConnectHosted, type config } from '@wormhole-foundation/wormhole-connect';

    const config: config.WormholeConnectConfig = {
      chains: ['Ethereum', 'Polygon', 'Solana'],
      tokens: ['ETH', 'WETH', 'MATIC', 'WMATIC'],
      rpcs: {
        Ethereum: 'https://rpc.ankr.com/eth',
        Solana: 'https://rpc.ankr.com/solana',
      },
    };

    const container = document.getElementById('bridge-container');

    wormholeConnectHosted(container, {
      config,
    });
    ```

!!! note
    The complete type definition of `WormholeConnectConfig` is available in the [Wormhole Connect repository](https://github.com/wormhole-foundation/wormhole-connect/blob/production%403.0.0/wormhole-connect/src/config/types.ts#L96){target=\_blank}.

## Examples {: #examples }

### Configuring Chains and RPC Endpoints {: #chains-and-rpc-endpoints }

Connect lets you customize the available chains to match your project's needs. You should provide your own RPC endpoints, as the default public ones may not support essential functions like balance fetching.

=== "Mainnet"

    ```js
    import WormholeConnect, { type config } from '@wormhole-foundation/wormhole-connect';

    const config: config.WormholeConnectConfig = {
      chains: ['Ethereum', 'Polygon', 'Solana'],
      rpcs: {
        Ethereum: 'https://rpc.ankr.com/eth',
        Solana: 'https://rpc.ankr.com/solana',
      },
    };

    function App() {
      return <WormholeConnect config={config} />;
    }
    ```

=== "Testnet"

    ```js
    import WormholeConnect, { type config } from '@wormhole-foundation/wormhole-connect';

    const config: config.WormholeConnectConfig = {
      // You can use Connect with testnet chains by specifying "network":
      network: 'Testnet',
      chains: ['Sepolia', 'ArbitrumSepolia', 'BaseSepolia', 'Avalanche'],
      rpcs: {
        Avalanche: 'https://rpc.ankr.com/avalanche_fuji',
        BaseSepolia: 'https://base-sepolia-rpc.publicnode.com',
      },
    };

    function App() {
      return <WormholeConnect config={config} />;
    }
    ```

!!! note
    For a complete list of available chain names, see the [Wormhole TypeScript SDK](https://github.com/wormhole-foundation/wormhole-sdk-ts/blob/main/core/base/src/constants/chains.ts){target=\_blank}.

### Configuring Routes

By default, Connect offers two bridging protocols: Wrapped Token Transfers (WTT) and Circle's CCTP (for native USDC). For most use cases, integrators require more than these default routes. The `routes` property allows you to specify which protocols to include and exclude any routes unnecessary for your application, including default and third-party routes.

!!! note "Terminology"
    The SDK and smart contracts use the name Token Bridge. In documentation, this product is referred to as Wrapped Token Transfers (WTT). Both terms describe the same protocol.

#### Available Route Plugins

The `@wormhole-foundation/wormhole-connect` package offers a variety of `route` plugins to give you flexibility in handling different protocols. You can choose from the following `route` exports for your integration:

- **[`TokenBridgeRoute`](https://github.com/wormhole-foundation/wormhole-sdk-ts/blob/main/connect/src/routes/tokenBridge/manual.ts){target=\_blank}**: Manually redeemed Wormhole WTT route.
- **[`ExecutorTokenBridgeRoute`](https://github.com/wormhole-foundation/wormhole-sdk-ts/blob/main/connect/src/routes/tokenBridge/executor.ts){target=\_blank}**: Executor.
- **[`CCTPRoute`](https://github.com/wormhole-foundation/wormhole-sdk-ts/blob/main/connect/src/routes/cctp/manual.ts){target=\_blank}**: Manually redeemed CCTP route.
- **[`AutomaticCCTPRoute`](https://github.com/wormhole-foundation/wormhole-sdk-ts/blob/main/connect/src/routes/cctp/automatic.ts){target=\_blank}**: Automatically redeemed (relayed) CCTP route.
- **`DEFAULT_ROUTES`**: Array containing the four preceding routes (`TokenBridgeRoute`, `AutomaticTokenBridgeRoute`, `CCTPRoute`, `AutomaticCCTPRoute`).
- **[`nttManualRoute(nttConfig)`](https://github.com/wormhole-foundation/native-token-transfers/blob/main/sdk/route/src/manual.ts){target=\_blank}**: Function that returns the manually-redeemed NTT route.
- **`nttExecutorRoute(nttConfig)`**: Function that returns the Executor-powered NTT route for one-click transfers.
- **[`MayanRoute`](https://github.com/mayan-finance/wormhole-sdk-route/blob/main/src/index.ts#L57){target=\_blank}**: Route that offers multiple Mayan protocols.
- **[`MayanRouteSWIFT`](https://github.com/mayan-finance/wormhole-sdk-route/blob/main/src/index.ts#L528){target=\_blank}**: Route for Mayan's Swift protocol only.
- **[`MayanRouteMCTP`](https://github.com/mayan-finance/wormhole-sdk-route/blob/main/src/index.ts#L539){target=\_blank}**: Route for Mayan's MCTP protocol only.
- **[`MayanRouteWH`](https://github.com/mayan-finance/wormhole-sdk-route/blob/main/src/index.ts#L550){target=\_blank}**: Route for Mayan's original Wormhole transfer protocol.

In addition to these routes, developers can create custom routes for their Wormhole-based protocols. For examples, refer to the [NTT](https://github.com/wormhole-foundation/native-token-transfers/tree/main/sdk/route){target=\_blank} and the [Mayan](https://github.com/mayan-finance/wormhole-sdk-route){target=\_blank} example GitHub repositories.

For further details on the `route` plugin interface, refer to the [Wormhole TypeScript SDK route code](https://github.com/wormhole-foundation/wormhole-sdk-ts/blob/main/connect/src/routes/route.ts){target=\_blank}.

#### Example: Offer Only CCTP Transfers

To configure Wormhole Connect to offer only USDC transfers via the CCTP route, use the following configuration:

```typescript
import WormholeConnect, {
  AutomaticCCTPRoute,
  type config,
} from '@wormhole-foundation/wormhole-connect';

const config: config.WormholeConnectConfig = {
  routes: [AutomaticCCTPRoute],
};

<WormholeConnect config={config} />;
```

#### Example: Offer All Default Routes and Third-Party Plugins

In this example, Wormhole Connect is configured with routes for both default protocols (WTT and CCTP), as well as third-party protocols like [Native Token Transfers (NTT)](/docs/products/token-transfers/native-token-transfers/overview/){target=\_blank} and [Mayan Swap](https://swap.mayan.finance/){target=\_blank}.

```typescript
import WormholeConnect, {
  DEFAULT_ROUTES,
  MayanRouteSWIFT,
  type config,
} from '@wormhole-foundation/wormhole-connect';
import { nttExecutorRoute } from '@wormhole-foundation/wormhole-connect/ntt';

import { myNttConfig } from './consts'; // Custom NTT configuration

const config: config.WormholeConnectConfig = {
  routes: [...DEFAULT_ROUTES, nttExecutorRoute({ ntt: myNttConfig }), MayanRouteSWIFT],
};

<WormholeConnect config={config} />;
```

This flexible plugin allows you to combine default routes (such as WTT and CCTP) with third-party protocols, offering complete control over which routes are available in your application.

### Adding Custom Tokens {: #custom-tokens }

The following section shows how to add an arbitrary token to your deployment of Connect.

!!! note
    You will need to [register](https://portalbridge.com/legacy-tools/#/register){target=\_blank} your token with WTT to get the contract addresses necessary for it to work with that protocol.

This example configuration adds the BONK token to Connect. Note the `wrappedTokens` property, which is required for use with WTT.

See the [Connect source code](https://github.com/wormhole-foundation/wormhole-connect/blob/production%403.0.0/wormhole-connect/src/config/types.ts#L182){target=\_blank} for the type definition of `TokensConfig`.

```typescript
import WormholeConnect, { type config } from '@wormhole-foundation/wormhole-connect';

const config: config.WormholeConnectConfig = {
  tokensConfig: {
    BONK: {
      key: 'BONK',
      symbol: 'BONK',
      nativeChain: 'Ethereum',
      icon: Icon.ETH,
      tokenId: {
        chain: 'Ethereum',
        address: '0x1151CB3d861920e07a38e03eEAd12C32178567F6',
      },
      coinGeckoId: 'bonk',
      decimals: 18,
    },
  },
  wrappedTokens: {
    BONK: {
      Solana: 'DezXAZ8z7PnrnRJjz3wXBoRgixCa6xjnB7YaB1pPB263',
    },
  },
};
```

### Configuring Native Token Transfers (NTT)

Connect supports [NTT](/docs/products/token-transfers/native-token-transfers/overview/){target=\_blank}, which allows native tokens to move between supported chains using NTT-deployed contracts, such as managers and transceivers.

To enable NTT in your app, follow these steps:

 1. Add the NTT route to the `routes` array by calling `nttExecutorRoute(...)` with your token deployment config. This sets up the Executor-powered route logic for native token transfers.
 2. Provide token metadata for each of the tokens listed in `nttExecutorRoute` in the [`tokensConfig`](#custom-tokens) object. These entries must include `symbol`, `decimals`, and the `tokenId`.

```typescript
import WormholeConnect, { type config } from '@wormhole-foundation/wormhole-connect';
import { nttExecutorRoute } from '@wormhole-foundation/wormhole-connect/ntt';

const wormholeConfig: config.WormholeConnectConfig = {
  network: 'Testnet',
  chains: ['Solana', 'BaseSepolia'],
  tokens: ['WSV'],
  ui: {
    title: 'Wormhole NTT UI',
    defaultInputs: {
      fromChain: 'Solana',
      toChain: 'BaseSepolia',
    },
  },
  routes: [
    nttExecutorRoute({
      ntt: {
        tokens: {
          WSV_NTT: [
            {
              chain: 'Solana',
              manager: 'nMxHx1o8GUg2pv99y8JAQb5RyWNqDWixbxWCaBcurQx',
              token: '2vLDzr7hUpLFHQotmR8EPcMTWczZUwCK31aefAzumkmv',
              transceiver: [
                {
                  address: 'AjL3f9FMHJ8VkNUHZqLYxa5aFy3aTN6LUWMv4qmdf5PN',
                  type: 'wormhole',
                },
              ],
            },
            {
              chain: 'BaseSepolia',
              manager: '0xaE02Ff9C3781C5BA295c522fB469B87Dc5EE9205',
              token: '0xb8dccDA8C166172159F029eb003d5479687452bD',
              transceiver: [
                {
                  address: '0xF4Af1Eac8995766b54210b179A837E3D59a9F146',
                  type: 'wormhole',
                },
              ],
            },
          ],
        },
      },
    }),
  ],
  tokensConfig: {
    WSVsol: {
      symbol: 'WSV',
      tokenId: {
        chain: 'Solana',
        address: '2vLDzr7hUpLFHQotmR8EPcMTWczZUwCK31aefAzumkmv',
      },
      icon: 'https://wormhole.com/token.png',
      decimals: 9,
    },
    WSVbase: {
      symbol: 'WSV',
      tokenId: {
        chain: 'BaseSepolia',
        address: '0xb8dccDA8C166172159F029eb003d5479687452bD',
      },
      icon: 'https://wormhole.com/token.png',
      decimals: 9,
    },
  },
};
```

For a complete working example of NTT configuration in Wormhole Connect, see the [ntt-connect demo repository](https://github.com/wormhole-foundation/demo-ntt-connect){target=\_blank}.

### Whitelisting Tokens {: #whitelisting-tokens }

Connect offers a list of built-in tokens by default. You can see it below:

- [Mainnet tokens](https://github.com/wormhole-foundation/wormhole-connect/blob/production%403.0.0/wormhole-connect/src/config/mainnet/tokens.ts){target=\_blank}
- [Testnet tokens](https://github.com/wormhole-foundation/wormhole-connect/blob/production%403.0.0/wormhole-connect/src/config/testnet/tokens.ts){target=\_blank}

You can customize the tokens shown in the UI using the `tokens` property. The following example adds a custom token and limits Connect to showing only that token, along with the native gas tokens ETH and SOL.

```jsx
import WormholeConnect, { type config } from '@wormhole-foundation/wormhole-connect';

const config: config.WormholeConnectConfig = {
  chains: ['Ethereum', 'Solana'],
  tokens: ['ETH', 'SOL', 'BONK'],
  rpcs: {
    Ethereum: 'https://rpc.ankr.com/eth',
    Solana: 'https://rpc.ankr.com/solana',
  },
  tokensConfig: {
    BONK: {
      key: 'BONK',
      symbol: 'BONK',
      icon: 'https://assets.coingecko.com/coins/images/28600/large/bonk.jpg?1696527587',
      tokenId: {
        chain: 'Ethereum',
        address: '0x1151CB3d861920e07a38e03eEAd12C32178567F6',
      },
      decimals: 18,
    },
  },
  wrappedTokens: {
    BONK: {
      Solana: 'DezXAZ8z7PnrnRJjz3wXBoRgixCa6xjnB7YaB1pPB263',
    },
  },
};

function App() {
  return <WormholeConnect config={config} />;
}
```

You can whitelist tokens by symbol or by specifying tuples of [chain, address]. For example, this would show only BONK token (on all chains you've whitelisted) as well as [`EPjFW...TDt1v`](https://solscan.io/token/EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v){target=\_blank} on Solana, which is USDC.

```jsx
import WormholeConnect, {
  type config,
} from '@wormhole-foundation/wormhole-connect';

const config: config.WormholeConnectConfig = {
  chains: ['Ethereum', 'Solana'],
  tokens: [
    // Whitelist BONK on every whitelisted chain
    'BONK',
    // Also whitelist USDC, specifically on Solana
    ['Solana', 'EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v']
  ],
  ...
};

function App() {
  return <WormholeConnect config={config} />;
}
```

### User-Inputted Tokens {: #user-inputted-tokens }

As of version 2.0, Connect allows users to paste token addresses to bridge any token they want. As an integrator, you may want to disable this feature if you are deploying Connect for use only with a specific token(s).

If you provide a token whitelist (see above), this is turned off automatically. However, you can also disable it explicitly like this:

```jsx
import WormholeConnect, { type config } from '@wormhole-foundation/wormhole-connect';

const config: config.WormholeConnectConfig = {
  ui: {
    disableUserInputtedTokens: true,
  },
};

function App() {
  return <WormholeConnect config={config} />;
}
```

Setting `ui.disableUserInputtedTokens` to `true` will disable the ability to paste in token addresses.

### Transaction Settings {: #transaction-settings }

Landing transactions on Solana can require finely tuned priority fees when there is congestion. You can tweak how Connect determines these with `transactionSettings`. All of the parameters in this configuration are optional; you can provide any combination of them.

```jsx
import WormholeConnect, { type config } from '@wormhole-foundation/wormhole-connect';

const config: config.WormholeConnectConfig = {
  transactionSettings: {
    Solana: {
      priorityFee: {
        // Number between 0-1, defaults to 0.9. Higher percentile yields higher fees.
        // For example, you can set percentile to 0.95 to make Connect compute the
        // 95th percentile priority fee amount based on recent transactions
        percentile: 0.95,

        // Any number, defaults to 1.0. The fee amount is multiplied by this number.
        // This can be used to further raise or lower the fees Connect is using.
        // For example, percentile=0.95 and percentileMultiple=1.1 would use
        // the 95th percentile fee, with a 10% increase
        percentileMultiple: 1.1,

        // Minimum fee you want to use in microlamports, regardless of recent transactions
        // Defaults to 1
        min: 200_000,

        // Maximum fee you want to use in microlamports, regardless of recent transactions
        // Defaults to 100,000,000
        max: 5_000_000,
      },
    },
  },
};

function App() {
  return <WormholeConnect config={config} />;
}
```

!!! note
    Connect can calculate fees more accurately if you are using a [Triton](https://triton.one){target=\_blank} RPC endpoint.

### Wallet Set Up  {: #reown-cloud-project-id }

Your selected blockchain network determines the available wallet options when using Wormhole Connect.

 - For EVM chains, wallets like [MetaMask](https://metamask.io/){target=\_blank} and [Reown Cloud](https://reown.com/home){target=\_blank} (formerly WalletConnect) are supported.
 - For Solana, you'll see options such as [Phantom](https://phantom.com/){target=\_blank}, [Web3Auth](https://wallet.web3auth.io/){target=\_blank}, and [Coin98](https://coin98.com/){target=\_blank}.

The wallet options automatically adjust based on the selected chain, providing a seamless user experience without additional configuration.

To add Reown Cloud (formerly known as WalletConnect) as a supported wallet option, you need to obtain a project ID from the [Reown Cloud dashboard](https://dashboard.reown.com/){target=\_blank}. Once you have the project ID, set it in your `WormholeConnectConfig` under the `walletConnectProjectId` property.

```typescript
import WormholeConnect, { type config } from '@wormhole-foundation/wormhole-connect';

const wormholeConfig: config.WormholeConnectConfig = {
  ...
  walletConnectProjectId: 'INSERT_PROJECT_ID',
};
```

!!! note
    If the `walletConnectProjectId` is not set, Reown Cloud (WalletConnect) will be disabled from the available wallet list in the Connect UI.


---

Page Title: Connect FAQs

- Resolved Markdown: https://wormhole.com/docs/ai/pages/products-connect-faqs.md
- Canonical (HTML): https://wormhole.com/docs/products/connect/faqs/
- Summary: Common questions and detailed answers about using Wormhole Connect, including supported assets, chains, customization, and integration options.
- Word Count: 946; Token Estimate: 1606

# Connect FAQs

## What types of assets does Connect support? 

Connect supports both native and wrapped assets across all Wormhole-supported blockchains. This includes:

 - Major stablecoins like USDT and USDC (via CCTP).
 - Native gas tokens such as ETH, SOL, etc.
 - Cross-chain asset swaps through integrators like Mayan.

When bridging assets through Wrapped Token Transfers (WTT), depending on the chain and token, assets may arrive as Wormhole-wrapped tokens on the destination chain.

## What chains does Connect support? 

Connect supports around 30 chains, spanning various blockchain runtimes:

 - EVM-based chains (Ethereum, Base, Arbitrum, BSC, etc.)
 - Solana
 - Move-based chains (Sui, Aptos)

For a complete list of supported chains, see the [Connect-supported chains list](/docs/products/connect/reference/support-matrix/){target=\_blank}.

## What is gas dropoff? 

Gas dropoff allows users to receive gas for transaction fees on the destination chain, eliminating the need to acquire the native gas token from a centralized exchange. The relayer automatically swaps part of the transferred assets into the native gas token, enabling seamless entry into new ecosystems.

## Can I customize Connect inside my application?

Connect can be [fully customized](https://connect-in-style.wormhole.com/){target=\_blank} to choose the chains and assets you wish to support. You may also select different themes and colors to tailor Connect for your decentralized application. For details, see the [GitHub readme](https://github.com/wormhole-foundation/wormhole-connect){target=\_blank}.

## How can I disable specific routes?

Use `isRouteSupportedHandler` in your `WormholeConnectConfig`. The callback runs when Connect evaluates a route for the current selection. If it returns `false`, that exact route is hidden in the widget, so the user cannot select it.

Common patterns you can implement include:

 - Disabling all routes of a given type (`AutomaticTokenBridge` or `ManualTokenBridge`).
 - Disabling routes by token using `fromToken` or `toToken`.
 - Disabling routes by direction using `fromChain` or `toChain`.

**Example: Disable all `AutomaticTokenBridge` routes**

```typescript
import WormholeConnect, {
  type config,
} from '@wormhole-foundation/wormhole-connect';

const config: config.WormholeConnectConfig = {
  // ...
  isRouteSupportedHandler: async ({ route }) => {
    if (route === 'AutomaticTokenBridge') {
      return false;
    }
    return true; // keep other routes visible
  },
};
```

**Example: Disable a specific route for a particular token**

```typescript
import WormholeConnect, {
  type config,
} from '@wormhole-foundation/wormhole-connect';

const BLOCKED_ADDRESSES = new Set<string>(['INSERT_TOKEN_ADDRESS']);

const config: config.WormholeConnectConfig = {
  // ...
  isRouteSupportedHandler: async ({ route, fromToken }) => {
    const tokenAddress =
      fromToken.tokenId !== 'native' ? fromToken.tokenId.address : 'native';

    if (
      BLOCKED_ADDRESSES.has(tokenAddress) &&
      route === 'AutomaticTokenBridge'
    ) {
      return false;
    }
    return true; // keep other routes visible
  },
};
```

**Example: Disable `AutomaticTokenBridge` from a specific chain**

```typescript
import WormholeConnect, {
  type config,
} from '@wormhole-foundation/wormhole-connect';

const BLOCKED_SOURCE_CHAINS = new Set<Chain>(['INSERT_CHAIN_NAME']);

const config: config.WormholeConnectConfig = {
  // ...
  isRouteSupportedHandler: async ({ route, fromChain }) => {
    if (
      BLOCKED_SOURCE_CHAINS.has(fromChain) &&
      route === 'AutomaticTokenBridge'
    ) {
      return false;
    }
    return true; // keep other routes visible
  },
};
```

## How can I hide specific tokens from the picker?

Use `isTokenSupportedHandler` in your `WormholeConnectConfig`. The callback runs for each token candidate; if it returns `false`, that token is not shown in the picker and can't be selected.

**Example: Hide a token by address**

```typescript
import WormholeConnect, {
  type config,
} from '@wormhole-foundation/wormhole-connect';

const BLOCKED_ADDRESSES = new Set<string>(['INSERT_TOKEN_ADDRESS']);

const config: config.WormholeConnectConfig = {
  // ...
  isTokenSupportedHandler: (token) => {
    // Address string provided by Connect
    const addr = token.addressString;

    if (addr && BLOCKED_ADDRESSES.has(addr)) {
      return false;
    }
    return true; // show all others
  },
};
```

## Which functions or events does Connect rely on for NTT integration? 

Connect relies on the NTT SDK for integration, with platform-specific implementations for Solana and EVM. The critical methods involved include initiate and redeem functions and rate capacity methods. These functions ensure Connect can handle token transfers and manage chain-rate limits.

## Do integrators need to enable wallets like Phantom or Backpack in Connect?

Integrators don’t need to explicitly enable wallets like Phantom or Backpack in Connect. However, the wallet must be installed and enabled in the user's browser to appear as an option in the interface.

## Which function should be modified to set priority fees for Solana transactions?

In [Wormhole Connect](https://github.com/wormhole-foundation/wormhole-connect){target=\_blank}, you can modify the priority fees for Solana transactions by updating the `computeBudget/index.ts` file. This file contains the logic for adjusting the compute unit limit and priority fees associated with Solana transactions.

To control the priority fee applied to your transactions, you can modify the `feePercentile` and `minPriorityFee` parameters in the `addComputeBudget` and `determineComputeBudget` functions.

The relevant file can be found in the Connect codebase: [`computeBudget/index.ts`](https://github.com/wormhole-foundation/wormhole-connect/blob/62f1ba8ee5502ac6fd405680e6b3816c9aa54325/sdk/src/contexts/solana/utils/computeBudget/index.ts){target=\_blank}.

## Is there a minimum amount for bridging with CCTP or the Connect SDK?

There is no minimum amount for bridging via CCTP if the user covers the gas fees on both the source and destination chains. However, if the transfer is automatically relayed, a minimum amount is required to cover relay fees on the destination chain. The relay provider charges these fees at cost.

Current relay fees:

- **Ethereum L1**: ~4.2 USDC
- **Base, Optimism, Arbitrum, Avalanche**: 0.3 USDC

Additional notes:

- **USDC to Solana**: Wormhole's native CCTP route does not currently support automatic relaying of USDC to Solana. However, you can transfer USDC to Solana using the [Mayan plugin](https://github.com/mayan-finance/wormhole-sdk-route){target=\_blank} for the SDK. Mayan is a protocol that integrates Wormhole and CCTP to enable this functionality.
- **Frontend integrations**:
    - **Connect**: A pre-built UI available via [@wormhole-foundation/wormhole-connect](https://www.npmjs.com/package/@wormhole-foundation/wormhole-connect){target=\_blank}.
    - **TypeScript SDK**: A lower-level integration option, available via [@wormhole-foundation/sdk](https://www.npmjs.com/package/@wormhole-foundation/sdk){target=\_blank}, allowing developers to build custom UIs.

        !!!note
            The TypeScript SDK was previously referred to as the "Connect SDK," but this naming has since been discontinued.


---

Page Title: Connect Supported Networks

- Resolved Markdown: https://wormhole.com/docs/ai/pages/products-connect-reference-supported-networks.md
- Canonical (HTML): https://wormhole.com/docs/products/connect/reference/supported-networks/
- Summary: Explore all blockchains supported by Wormhole Connect, including network availability, block explorers, and cross-chain transfer support.
- Word Count: 2119; Token Estimate: 5768

# Supported Networks



<div class="full-width" markdown>

<table data-full-width="true" markdown><thead><th>Blockchain</th><th>Environment</th><th>Mainnet</th><th>Testnet</th><th>Devnet</th><th>Quick Links</th></thead><tbody><tr><td>Ethereum</td><td>EVM</td><td>:white_check_mark:</td><td>:white_check_mark:</td><td>:white_check_mark:</td><td>:material-web: <a href="https://ethereum.org/" target="_blank">Website</a><br>:material-file-document: <a href="https://ethereum.org/developers/docs/" target="_blank">Developer Docs</a><br>:octicons-package-16: <a href="https://etherscan.io/" target="_blank">Block Explorer</a></td></tr><tr><td>Solana</td><td>SVM</td><td>:white_check_mark:</td><td>:white_check_mark:</td><td>:x:</td><td>:material-web: <a href="https://solana.com/" target="_blank">Website</a><br>:material-file-document: <a href="https://solana.com/docs" target="_blank">Developer Docs</a><br>:octicons-package-16: <a href="https://explorer.solana.com/" target="_blank">Block Explorer</a></td></tr><tr><td>Aptos</td><td>Move VM</td><td>:white_check_mark:</td><td>:x:</td><td>:x:</td><td>:material-web: <a href="https://aptosnetwork.com/" target="_blank">Website</a><br>:material-file-document: <a href="https://aptos.dev/" target="_blank">Developer Docs</a><br>:octicons-package-16: <a href="https://explorer.aptoslabs.com/" target="_blank">Block Explorer</a></td></tr><tr><td>Arbitrum</td><td>EVM</td><td>:white_check_mark:</td><td>:white_check_mark:</td><td>:x:</td><td>:material-web: <a href="https://arbitrum.io/" target="_blank">Website</a><br>:material-file-document: <a href="https://docs.arbitrum.io/" target="_blank">Developer Docs</a><br>:octicons-package-16: <a href="https://arbiscan.io/" target="_blank">Block Explorer</a></td></tr><tr><td>Avalanche</td><td>EVM</td><td>:white_check_mark:</td><td>:white_check_mark:</td><td>:x:</td><td>:material-web: <a href="https://www.avax.network/" target="_blank">Website</a><br>:material-file-document: <a href="https://build.avax.network/docs/primary-network" target="_blank">Developer Docs</a><br>:octicons-package-16: <a href="https://snowtrace.io/" target="_blank">Block Explorer</a></td></tr><tr><td>Base</td><td>EVM</td><td>:white_check_mark:</td><td>:white_check_mark:</td><td>:x:</td><td>:material-web: <a href="https://base.org/" target="_blank">Website</a><br>:material-file-document: <a href="https://docs.base.org/" target="_blank">Developer Docs</a><br>:octicons-package-16: <a href="https://basescan.org/" target="_blank">Block Explorer</a></td></tr><tr><td>Berachain</td><td>EVM</td><td>:white_check_mark:</td><td>:white_check_mark:</td><td>:x:</td><td>:material-web: <a href="https://www.berachain.com/" target="_blank">Website</a><br>:material-file-document: <a href="https://docs.berachain.com/" target="_blank">Developer Docs</a><br>:octicons-package-16: <a href="https://berascan.com/" target="_blank">Block Explorer</a></td></tr><tr><td>BNB Smart Chain</td><td>EVM</td><td>:white_check_mark:</td><td>:white_check_mark:</td><td>:x:</td><td>:material-web: <a href="https://www.bnbchain.org/en/bnb-smart-chain" target="_blank">Website</a><br>:material-file-document: <a href="https://docs.bnbchain.org/" target="_blank">Developer Docs</a><br>:octicons-package-16: <a href="https://bscscan.com/" target="_blank">Block Explorer</a></td></tr><tr><td>Celo</td><td>EVM</td><td>:white_check_mark:</td><td>:white_check_mark:</td><td>:x:</td><td>:material-web: <a href="https://celo.org/" target="_blank">Website</a><br>:material-file-document: <a href="https://docs.celo.org/" target="_blank">Developer Docs</a><br>:octicons-package-16: <a href="https://celo.blockscout.com/" target="_blank">Block Explorer</a></td></tr><tr><td>CreditCoin</td><td>EVM</td><td>:white_check_mark:</td><td>:x:</td><td>:x:</td><td>:material-web: <a href="https://creditcoin.org/" target="_blank">Website</a><br>:material-file-document: <a href="https://docs.creditcoin.org/" target="_blank">Developer Docs</a><br>:octicons-package-16: <a href="https://creditcoin.subscan.io/" target="_blank">Block Explorer</a></td></tr><tr><td>Fantom</td><td>EVM</td><td>:white_check_mark:</td><td>:white_check_mark:</td><td>:x:</td><td>:material-web: <a href="https://fantom.foundation/" target="_blank">Website</a><br>:material-file-document: <a href="https://docs.fantom.foundation/" target="_blank">Developer Docs</a><br>:octicons-package-16: <a href="https://explorer.fantom.network/" target="_blank">Block Explorer</a></td></tr><tr><td>Fogo</td><td>SVM</td><td>:white_check_mark:</td><td>:white_check_mark:</td><td>:x:</td><td>:material-web: <a href="https://www.fogo.io/" target="_blank">Website</a><br>:octicons-package-16: <a href="https://fogoscan.com/?cluster=testnet" target="_blank">Block Explorer</a></td></tr><tr><td>HyperCore</td><td>EVM</td><td>:white_check_mark:</td><td>:white_check_mark:</td><td>:x:</td><td>:material-web: <a href="https://hyperliquid.gitbook.io/hyperliquid-docs/hypercore" target="_blank">Website</a><br>:material-file-document: <a href="https://hyperliquid.gitbook.io/hyperliquid-docs/hypercore" target="_blank">Developer Docs</a><br></td></tr><tr><td>HyperEVM :material-alert:{ title='⚠️ The HyperEVM integration is experimental, as its node software is not open source. Use Wormhole messaging on HyperEVM with caution.' }</td><td>EVM</td><td>:white_check_mark:</td><td>:white_check_mark:</td><td>:x:</td><td>:material-web: <a href="https://hyperfoundation.org/" target="_blank">Website</a><br>:material-file-document: <a href="https://hyperliquid.gitbook.io/hyperliquid-docs" target="_blank">Developer Docs</a><br></td></tr><tr><td>Ink</td><td>EVM</td><td>:white_check_mark:</td><td>:x:</td><td>:x:</td><td>:material-web: <a href="https://inkonchain.com/" target="_blank">Website</a><br>:material-file-document: <a href="https://docs.inkonchain.com/" target="_blank">Developer Docs</a><br>:octicons-package-16: <a href="https://explorer-sepolia.inkonchain.com/" target="_blank">Block Explorer</a></td></tr><tr><td>Kaia</td><td>EVM</td><td>:white_check_mark:</td><td>:white_check_mark:</td><td>:x:</td><td>:material-web: <a href="https://www.kaia.io/" target="_blank">Website</a><br>:material-file-document: <a href="https://docs.kaia.io/" target="_blank">Developer Docs</a><br>:octicons-package-16: <a href="https://kaiascan.io/" target="_blank">Block Explorer</a></td></tr><tr><td>Linea</td><td>EVM</td><td>:white_check_mark:</td><td>:x:</td><td>:x:</td><td>:material-web: <a href="https://linea.build/" target="_blank">Website</a><br>:material-file-document: <a href="https://docs.linea.build/" target="_blank">Developer Docs</a><br>:octicons-package-16: <a href="https://docs.linea.build/get-started/build/block-explorers" target="_blank">Block Explorer</a></td></tr><tr><td>Mantle</td><td>EVM</td><td>:white_check_mark:</td><td>:white_check_mark:</td><td>:x:</td><td>:material-web: <a href="https://www.mantle.xyz/" target="_blank">Website</a><br>:material-file-document: <a href="https://docs.mantle.xyz/network/" target="_blank">Developer Docs</a><br>:octicons-package-16: <a href="https://mantlescan.xyz/" target="_blank">Block Explorer</a></td></tr><tr><td>MegaETH</td><td>EVM</td><td>:white_check_mark:</td><td>:x:</td><td>:x:</td><td>:material-web: <a href="https://www.megaeth.com/" target="_blank">Website</a><br>:material-file-document: <a href="https://docs.megaeth.com/" target="_blank">Developer Docs</a><br>:octicons-package-16: <a href="https://mega.etherscan.io/" target="_blank">Block Explorer</a></td></tr><tr><td>Mezo</td><td>EVM</td><td>:white_check_mark:</td><td>:white_check_mark:</td><td>:x:</td><td>:material-web: <a href="https://mezo.org/" target="_blank">Website</a><br>:material-file-document: <a href="https://mezo.org/docs/developers/" target="_blank">Developer Docs</a><br>:octicons-package-16: <a href="https://explorer.test.mezo.org/" target="_blank">Block Explorer</a></td></tr><tr><td>Moca</td><td>EVM</td><td>:white_check_mark:</td><td>:x:</td><td>:x:</td><td>:material-web: <a href="https://mocachain.org/en" target="_blank">Website</a><br>:material-file-document: <a href="https://mocacoin.gitbook.io/litepaper" target="_blank">Developer Docs</a><br>:octicons-package-16: <a href="https://devnet-scan.mocachain.org/" target="_blank">Block Explorer</a></td></tr><tr><td>Monad</td><td>EVM</td><td>:white_check_mark:</td><td>:white_check_mark:</td><td>:x:</td><td>:material-web: <a href="https://www.monad.xyz/" target="_blank">Website</a><br>:material-file-document: <a href="https://docs.monad.xyz/" target="_blank">Developer Docs</a><br>:octicons-package-16: <a href="https://testnet.monvision.io/" target="_blank">Block Explorer</a></td></tr><tr><td>Moonbeam</td><td>EVM</td><td>:white_check_mark:</td><td>:white_check_mark:</td><td>:x:</td><td>:material-web: <a href="https://moonbeam.network/" target="_blank">Website</a><br>:material-file-document: <a href="https://docs.moonbeam.network/" target="_blank">Developer Docs</a><br>:octicons-package-16: <a href="https://moonscan.io/" target="_blank">Block Explorer</a></td></tr><tr><td>Optimism</td><td>EVM</td><td>:white_check_mark:</td><td>:white_check_mark:</td><td>:x:</td><td>:material-web: <a href="https://www.optimism.io/" target="_blank">Website</a><br>:material-file-document: <a href="https://docs.optimism.io/" target="_blank">Developer Docs</a><br>:octicons-package-16: <a href="https://optimistic.etherscan.io/" target="_blank">Block Explorer</a></td></tr><tr><td>Plume</td><td>EVM</td><td>:white_check_mark:</td><td>:x:</td><td>:x:</td><td>:material-web: <a href="https://plume.org/" target="_blank">Website</a><br>:material-file-document: <a href="https://docs.plume.org/plume" target="_blank">Developer Docs</a><br>:octicons-package-16: <a href="https://explorer.plume.org/" target="_blank">Block Explorer</a></td></tr><tr><td>Polygon</td><td>EVM</td><td>:white_check_mark:</td><td>:white_check_mark:</td><td>:x:</td><td>:material-web: <a href="https://polygon.technology/" target="_blank">Website</a><br>:material-file-document: <a href="https://docs.polygon.technology/" target="_blank">Developer Docs</a><br>:octicons-package-16: <a href="https://polygonscan.com/" target="_blank">Block Explorer</a></td></tr><tr><td>Scroll</td><td>EVM</td><td>:white_check_mark:</td><td>:white_check_mark:</td><td>:x:</td><td>:material-web: <a href="https://scroll.io/" target="_blank">Website</a><br>:material-file-document: <a href="https://docs.scroll.io/en/home/" target="_blank">Developer Docs</a><br>:octicons-package-16: <a href="https://scrollscan.com/" target="_blank">Block Explorer</a></td></tr><tr><td>SeiEVM</td><td>EVM</td><td>:white_check_mark:</td><td>:x:</td><td>:x:</td><td>:material-web: <a href="https://www.sei.io/" target="_blank">Website</a><br>:material-file-document: <a href="https://docs.sei.io/evm" target="_blank">Developer Docs</a><br>:octicons-package-16: <a href="https://seistream.app/" target="_blank">Block Explorer</a></td></tr><tr><td>Sonic</td><td>EVM</td><td>:white_check_mark:</td><td>:x:</td><td>:x:</td><td>:material-web: <a href="https://www.soniclabs.com/" target="_blank">Website</a><br>:material-file-document: <a href="https://docs.soniclabs.com/" target="_blank">Developer Docs</a><br>:octicons-package-16: <a href="https://sonicscan.org/" target="_blank">Block Explorer</a></td></tr><tr><td>Sui</td><td>Sui Move VM</td><td>:white_check_mark:</td><td>:white_check_mark:</td><td>:x:</td><td>:material-web: <a href="https://www.sui.io/" target="_blank">Website</a><br>:material-file-document: <a href="https://docs.sui.io/" target="_blank">Developer Docs</a><br>:octicons-package-16: <a href="https://suiscan.xyz/" target="_blank">Block Explorer</a></td></tr><tr><td>Unichain</td><td>EVM</td><td>:white_check_mark:</td><td>:white_check_mark:</td><td>:x:</td><td>:material-web: <a href="https://www.unichain.org/" target="_blank">Website</a><br>:material-file-document: <a href="https://docs.unichain.org/docs" target="_blank">Developer Docs</a><br>:octicons-package-16: <a href="https://sepolia.uniscan.xyz/" target="_blank">Block Explorer</a></td></tr><tr><td>World Chain</td><td>EVM</td><td>:white_check_mark:</td><td>:x:</td><td>:x:</td><td>:material-web: <a href="https://world.org/world-chain" target="_blank">Website</a><br>:material-file-document: <a href="https://docs.world.org/" target="_blank">Developer Docs</a><br>:octicons-package-16: <a href="https://docs.world.org/world-chain/providers/explorers" target="_blank">Block Explorer</a></td></tr><tr><td>X Layer</td><td>EVM</td><td>:white_check_mark:</td><td>:x:</td><td>:x:</td><td>:material-web: <a href="https://web3.okx.com/xlayer" target="_blank">Website</a><br>:material-file-document: <a href="https://web3.okx.com/xlayer/docs/developer/build-on-xlayer/about-xlayer" target="_blank">Developer Docs</a><br>:octicons-package-16: <a href="https://web3.okx.com/explorer/x-layer" target="_blank">Block Explorer</a></td></tr><tr><td>XRPL-EVM</td><td>EVM</td><td>:white_check_mark:</td><td>:x:</td><td>:x:</td><td>:material-web: <a href="https://www.xrplevm.org/" target="_blank">Website</a><br>:material-file-document: <a href="https://docs.xrplevm.org/" target="_blank">Developer Docs</a><br>:octicons-package-16: <a href="https://explorer.xrplevm.org/" target="_blank">Block Explorer</a></td></tr></tbody></table>

</div>


---

Page Title: Connect Theme & UI Customization

- Resolved Markdown: https://wormhole.com/docs/ai/pages/products-connect-configuration-theme.md
- Canonical (HTML): https://wormhole.com/docs/products/connect/configuration/theme/
- Summary: Learn how to style Wormhole Connect with custom color schemes, fonts, layouts, and menus for a streamlined user experience.
- Word Count: 368; Token Estimate: 993

## Theme & UI Customization

This page focuses on how to style the Connect widget, covering color schemes, fonts, layout changes (like toggling the hamburger menu), and adding extra menu entries. You'll learn how to customize Connect's look and feel to match your application's branding.

### Changing the Color Scheme

You can customize Connect's color scheme by providing a `theme` prop.

=== "React integration"

    ```ts
    import WormholeConnect, { type config, WormholeConnectTheme } from '@wormhole-foundation/wormhole-connect';

    const config: config.WormholeConnectConfig = {
      /* Your config... */
    };

    const theme: WormholeConnectTheme = {
      mode: 'dark',
      primary: '#78c4b6',
      font: 'Comic Sans; sans-serif',
    };

    function App() {
      return <WormholeConnect config={config} theme={theme} />;
    }
    ```

=== "Hosted integration"

    ```ts
    import WormholeConnect, { type config, WormholeConnectTheme, wormholeConnectHosted } from '@wormhole-foundation/wormhole-connect';

    const config: config.WormholeConnectConfig = {
      /* Your config... */
    };

    const theme: WormholeConnectTheme = {
      mode: 'dark',
      primary: '#78c4b6',
      font: 'Comic Sans; sans-serif',
    };

    const container = document.getElementById('bridge-container');

    wormholeConnectHosted(container, {
      config,
      theme,
    });
    ```

The `WormholeConnectTheme` type supports the following properties:

| <div style="width:10em">Property</div> |                              Description                              |        Example        |
|:--------------------------------------:|:---------------------------------------------------------------------:|:---------------------:|
|                 `mode`                 |                 Dark mode or light mode. **Required**                 | `"dark"` or `"light"` |
|                `input`                 |                Color used for input fields, dropdowns                 |      `"#AABBCC"`      |
|               `primary`                |                    Primary color used for buttons                     |      `"#AABBCC"`      |
|              `secondary`               |               Secondary color used for some UI elements               |      `"#AABBCC"`      |
|                 `text`                 |                      Primary color used for text                      |      `"#AABBCC"`      |
|            `textSecondary`             |                 Secondary color used for dimmer text                  |      `"#AABBCC"`      |
|                `error`                 |         Color to display errors in, usually some shade of red         |      `"#AABBCC"`      |
|               `success`                |                 Color to display success messages in                  |      `"#AABBCC"`      |
|                 `font`                 | Font used in the UI, can be custom font available in your application | `"Arial; sans-serif"` |

### Toggle Hamburger Menu {: #toggle-hamburger-menu }

By setting the `showHamburgerMenu` option to **false**, you can deactivate the hamburger menu, which will position the links at the bottom.

#### Add Extra Menu Entry {: #add-extra-menu-entry }

By setting the `showHamburgerMenu` option to `false`, you can add extra links. The following properties are accessed through the `menu[]` property (e.g., `menu[].label`):

| Property |                 Description                 |
|:--------:|:-------------------------------------------:|
| `label`  |            Link name to show up             |
|  `href`  |              Target URL or URN              |
| `target` | Anchor standard target, by default `_blank` |
| `order`  | Order where the new item should be injected |

```jsx
import WormholeConnect, { type config } from '@wormhole-foundation/wormhole-connect';

const config: config.WormholeConnectConfig = {
  ui: {
    showHamburgerMenu: false,
    menu: [
      {
        label: 'Advance Tools',
        href: 'https://portalbridge.com',
        target: '_self',
        order: 1,
      },
    ],
  },
};

function App() {
  return <WormholeConnect config={config} />;
}
```


---

Page Title: Contract Addresses

- Resolved Markdown: https://wormhole.com/docs/ai/pages/products-reference-contract-addresses.md
- Canonical (HTML): https://wormhole.com/docs/products/reference/contract-addresses/
- Summary: This page documents the deployed contract addresses of the Wormhole contracts on each chain, including Core Contracts, TokenBridge, and more.
- Word Count: 4112; Token Estimate: 11475

# Contract Addresses

## Core Contracts



=== "Mainnet"

    <table data-full-width="true" markdown><thead><th>Chain Name</th><th>Contract Address</th></thead><tbody><tr><td>Ethereum</td><td><code>0x98f3c9e6E3fAce36bAAd05FE09d375Ef1464288B</code></td></tr><tr><td>Solana</td><td><code>worm2ZoG2kUd4vFXhvjh93UUH596ayRfgQ2MgjNMTth</code></td></tr><tr><td>0G (Zero Gravity)</td><td><code>0xC699482c17d43b7D5349F2D3f58d61fEFA972B8c</code></td></tr><tr><td>Algorand</td><td><code>842125965</code></td></tr><tr><td>Aptos</td><td><code>0x5bc11445584a763c1fa7ed39081f1b920954da14e04b32440cba863d03e19625</code></td></tr><tr><td>Arbitrum</td><td><code>0xa5f208e072434bC67592E4C49C1B991BA79BCA46</code></td></tr><tr><td>Avalanche</td><td><code>0x54a8e5f9c4CbA08F9943965859F6c34eAF03E26c</code></td></tr><tr><td>Base</td><td><code>0xbebdb6C8ddC678FfA9f8748f85C815C556Dd8ac6</code></td></tr><tr><td>Berachain</td><td><code>0xCa1D5a146B03f6303baF59e5AD5615ae0b9d146D</code></td></tr><tr><td>BNB Smart Chain</td><td><code>0x98f3c9e6E3fAce36bAAd05FE09d375Ef1464288B</code></td></tr><tr><td>Celo</td><td><code>0xa321448d90d4e5b0A732867c18eA198e75CAC48E</code></td></tr><tr><td>CreditCoin</td><td><code>0xaBf89de706B583424328B54dD05a8fC986750Da8</code></td></tr><tr><td>Fantom</td><td><code>0x126783A6Cb203a3E35344528B26ca3a0489a1485</code></td></tr><tr><td>Fogo</td><td><code>worm2mrQkG1B1KTz37erMfWN8anHkSK24nzca7UD8BB</code></td></tr><tr><td>HyperEVM :material-alert:{ title='⚠️ The HyperEVM integration is experimental, as its node software is not open source. Use Wormhole messaging on HyperEVM with caution.' }</td><td><code>0x7C0faFc4384551f063e05aee704ab943b8B53aB3</code></td></tr><tr><td>Injective</td><td><code>inj17p9rzwnnfxcjp32un9ug7yhhzgtkhvl9l2q74d</code></td></tr><tr><td>Ink</td><td><code>0xCa1D5a146B03f6303baF59e5AD5615ae0b9d146D</code></td></tr><tr><td>Kaia</td><td><code>0x0C21603c4f3a6387e241c0091A7EA39E43E90bb7</code></td></tr><tr><td>Linea</td><td><code>0x0C56aebD76E6D9e4a1Ec5e94F4162B4CBbf77b32</code></td></tr><tr><td>Mantle</td><td><code>0xbebdb6C8ddC678FfA9f8748f85C815C556Dd8ac6</code></td></tr><tr><td>MegaETH</td><td><code>0xaBf89de706B583424328B54dD05a8fC986750Da8</code></td></tr><tr><td>Mezo</td><td><code>0xaBf89de706B583424328B54dD05a8fC986750Da8</code></td></tr><tr><td>Moca</td><td><code>0xaBf89de706B583424328B54dD05a8fC986750Da8</code></td></tr><tr><td>Monad</td><td><code>0x194B123c5E96B9b2E49763619985790Dc241CAC0</code></td></tr><tr><td>Moonbeam</td><td><code>0xC8e2b0cD52Cf01b0Ce87d389Daa3d414d4cE29f3</code></td></tr><tr><td>NEAR</td><td><code>contract.wormhole_crypto.near</code></td></tr><tr><td>Neutron</td><td><code>neutron16rerygcpahqcxx5t8vjla46ym8ccn7xz7rtc6ju5ujcd36cmc7zs9zrunh</code></td></tr><tr><td>Optimism</td><td><code>0xEe91C335eab126dF5fDB3797EA9d6aD93aeC9722</code></td></tr><tr><td>Plume</td><td><code>0xaBf89de706B583424328B54dD05a8fC986750Da8</code></td></tr><tr><td>Polygon</td><td><code>0x7A4B5a56256163F07b2C80A7cA55aBE66c4ec4d7</code></td></tr><tr><td>Pythnet</td><td><code>H3fxXJ86ADW2PNuDDmZJg6mzTtPxkYCpNuQUTgmJ7AjU</code></td></tr><tr><td>Scroll</td><td><code>0xbebdb6C8ddC678FfA9f8748f85C815C556Dd8ac6</code></td></tr><tr><td>Sei</td><td><code>sei1gjrrme22cyha4ht2xapn3f08zzw6z3d4uxx6fyy9zd5dyr3yxgzqqncdqn</code></td></tr><tr><td>SeiEVM</td><td><code>0xCa1D5a146B03f6303baF59e5AD5615ae0b9d146D</code></td></tr><tr><td>Sui</td><td><code>0xaeab97f96cf9877fee2883315d459552b2b921edc16d7ceac6eab944dd88919c</code></td></tr><tr><td>Unichain</td><td><code>0xCa1D5a146B03f6303baF59e5AD5615ae0b9d146D</code></td></tr><tr><td>World Chain</td><td><code>0xcbcEe4e081464A15d8Ad5f58BB493954421eB506</code></td></tr><tr><td>X Layer</td><td><code>0x194B123c5E96B9b2E49763619985790Dc241CAC0</code></td></tr><tr><td>XRPL-EVM</td><td><code>0xaBf89de706B583424328B54dD05a8fC986750Da8</code></td></tr></tbody></table>

=== "Testnet"

    <table data-full-width="true" markdown><thead><th>Chain Name</th><th>Contract Address</th></thead><tbody><tr><td>Ethereum Holesky</td><td><code>0xa10f2eF61dE1f19f586ab8B6F2EbA89bACE63F7a</code></td></tr><tr><td>Ethereum Sepolia</td><td><code>0x4a8bc80Ed5a4067f1CCf107057b8270E0cC11A78</code></td></tr><tr><td>Solana</td><td><code>3u8hJUVTA4jH1wYAyUur7FFZVQ8H635K3tSHHF4ssjQ5</code></td></tr><tr><td>0G (Zero Gravity)</td><td><code>0x059560c0D626bdB982454b5EBd65DC8E7cF7973c</code></td></tr><tr><td>Algorand</td><td><code>86525623</code></td></tr><tr><td>Aptos</td><td><code>0x5bc11445584a763c1fa7ed39081f1b920954da14e04b32440cba863d03e19625</code></td></tr><tr><td>Arbitrum Sepolia</td><td><code>0x6b9C8671cdDC8dEab9c719bB87cBd3e782bA6a35</code></td></tr><tr><td>Avalanche</td><td><code>0x7bbcE28e64B3F8b84d876Ab298393c38ad7aac4C</code></td></tr><tr><td>Base Sepolia</td><td><code>0x79A1027a6A159502049F10906D333EC57E95F083</code></td></tr><tr><td>Berachain</td><td><code>0xBB73cB66C26740F31d1FabDC6b7A46a038A300dd</code></td></tr><tr><td>BNB Smart Chain</td><td><code>0x68605AD7b15c732a30b1BbC62BE8F2A509D74b4D</code></td></tr><tr><td>Celo</td><td><code>0x88505117CA88e7dd2eC6EA1E13f0948db2D50D56</code></td></tr><tr><td>Converge</td><td><code>0x556B259cFaCd9896B2773310080c7c3bcE90Ff01</code></td></tr><tr><td>CreditCoin</td><td><code>0xaBf89de706B583424328B54dD05a8fC986750Da8</code></td></tr><tr><td>Fantom</td><td><code>0x1BB3B4119b7BA9dfad76B0545fb3F531383c3bB7</code></td></tr><tr><td>Fogo</td><td><code>BhnQyKoQQgpuRTRo6D8Emz93PvXCYfVgHhnrR4T3qhw4</code></td></tr><tr><td>HyperEVM :material-alert:{ title='⚠️ The HyperEVM integration is experimental, as its node software is not open source. Use Wormhole messaging on HyperEVM with caution.' }</td><td><code>0xBB73cB66C26740F31d1FabDC6b7A46a038A300dd</code></td></tr><tr><td>Injective</td><td><code>inj1xx3aupmgv3ce537c0yce8zzd3sz567syuyedpg</code></td></tr><tr><td>Ink</td><td><code>0xBB73cB66C26740F31d1FabDC6b7A46a038A300dd</code></td></tr><tr><td>Kaia</td><td><code>0x1830CC6eE66c84D2F177B94D544967c774E624cA</code></td></tr><tr><td>Linea</td><td><code>0x79A1027a6A159502049F10906D333EC57E95F083</code></td></tr><tr><td>Mantle</td><td><code>0x376428e7f26D5867e69201b275553C45B09EE090</code></td></tr><tr><td>MegaETH</td><td><code>0x81705b969cDcc6FbFde91a0C6777bE0EF3A75855</code></td></tr><tr><td>Mezo</td><td><code>0x268557122Ffd64c85750d630b716471118F323c8</code></td></tr><tr><td>Moca</td><td><code>0xaBf89de706B583424328B54dD05a8fC986750Da8</code></td></tr><tr><td>Monad Testnet</td><td><code>0xaBf89de706B583424328B54dD05a8fC986750Da8</code></td></tr><tr><td>Moonbeam</td><td><code>0xa5B7D85a8f27dd7907dc8FdC21FA5657D5E2F901</code></td></tr><tr><td>NEAR</td><td><code>wormhole.wormhole.testnet</code></td></tr><tr><td>Neutron</td><td><code>neutron1enf63k37nnv9cugggpm06mg70emcnxgj9p64v2s8yx7a2yhhzk2q6xesk4</code></td></tr><tr><td>Optimism Sepolia</td><td><code>0x31377888146f3253211EFEf5c676D41ECe7D58Fe</code></td></tr><tr><td>Osmosis</td><td><code>osmo1hggkxr0hpw83f8vuft7ruvmmamsxmwk2hzz6nytdkzyup9krt0dq27sgyx</code></td></tr><tr><td>Plasma</td><td><code>0xaBf89de706B583424328B54dD05a8fC986750Da8</code></td></tr><tr><td>Plume</td><td><code>0x81705b969cDcc6FbFde91a0C6777bE0EF3A75855</code></td></tr><tr><td>Polygon Amoy</td><td><code>0x6b9C8671cdDC8dEab9c719bB87cBd3e782bA6a35</code></td></tr><tr><td>Pythnet</td><td><code>EUrRARh92Cdc54xrDn6qzaqjA77NRrCcfbr8kPwoTL4z</code></td></tr><tr><td>Scroll</td><td><code>0x055F47F1250012C6B20c436570a76e52c17Af2D5</code></td></tr><tr><td>Sei</td><td><code>sei1nna9mzp274djrgzhzkac2gvm3j27l402s4xzr08chq57pjsupqnqaj0d5s</code></td></tr><tr><td>SeiEVM</td><td><code>0xBB73cB66C26740F31d1FabDC6b7A46a038A300dd</code></td></tr><tr><td>Stacks</td><td><code>ST37PDDGEA78QSPSBZM1ZHPCZV9GKAPDFHA32RWY8</code></td></tr><tr><td>Sui</td><td><code>0x31358d198147da50db32eda2562951d53973a0c0ad5ed738e9b17d88b213d790</code></td></tr><tr><td>Unichain</td><td><code>0xBB73cB66C26740F31d1FabDC6b7A46a038A300dd</code></td></tr><tr><td>World Chain</td><td><code>0xe5E02cD12B6FcA153b0d7fF4bF55730AE7B3C93A</code></td></tr><tr><td>X Layer</td><td><code>0xA31aa3FDb7aF7Db93d18DDA4e19F811342EDF780</code></td></tr><tr><td>XRPL-EVM</td><td><code>0xaBf89de706B583424328B54dD05a8fC986750Da8</code></td></tr></tbody></table>

=== "Devnet"

    <table data-full-width="true" markdown><thead><th>Chain Name</th><th>Contract Address</th></thead><tbody><tr><td>Ethereum</td><td><code>0xC89Ce4735882C9F0f0FE26686c53074E09B0D550</code></td></tr><tr><td>Solana</td><td><code>Bridge1p5gheXUvJ6jGWGeCsgPKgnE3YgdGKRVCMY9o</code></td></tr><tr><td>Algorand</td><td><code>1004</code></td></tr><tr><td>Aptos</td><td><code>0xde0036a9600559e295d5f6802ef6f3f802f510366e0c23912b0655d972166017</code></td></tr><tr><td>BNB Smart Chain</td><td><code>0xC89Ce4735882C9F0f0FE26686c53074E09B0D550</code></td></tr><tr><td>NEAR</td><td><code>wormhole.test.near</code></td></tr><tr><td>Stacks</td><td><code>ST1PQHQKV0RJXZFY1DGX8MNSNYVE3VGZJSRTPGZGM</code></td></tr><tr><td>Sui</td><td><code>0x5a5160ca3c2037f4b4051344096ef7a48ebf4400b3f385e57ea90e1628a8bde0</code></td></tr></tbody></table>

## Wrapped Token Transfers (WTT)



=== "Mainnet"

    <table data-full-width="true" markdown><thead><th>Chain Name</th><th>Contract Address</th></thead><tbody><tr><td>Ethereum</td><td><code>0x3ee18B2214AFF97000D974cf647E7C347E8fa585</code></td></tr><tr><td>Solana</td><td><code>wormDTUJ6AWPNvk59vGQbDvGJmqbDTdgWgAqcLBCgUb</code></td></tr><tr><td>0G (Zero Gravity)</td><td><code>0xee12EBDdF6E34A206e1798D185317C846BC21638</code></td></tr><tr><td>Algorand</td><td><code>842126029</code></td></tr><tr><td>Aptos</td><td><code>0x576410486a2da45eee6c949c995670112ddf2fbeedab20350d506328eefc9d4f</code></td></tr><tr><td>Arbitrum</td><td><code>0x0b2402144Bb366A632D14B83F244D2e0e21bD39c</code></td></tr><tr><td>Avalanche</td><td><code>0x0e082F06FF657D94310cB8cE8B0D9a04541d8052</code></td></tr><tr><td>Base</td><td><code>0x8d2de8d2f73F1F4cAB472AC9A881C9b123C79627</code></td></tr><tr><td>Berachain</td><td><code>0x3Ff72741fd67D6AD0668d93B41a09248F4700560</code></td></tr><tr><td>BNB Smart Chain</td><td><code>0xB6F6D86a8f9879A9c87f643768d9efc38c1Da6E7</code></td></tr><tr><td>Celo</td><td><code>0x796Dff6D74F3E27060B71255Fe517BFb23C93eed</code></td></tr><tr><td>Fantom</td><td><code>0x7C9Fc5741288cDFdD83CeB07f3ea7e22618D79D2</code></td></tr><tr><td>Fogo</td><td><code>wormQuCVWSSmPdjVmEzAWxAXViVyTSWnLyhff5hVYGS</code></td></tr><tr><td>Injective</td><td><code>inj1ghd753shjuwexxywmgs4xz7x2q732vcnxxynfn</code></td></tr><tr><td>Ink</td><td><code>0x3Ff72741fd67D6AD0668d93B41a09248F4700560</code></td></tr><tr><td>Kaia</td><td><code>0x5b08ac39EAED75c0439FC750d9FE7E1F9dD0193F</code></td></tr><tr><td>Mantle</td><td><code>0x24850c6f61C438823F01B7A3BF2B89B72174Fa9d</code></td></tr><tr><td>MegaETH</td><td><code>0xF97B81E513f53c7a6B57Bd0b103a6c295b3096C5</code></td></tr><tr><td>Monad</td><td><code>0x0B2719cdA2F10595369e6673ceA3Ee2EDFa13BA7</code></td></tr><tr><td>Moonbeam</td><td><code>0xb1731c586ca89a23809861c6103f0b96b3f57d92</code></td></tr><tr><td>NEAR</td><td><code>contract.portalbridge.near</code></td></tr><tr><td>Optimism</td><td><code>0x1D68124e65faFC907325e3EDbF8c4d84499DAa8b</code></td></tr><tr><td>Polygon</td><td><code>0x5a58505a96D1dbf8dF91cB21B54419FC36e93fdE</code></td></tr><tr><td>Scroll</td><td><code>0x24850c6f61C438823F01B7A3BF2B89B72174Fa9d</code></td></tr><tr><td>Sei</td><td><code>sei1smzlm9t79kur392nu9egl8p8je9j92q4gzguewj56a05kyxxra0qy0nuf3</code></td></tr><tr><td>SeiEVM</td><td><code>0x3Ff72741fd67D6AD0668d93B41a09248F4700560</code></td></tr><tr><td>Sui</td><td><code>0xc57508ee0d4595e5a8728974a4a93a787d38f339757230d441e895422c07aba9</code></td></tr><tr><td>Unichain</td><td><code>0x3Ff72741fd67D6AD0668d93B41a09248F4700560</code></td></tr><tr><td>World Chain</td><td><code>0xc309275443519adca74c9136b02A38eF96E3a1f6</code></td></tr><tr><td>X Layer</td><td><code>0x5537857664B0f9eFe38C9f320F75fEf23234D904</code></td></tr><tr><td>XRPL-EVM</td><td><code>0x47F5195163270345fb4d7B9319Eda8C64C75E278</code></td></tr></tbody></table>

=== "Testnet"

    <table data-full-width="true" markdown><thead><th>Chain Name</th><th>Contract Address</th></thead><tbody><tr><td>Ethereum Holesky</td><td><code>0x76d093BbaE4529a342080546cAFEec4AcbA59EC6</code></td></tr><tr><td>Ethereum Sepolia</td><td><code>0xDB5492265f6038831E89f495670FF909aDe94bd9</code></td></tr><tr><td>Solana</td><td><code>DZnkkTmCiFWfYTfT41X3Rd1kDgozqzxWaHqsw6W4x2oe</code></td></tr><tr><td>0G (Zero Gravity)</td><td><code>0x7d8eBc211C4221eA18E511E4f0fD50c5A539f275</code></td></tr><tr><td>Algorand</td><td><code>86525641</code></td></tr><tr><td>Aptos</td><td><code>0x576410486a2da45eee6c949c995670112ddf2fbeedab20350d506328eefc9d4f</code></td></tr><tr><td>Arbitrum Sepolia</td><td><code>0xC7A204bDBFe983FCD8d8E61D02b475D4073fF97e</code></td></tr><tr><td>Avalanche</td><td><code>0x61E44E506Ca5659E6c0bba9b678586fA2d729756</code></td></tr><tr><td>Base Sepolia</td><td><code>0x86F55A04690fd7815A3D802bD587e83eA888B239</code></td></tr><tr><td>Berachain</td><td><code>0xa10f2eF61dE1f19f586ab8B6F2EbA89bACE63F7a</code></td></tr><tr><td>BNB Smart Chain</td><td><code>0x9dcF9D205C9De35334D646BeE44b2D2859712A09</code></td></tr><tr><td>Celo</td><td><code>0x05ca6037eC51F8b712eD2E6Fa72219FEaE74E153</code></td></tr><tr><td>Fantom</td><td><code>0x599CEa2204B4FaECd584Ab1F2b6aCA137a0afbE8</code></td></tr><tr><td>Fogo</td><td><code>78HdStBqCMioGii9D8mF3zQaWDqDZBQWTUwjjpdmbJKX</code></td></tr><tr><td>HyperEVM :material-alert:{ title='⚠️ The HyperEVM integration is experimental, as its node software is not open source. Use Wormhole messaging on HyperEVM with caution.' }</td><td><code>0x4a8bc80Ed5a4067f1CCf107057b8270E0cC11A78</code></td></tr><tr><td>Injective</td><td><code>inj1q0e70vhrv063eah90mu97sazhywmeegp7myvnh</code></td></tr><tr><td>Ink</td><td><code>0x376428e7f26D5867e69201b275553C45B09EE090</code></td></tr><tr><td>Kaia</td><td><code>0xC7A13BE098720840dEa132D860fDfa030884b09A</code></td></tr><tr><td>Linea</td><td><code>0xC7A204bDBFe983FCD8d8E61D02b475D4073fF97e</code></td></tr><tr><td>Mantle</td><td><code>0x75Bfa155a9D7A3714b0861c8a8aF0C4633c45b5D</code></td></tr><tr><td>MegaETH</td><td><code>0x3D5c2c2BEA15Af5D45F084834c535628C48c42A4</code></td></tr><tr><td>Mezo</td><td><code>0xA31aa3FDb7aF7Db93d18DDA4e19F811342EDF780</code></td></tr><tr><td>Moca</td><td><code>0xF97B81E513f53c7a6B57Bd0b103a6c295b3096C5</code></td></tr><tr><td>Monad Testnet</td><td><code>0xF97B81E513f53c7a6B57Bd0b103a6c295b3096C5</code></td></tr><tr><td>Moonbeam</td><td><code>0xbc976D4b9D57E57c3cA52e1Fd136C45FF7955A96</code></td></tr><tr><td>NEAR</td><td><code>token.wormhole.testnet</code></td></tr><tr><td>Optimism Sepolia</td><td><code>0x99737Ec4B815d816c49A385943baf0380e75c0Ac</code></td></tr><tr><td>Polygon Amoy</td><td><code>0xC7A204bDBFe983FCD8d8E61D02b475D4073fF97e</code></td></tr><tr><td>Scroll</td><td><code>0x22427d90B7dA3fA4642F7025A854c7254E4e45BF</code></td></tr><tr><td>Sei</td><td><code>sei1jv5xw094mclanxt5emammy875qelf3v62u4tl4lp5nhte3w3s9ts9w9az2</code></td></tr><tr><td>SeiEVM</td><td><code>0x23908A62110e21C04F3A4e011d24F901F911744A</code></td></tr><tr><td>Sui</td><td><code>0x6fb10cdb7aa299e9a4308752dadecb049ff55a892de92992a1edbd7912b3d6da</code></td></tr><tr><td>Unichain</td><td><code>0xa10f2eF61dE1f19f586ab8B6F2EbA89bACE63F7a</code></td></tr><tr><td>World Chain</td><td><code>0x430855B4D43b8AEB9D2B9869B74d58dda79C0dB2</code></td></tr><tr><td>X Layer</td><td><code>0xdA91a06299BBF302091B053c6B9EF86Eff0f930D</code></td></tr><tr><td>XRPL-EVM</td><td><code>0x7d8eBc211C4221eA18E511E4f0fD50c5A539f275</code></td></tr></tbody></table>

=== "Devnet"

    <table data-full-width="true" markdown><thead><th>Chain Name</th><th>Contract Address</th></thead><tbody><tr><td>Ethereum</td><td><code>0x0290FB167208Af455bB137780163b7B7a9a10C16</code></td></tr><tr><td>Solana</td><td><code>B6RHG3mfcckmrYN1UhmJzyS1XX3fZKbkeUcpJe9Sy3FE</code></td></tr><tr><td>Algorand</td><td><code>1006</code></td></tr><tr><td>Aptos</td><td><code>0x84a5f374d29fc77e370014dce4fd6a55b58ad608de8074b0be5571701724da31</code></td></tr><tr><td>BNB Smart Chain</td><td><code>0x0290FB167208Af455bB137780163b7B7a9a10C16</code></td></tr><tr><td>NEAR</td><td><code>token.test.near</code></td></tr><tr><td>Sui</td><td><code>0xa6a3da85bbe05da5bfd953708d56f1a3a023e7fb58e5a824a3d4de3791e8f690</code></td></tr></tbody></table>

## CCTP



=== "Mainnet"

    <table data-full-width="true" markdown><thead><th>Chain Name</th><th>Contract Address</th></thead><tbody><tr><td>Ethereum</td><td><code>0xAaDA05BD399372f0b0463744C09113c137636f6a</code></td></tr><tr><td>Arbitrum</td><td><code>0x2703483B1a5a7c577e8680de9Df8Be03c6f30e3c</code></td></tr><tr><td>Avalanche</td><td><code>0x09Fb06A271faFf70A651047395AaEb6265265F13</code></td></tr><tr><td>Base</td><td><code>0x03faBB06Fa052557143dC28eFCFc63FC12843f1D</code></td></tr><tr><td>Optimism</td><td><code>0x2703483B1a5a7c577e8680de9Df8Be03c6f30e3c</code></td></tr><tr><td>Polygon</td><td><code>0x0FF28217dCc90372345954563486528aa865cDd6</code></td></tr></tbody></table>

=== "Testnet"

    <table data-full-width="true" markdown><thead><th>Chain Name</th><th>Contract Address</th></thead><tbody><tr><td>Ethereum Sepolia</td><td><code>0x2703483B1a5a7c577e8680de9Df8Be03c6f30e3c</code></td></tr><tr><td>Arbitrum Sepolia</td><td><code>0x2703483B1a5a7c577e8680de9Df8Be03c6f30e3c</code></td></tr><tr><td>Avalanche</td><td><code>0x58f4c17449c90665891c42e14d34aae7a26a472e</code></td></tr><tr><td>Base Sepolia</td><td><code>0x2703483B1a5a7c577e8680de9Df8Be03c6f30e3c</code></td></tr><tr><td>Optimism Sepolia</td><td><code>0x2703483B1a5a7c577e8680de9Df8Be03c6f30e3c</code></td></tr></tbody></table>

## Settlement Token Router

=== "Mainnet"

    <table data-full-width="true" markdown><thead><tr><th>Chain Name</th><th>Contract Address</th></tr></thead><tbody><tr><td>Ethereum</td><td><code>0x70287c79ee41C5D1df8259Cd68Ba0890cd389c47</code></td></tr><tr><td>Solana</td><td><code>28topqjtJzMnPaGFmmZk68tzGmj9W9aMntaEK3QkgtRe</code></td></tr><tr><td>Arbitrum</td><td><code>0x70287c79ee41C5D1df8259Cd68Ba0890cd389c47</code></td></tr><tr><td>Avalanche</td><td><code>0x70287c79ee41C5D1df8259Cd68Ba0890cd389c47</code></td></tr><tr><td>Base</td><td><code>0x70287c79ee41C5D1df8259Cd68Ba0890cd389c47</code></td></tr><tr><td>Optimism</td><td><code>0x70287c79ee41C5D1df8259Cd68Ba0890cd389c47</code></td></tr><tr><td>Polygon</td><td><code>0x70287c79ee41C5D1df8259Cd68Ba0890cd389c47</code></td></tr></tbody></table>

=== "Testnet"

    <table data-full-width="true" markdown><thead><tr><th>Chain Name</th><th>Contract Address</th></tr></thead><tbody><tr><td>Solana</td><td><code>tD8RmtdcV7bzBeuFgyrFc8wvayj988ChccEzRQzo6md</code></td></tr><tr><td>Arbitrum Sepolia</td><td><code>0xe0418C44F06B0b0D7D1706E01706316DBB0B210E</code></td></tr><tr><td>Optimism Sepolia</td><td><code>0x6BAa7397c18abe6221b4f6C3Ac91C88a9faE00D8</code></td></tr></tbody></table>

## Executor



=== "Mainnet"

    <table data-full-width="true" markdown><thead><th>Chain Name</th><th>Contract Address</th></thead><tbody><tr><td>Ethereum</td><td><code>0x84EEe8dBa37C36947397E1E11251cA9A06Fc6F8a</code></td></tr><tr><td>Solana</td><td><code>execXUrAsMnqMmTHj5m7N1YQgsDz3cwGLYCYyuDRciV</code></td></tr><tr><td>0G (Zero Gravity)</td><td><code>0xcD2BffD0C0289e8C0cb89c458dB1B74f1892Fa6c</code></td></tr><tr><td>Aptos</td><td><code>0x11aa75c059e1a7855be66b931bf340a2e0973274ac16b5f519c02ceafaf08a18</code></td></tr><tr><td>Arbitrum</td><td><code>0x3980f8318fc03d79033Bbb421A622CDF8d2Eeab4</code></td></tr><tr><td>Avalanche</td><td><code>0x4661F0E629E4ba8D04Ee90080Aee079740B00381</code></td></tr><tr><td>Base</td><td><code>0x9E1936E91A4a5AE5A5F75fFc472D6cb8e93597ea</code></td></tr><tr><td>Berachain</td><td><code>0x0Dd7a5a32311b8D87A615Cc7f079B632D3d5e2D3</code></td></tr><tr><td>BNB Smart Chain</td><td><code>0xeC8cCCD058DbF28e5D002869Aa9aFa3992bf4ee0</code></td></tr><tr><td>Celo</td><td><code>0xe6Ea5087c6860B94Cf098a403506262D8F28cF05</code></td></tr><tr><td>CreditCoin</td><td><code>0xd2e420188f17607Aa6344ee19c3e76Cf86CA7BDe</code></td></tr><tr><td>Fogo</td><td><code>execXUrAsMnqMmTHj5m7N1YQgsDz3cwGLYCYyuDRciV</code></td></tr><tr><td>HyperEVM :material-alert:{ title='⚠️ The HyperEVM integration is experimental, as its node software is not open source. Use Wormhole messaging on HyperEVM with caution.' }</td><td><code>0xd7717899cc4381033Bc200431286D0AC14265F78</code></td></tr><tr><td>Ink</td><td><code>0x3e44a5F45cbD400acBEF534F51e616043B211Ddd</code></td></tr><tr><td>Linea</td><td><code>0x23aF2B5296122544A9A7861da43405D5B15a9bD3</code></td></tr><tr><td>MegaETH</td><td><code>0xD405E0A1f3f9edc25Ea32d0B079d6118328b2EcB</code></td></tr><tr><td>Mezo</td><td><code>0x0f9b8E144Cc5C5e7C0073829Afd30F26A50c5606</code></td></tr><tr><td>Moca</td><td><code>0x7b8097af5459846c5A72fCc960D94F31C05915aD</code></td></tr><tr><td>Monad</td><td><code>0xC04dE634982cAdF2A677310b73630B7Ac56A3f65</code></td></tr><tr><td>Moonbeam</td><td><code>0x85D06449C78064c2E02d787e9DC71716786F8D19</code></td></tr><tr><td>Optimism</td><td><code>0x85B704501f6AE718205C0636260768C4e72ac3e7</code></td></tr><tr><td>Polygon</td><td><code>0x0B23efA164aB3eD08e9a39AC7aD930Ff4F5A5e81</code></td></tr><tr><td>Scroll</td><td><code>0xcFAdDE24640e395F5A71456A825D0D7C3741F075</code></td></tr><tr><td>SeiEVM</td><td><code>0x25f1c923fb7a5aefa5f0a2b419fc70f2368e66e5</code></td></tr><tr><td>Sonic</td><td><code>0x3Fdc36b4260Da38fBDba1125cCBD33DD0AC74812</code></td></tr><tr><td>Sui</td><td><code>0xdb0fe8bb1e2b5be628adbea0636063325073e1070ee11e4281457dfd7f158235</code></td></tr><tr><td>Unichain</td><td><code>0x764dD868eAdD27ce57BCB801E4ca4a193d231Aed</code></td></tr><tr><td>World Chain</td><td><code>0x8689b4E6226AdC8fa8FF80aCc3a60AcE31e8804B</code></td></tr><tr><td>XRPL-EVM</td><td><code>0x8345E90Dcd92f5Cf2FAb0C8E2A56A5bc2c30d896</code></td></tr></tbody></table>

=== "Testnet"

    <table data-full-width="true" markdown><thead><th>Chain Name</th><th>Contract Address</th></thead><tbody><tr><td>Ethereum Sepolia</td><td><code>0xD0fb39f5a3361F21457653cB70F9D0C9bD86B66B</code></td></tr><tr><td>Solana</td><td><code>execXUrAsMnqMmTHj5m7N1YQgsDz3cwGLYCYyuDRciV</code></td></tr><tr><td>0G (Zero Gravity)</td><td><code>0x7C43825EeB76DF7aAf3e1D2e8f684d4876F0CC05</code></td></tr><tr><td>Aptos</td><td><code>0x139717c339f08af674be77143507a905aa28cbc67a0e53e7095c07b630d73815</code></td></tr><tr><td>Arbitrum Sepolia</td><td><code>0xBF161de6B819c8af8f2230Bcd99a9B3592f6F87b</code></td></tr><tr><td>Avalanche</td><td><code>0x4661F0E629E4ba8D04Ee90080Aee079740B00381</code></td></tr><tr><td>Base Sepolia</td><td><code>0x51B47D493CBA7aB97e3F8F163D6Ce07592CE4482</code></td></tr><tr><td>BNB Smart Chain</td><td><code>0xeC8cCCD058DbF28e5D002869Aa9aFa3992bf4ee0</code></td></tr><tr><td>Converge</td><td><code>0xAab9935349B9c08e0e970720F6D640d5B91C293E</code></td></tr><tr><td>Fogo</td><td><code>execXUrAsMnqMmTHj5m7N1YQgsDz3cwGLYCYyuDRciV</code></td></tr><tr><td>Linea</td><td><code>0x4f6c3a93a80DdC691312974DAAbf9B6e4Bb44111</code></td></tr><tr><td>Mezo</td><td><code>0x0f9b8E144Cc5C5e7C0073829Afd30F26A50c5606</code></td></tr><tr><td>Moca</td><td><code>0xc4a03f2c47caA4b961101bAD6338DEf37376F052</code></td></tr><tr><td>Monad Testnet</td><td><code>0xe37D3E162B4B1F17131E4e0e6122DbA31243382f</code></td></tr><tr><td>Optimism Sepolia</td><td><code>0x5856651eB82aeb6979B4954317194d48e1891b3c</code></td></tr><tr><td>Plume</td><td><code>0x8fc2FbA8F962fbE89a9B02f03557a011c335A455</code></td></tr><tr><td>Polygon Amoy</td><td><code>0x7056721C33De437f0997F67BC87521cA86b721d3</code></td></tr><tr><td>SeiEVM</td><td><code>0x25f1c923Fb7A5aEFA5F0A2b419fC70f2368e66e5</code></td></tr><tr><td>Sui</td><td><code>0x4000cfe2955d8355b3d3cf186f854fea9f787a457257056926fde1ec977670eb</code></td></tr><tr><td>Unichain</td><td><code>0x764dD868eAdD27ce57BCB801E4ca4a193d231Aed</code></td></tr><tr><td>XRPL-EVM</td><td><code>0x4d9525D94D275dEB495b7C8840b154Ae04cfaC2A</code></td></tr></tbody></table>

## Quoter Router



=== "Mainnet"

    <table data-full-width="true" markdown><thead><th>Chain Name</th><th>Contract Address</th></thead><tbody><tr><td>Ethereum</td><td><code>0xF22F1c0A3a8Cb42F695601731974784C499C4EF3</code></td></tr><tr><td>Arbitrum</td><td><code>0x32eec14c963c23176bd8951f192292006756bDcC</code></td></tr><tr><td>Avalanche</td><td><code>0xA3a2A615774d34c6a4dF443C488B084eacaBd2D0</code></td></tr><tr><td>Base</td><td><code>0x265fd0500a430d65d6D79Cd8707F24C048604658</code></td></tr><tr><td>BNB Smart Chain</td><td><code>0xc921F293c27F332D47283174b11C872295624Edb</code></td></tr><tr><td>Ink</td><td><code>0xdEC050E66BEb2f0d5507761A0fE4867839bd88D2</code></td></tr><tr><td>Monad</td><td><code>0x3d9282A8e9a3cdd9b25AE969eff4705a1Fe75F34</code></td></tr><tr><td>Optimism</td><td><code>0xa3B6551cCbB5Fe1dc33b71EE3590B1Df22ae75B3</code></td></tr><tr><td>Plume</td><td><code>0x85BA1B2A2195be51Ab715be458B32B120532d230</code></td></tr><tr><td>Polygon</td><td><code>0x2a856931603930B827B1A4352FB4D66fA029F123</code></td></tr><tr><td>Sei</td><td><code>0x1D6FeA87671F7c5E184F4c59c3BdcEc5CFC3eC1c</code></td></tr></tbody></table>

=== "Testnet"

    <table data-full-width="true" markdown><thead><th>Chain Name</th><th>Contract Address</th></thead><tbody><tr><td>Ethereum Sepolia</td><td><code>0xc0C35D7bfBc4175e0991Ae294f561b433eA4158f</code></td></tr><tr><td>Solana</td><td><code>qtrrrV7W3E1jnX1145wXR6ZpthG19ur5xHC1n6PPhDV</code></td></tr><tr><td>Arbitrum Sepolia</td><td><code>0x5E8c14F436c9ed2ff2E8B042B0542136bf108C6f</code></td></tr><tr><td>Avalanche</td><td><code>0xA3a2A615774d34c6a4dF443C488B084eacaBd2D0</code></td></tr><tr><td>Base Sepolia</td><td><code>0x2507d6899C3D4b93BF46b555d0cB401f44065772</code></td></tr><tr><td>Optimism Sepolia</td><td><code>0x6a829dF7C91f35f9aD72Cd5d05550b95BbC9fd2F</code></td></tr><tr><td>Polygon Amoy</td><td><code>0xE00444636DA924FBAe94471d73D56b5E03cA781c</code></td></tr><tr><td>Sei</td><td><code>0x1D6FeA87671F7c5E184F4c59c3BdcEc5CFC3eC1c</code></td></tr></tbody></table>

!!! note
    Wormhole Labs’ Quoter uses the following public keys:

    - **Mainnet**: `0xa54008017941EcE968623a0Dd8Ee907E2b133596`.
    - **Testnet**: `0x5241c9276698439fef2780dbab76fec90b633fbd`.
## Wormhole Labs Quoter Implementation



=== "Mainnet"

    <table data-full-width="true" markdown><thead><th>Chain Name</th><th>Contract Address</th></thead><tbody><tr><td>Ethereum</td><td><code>0xA25862D222Eb8343505c12d96e097e4332468D60</code></td></tr><tr><td>Arbitrum</td><td><code>0xA25862D222Eb8343505c12d96e097e4332468D60</code></td></tr><tr><td>Avalanche</td><td><code>0xA25862D222Eb8343505c12d96e097e4332468D60</code></td></tr><tr><td>Base</td><td><code>0xA25862D222Eb8343505c12d96e097e4332468D60</code></td></tr><tr><td>BNB Smart Chain</td><td><code>0xA25862D222Eb8343505c12d96e097e4332468D60</code></td></tr><tr><td>Ink</td><td><code>0xA25862D222Eb8343505c12d96e097e4332468D60</code></td></tr><tr><td>Monad</td><td><code>0xA25862D222Eb8343505c12d96e097e4332468D60</code></td></tr><tr><td>Optimism</td><td><code>0xA25862D222Eb8343505c12d96e097e4332468D60</code></td></tr><tr><td>Plume</td><td><code>0xA25862D222Eb8343505c12d96e097e4332468D60</code></td></tr><tr><td>Polygon</td><td><code>0xA25862D222Eb8343505c12d96e097e4332468D60</code></td></tr><tr><td>Sei</td><td><code>0xA25862D222Eb8343505c12d96e097e4332468D60</code></td></tr></tbody></table>

=== "Testnet"

    <table data-full-width="true" markdown><thead><th>Chain Name</th><th>Contract Address</th></thead><tbody><tr><td>Ethereum Sepolia</td><td><code>0x5a6c5A46082D029FDD7c5cF8265047E0c4BB2089</code></td></tr><tr><td>Solana</td><td><code>qtrxiqVAfVS61utwZLUi7UKugjCgFaNxBGyskmGingz</code></td></tr><tr><td>Arbitrum Sepolia</td><td><code>0x5a6c5A46082D029FDD7c5cF8265047E0c4BB2089</code></td></tr><tr><td>Avalanche</td><td><code>0x5a6c5A46082D029FDD7c5cF8265047E0c4BB2089</code></td></tr><tr><td>Base Sepolia</td><td><code>0x5a6c5A46082D029FDD7c5cF8265047E0c4BB2089</code></td></tr><tr><td>Optimism Sepolia</td><td><code>0x5a6c5A46082D029FDD7c5cF8265047E0c4BB2089</code></td></tr><tr><td>Polygon Amoy</td><td><code>0x5a6c5A46082D029FDD7c5cF8265047E0c4BB2089</code></td></tr><tr><td>Sei</td><td><code>0x5a6c5A46082D029FDD7c5cF8265047E0c4BB2089</code></td></tr></tbody></table>

!!! note
    Wormhole Labs’ Quoter uses the following public keys:

    - **Mainnet**: `0xa54008017941EcE968623a0Dd8Ee907E2b133596`.
    - **Testnet**: `0x5241c9276698439fef2780dbab76fec90b633fbd`.
## Guardian Governance

=== "Mainnet"

    
    <table data-full-width="true" markdown><thead><th>Chain Name</th><th>Contract Address</th></thead><tbody><tr><td>Ethereum</td><td><code>0x23Fea5514DFC9821479fBE18BA1D7e1A61f6FfCf</code></td></tr><tr><td>Solana</td><td><code>NGoD1yTeq5KaURrZo7MnCTFzTA4g62ygakJCnzMLCfm (see note below!)</code></td></tr><tr><td>Arbitrum</td><td><code>0x36CF4c88FA548c6Ad9fcDc696e1c27Bb3306163F</code></td></tr><tr><td>Avalanche</td><td><code>0x169D91C797edF56100F1B765268145660503a423</code></td></tr><tr><td>Base</td><td><code>0x838a95B6a3E06B6f11C437e22f3C7561a6ec40F1</code></td></tr><tr><td>BNB Smart Chain</td><td><code>0x8E4dc685e990379b8D53EcA47841E09B8d30043e</code></td></tr><tr><td>Fogo</td><td><code>ngoLQ35zgtP3SxWrjAJ8Mz2H8BPFVeZoxyBPotPYwnB (see note below!)</code></td></tr><tr><td>HyperEVM :material-alert:{ title='⚠️ The HyperEVM integration is experimental, as its node software is not open source. Use Wormhole messaging on HyperEVM with caution.' }</td><td><code>0x574B7864119C9223A9870Ea614dC91A8EE09E512</code></td></tr><tr><td>MegaETH</td><td><code>0x574B7864119C9223A9870Ea614dC91A8EE09E512</code></td></tr><tr><td>Monad</td><td><code>0x574B7864119C9223A9870Ea614dC91A8EE09E512</code></td></tr><tr><td>Optimism</td><td><code>0x0E09a3081837ff23D2e59B179E0Bc48A349Afbd8</code></td></tr><tr><td>Unichain</td><td><code>0x574b7864119c9223a9870ea614dc91a8ee09e512</code></td></tr><tr><td>XRPL-EVM</td><td><code>0x574B7864119C9223A9870Ea614dC91A8EE09E512</code></td></tr><tr><td>Sui</td><td><code>See note below!</code></td></tr></tbody></table>
    

=== "Testnet"

    
    <table data-full-width="true" markdown><thead><th>Chain Name</th><th>Contract Address</th></thead><tbody><tr><td>Ethereum Sepolia</td><td><code>0x9517F0164c1d089ad72E669E57b9088790966dBd</code></td></tr><tr><td>Solana</td><td><code>NGoD1yTeq5KaURrZo7MnCTFzTA4g62ygakJCnzMLCfm</code></td></tr><tr><td>Arbitrum Sepolia</td><td><code>0x81b65A48DCAccBA04aCa3C055C4112b0715b90c0</code></td></tr><tr><td>Base Sepolia</td><td><code>0x720A59128B96Eda6EC2940c7899406E4dc56d0DC</code></td></tr><tr><td>Optimism Sepolia</td><td><code>0xcE1DE1eA4b040D324a07719043A6234C94fd0b5d</code></td></tr><tr><td>XRPL-EVM</td><td><code>0x574B7864119C9223A9870Ea614dC91A8EE09E512</code></td></tr></tbody></table>
    
!!! note
    Guardian-governed ownership contracts are used where an owner is required, without adding new trust assumptions. They only accept instructions signed by a quorum of Wormhole Guardians, validated on-chain by the Wormhole Core contracts. Implementations: [EVM](https://github.com/wormhole-foundation/native-token-transfers/blob/main/evm/src/wormhole/Governance.sol){target=\_blank} and [SVM](https://github.com/wormhole-foundation/native-token-transfers/blob/main/solana/programs/wormhole-governance/src/instructions/governance.rs){target=\_blank}.

    On SVM chains (Solana, Fogo), deployments set the admin to a [governance PDA](https://solana.com/docs/core/pda){target=\_blank} derived from the Guardian governance program. The admin address may differ from the program ID when inspecting deployments on-chain.

    The following governance PDAs are used as the admin for deployments on SVM chains:

    - **Solana:** `4iUtozoQLdJ2FV7vXe9q215ETSw1Mnt8WKP4NyqNgAxz`.
    - **Fogo:** `nWfGbhWvREnvF1zCvhrXiKidzDJ8DzCdHb13YYZeVkV`.

    On Sui, separate instances of the Move governance contract need to be deployed for each individual token due to technical reasons. The NTT CLI is able to perform such deployments for your token via "ntt sui deploy-governance --transfer".


## Delegated Guardians

=== "Mainnet"

    <table data-full-width="true" markdown><thead><tr><th>Chain Name</th><th>Contract Address</th></tr></thead><tbody><tr><td>Ethereum</td><td><code>0x1462800febd49232798132e8c8b721aa86c4c209</code></td></tr></tbody></table>

## IBC

This configuration is for the `ibc` feature for guardians.

=== "Mainnet"

    <table data-full-width="true" markdown><thead><tr><th>Chain Name</th><th>Contract Address</th></tr></thead><tbody><tr><td>Wormchain</td><td><code>wormhole1wkwy0xh89ksdgj9hr347dyd2dw7zesmtrue6kfzyml4vdtz6e5ws2y050r</code></td></tr></tbody></table>

## Gateway

This configuration is for the `gatewayContract` guardian configuration.

=== "Mainnet"

    <table data-full-width="true" markdown><thead><tr><th>Chain Name</th><th>Contract Address</th></tr></thead><tbody><tr><td>Wormchain</td><td><code>wormhole1ufs3tlq4umljk0qfe8k5ya0x6hpavn897u2cnf9k0en9jr7qarqqaqfk2j</code></td></tr></tbody></table>

## Read-Only Deployments

=== "Mainnet"

    <table data-full-width="true" markdown><thead><th>Chain Name</th><th>Contract Address</th></thead><tbody>
    <tr><td>Acala</td><td><code>0xa321448d90d4e5b0A732867c18eA198e75CAC48E</code></td></tr>
    <tr><td>Aurora</td><td><code>0x51b5123a7b0F9b2bA265f9c4C8de7D78D52f510F</code></td></tr>
    <tr><td>Blast</td><td><code>0xbebdb6C8ddC678FfA9f8748f85C815C556Dd8ac6</code></td></tr>
    <tr><td>Corn</td><td><code>0xa683c66045ad16abb1bCE5ad46A64d95f9A25785</code></td></tr>
    <tr><td>Gnosis</td><td><code>0xa321448d90d4e5b0A732867c18eA198e75CAC48E</code></td></tr>
    <tr><td>Goat</td><td><code>0x352A86168e6988A1aDF9A15Cb00017AAd3B67155</code></td></tr>
    <tr><td>Karura</td><td><code>0xa321448d90d4e5b0A732867c18eA198e75CAC48E</code></td></tr>
    <tr><td>LightLink</td><td><code>0x352A86168e6988A1aDF9A15Cb00017AAd3B67155</code></td></tr>
    <tr><td>Oasis</td><td><code>0xfE8cD454b4A1CA468B57D79c0cc77Ef5B6f64585</code></td></tr>
    <tr><td>Rootstock</td><td><code>0xbebdb6C8ddC678FfA9f8748f85C815C556Dd8ac6</code></td></tr>
    <tr><td>Sonic</td><td><code>0x352A86168e6988A1aDF9A15Cb00017AAd3B67155</code></td></tr>
    <tr><td>Telos</td><td><code>0x352A86168e6988A1aDF9A15Cb00017AAd3B67155</code></td></tr>
    <tr><td>Terra</td><td><code>terra1dq03ugtd40zu9hcgdzrsq6z2z4hwhc9tqk2uy5</code></td></tr>
    <tr><td>Terra 2.0</td><td><code>terra12mrnzvhx3rpej6843uge2yyfppfyd3u9c3uq223q8sl48huz9juqffcnhp</code></td></tr>
    <tr><td>SNAXchain</td><td><code>0xc1BA3CC4bFE724A08FbbFbF64F8db196738665f4</code></td></tr>
    <tr><td>XPLA</td><td><code>xpla1jn8qmdda5m6f6fqu9qv46rt7ajhklg40ukpqchkejcvy8x7w26cqxamv3w</code></td></tr>
    </tbody>
    </table>
!!! note
    Read-only deployments allow Wormhole messages to be received on chains not fully integrated with Wormhole Guardians. These deployments support cross-chain data verification but cannot originate messages. For example, a governance message can be sent from a fully integrated chain and processed on a read-only chain, but the read-only chain cannot send messages back.


---

Page Title: Core Contract (EVM)

- Resolved Markdown: https://wormhole.com/docs/ai/pages/products-messaging-reference-core-contract-evm.md
- Canonical (HTML): https://wormhole.com/docs/products/messaging/reference/core-contract-evm/
- Summary: Reference for the Wormhole Core contract on EVM chains. Covers the proxy structure, components, state variables, functions, events, and errors.
- Word Count: 1963; Token Estimate: 4016

# Core Contract (EVM)

The [Wormhole Core Contract on EVM](https://github.com/wormhole-foundation/wormhole/blob/main/ethereum/contracts/Implementation.sol){target=\_blank} chains is a proxy-based contract responsible for receiving and verifying Wormhole messages (VAAs). It implements the messaging interface and delegates logic to upgradeable implementation contracts.

## Structure Overview

The Wormhole Core system consists of a proxy contract and a modular implementation constructed through layered inheritance.

```text
Wormhole.sol (Proxy)
└── Implementation.sol
    └── Governance.sol
        ├── Getters.sol
        ├── GovernanceStructs.sol
        ├── Messages.sol
        ├── Setters.sol
        └── Structs.sol
```

**Key Components:**

 - **Wormhole.sol**: The upgradeable proxy contract that delegates all logic to `Implementation.sol`.
 - **Implementation.sol**: The main logic contract, which handles message publication and initialization. Inherits from Governance.sol.
 - **Governance.sol**: Core governance logic for processing upgrades, setting fees, and updating the Guardian set. Also responsible for verifying governance VAAs and performing privileged actions.
 - **Getters.sol**: Exposes view functions to access internal contract state, such as current Guardian sets, fees, and contract configuration.
 - **GovernanceStructs.sol**: Provides structures and helpers for processing governance-related VAAs.
 - **Messages.sol**: Handles VAA parsing and verification.
 - **Setters.sol**: Contains internal functions for mutating contract state.
 - **Structs.sol**: Defines core data structures like GuardianSet and VM (VAA Message) used across multiple modules.

## State Variables

 - **`provider` ++"Structs.Provider"++**: Holds metadata like `chainId`, `governanceChainId`, and `governanceContract`. This is a nested struct.
 - **`guardianSets` ++"mapping(uint32 => GuardianSet)"++**: Mapping of all Guardian sets by index.
 - **`guardianSetIndex` ++"uint32"++**: Index of the currently active Guardian set.
 - **`guardianSetExpiry` ++"uint32"++**: How long a Guardian set remains valid after it's replaced (in seconds).
 - **`sequences` ++"mapping(address => uint64)"++**: Tracks message sequences per emitter (used to enforce message ordering).
 - **`consumedGovernanceActions` ++"mapping(bytes32 => bool)"++**: Used to prevent governance VAAs from being reused (replay protection).
 - **`initializedImplementations` ++"mapping(address => bool)"++**: Tracks which implementation addresses have been initialized (for upgrade safety).
 - **`messageFee` ++"uint256"++**: The amount (in native gas token) required to post a message. Set via governance.
 - **`evmChainId` ++"uint256"++**: The actual EVM chain ID (e.g., 1 for Ethereum, 10 for Optimism). Used in fork recovery.

## Events

### LogMessagePublished

Emitted when a message is published via `publishMessage`. *(Defined in [Implementation.sol](https://github.com/wormhole-foundation/wormhole/blob/main/ethereum/contracts/Implementation.sol){target=\_blank})*

```solidity
event LogMessagePublished(
    address indexed sender,
    uint64 sequence,
    uint32 nonce,
    bytes payload,
    uint8 consistencyLevel
)
```

??? interface "Parameters"

    `sender` ++"address"++  

    Address that called `publishMessage`.

    ---

    `sequence` ++"uint64"++

    The sequence number of the message.

    ---

    `nonce` ++"uint32"++

    The provided nonce.

    ---

    `payload` ++"bytes"++

    The payload that was published.

    ---

    `consistencyLevel` ++"uint8"++

    Finality level requested.

### ContractUpgraded

Emitted when the Core Contract is upgraded to a new implementation via governance. *(Defined in [Governance.sol](https://github.com/wormhole-foundation/wormhole/blob/main/ethereum/contracts/Governance.sol){target=\_blank})*

```solidity
event ContractUpgraded(
    address indexed oldContract,
    address indexed newContract
)
```

??? interface "Parameters"

    `oldContract` ++"address"++

    The address of the previous implementation.

    ---

    `newContract` ++"address"++

    The address of the new implementation.

### GuardianSetAdded

Emitted when a new Guardian set is registered via governance. *(Defined in [Governance.sol](https://github.com/wormhole-foundation/wormhole/blob/main/ethereum/contracts/Governance.sol){target=\_blank})*

```solidity
event GuardianSetAdded(
    uint32 indexed index
)
```

??? interface "Parameters"

    `index` ++"uint32"++

    Index of the newly added Guardian set.

### LogGuardianSetChanged

Emitted when the active Guardian set is changed. *(Defined in [State.sol](https://github.com/wormhole-foundation/wormhole/blob/main/ethereum/contracts/State.sol){target=\_blank})*

```solidity
event LogGuardianSetChanged(
    uint32 oldGuardianIndex,
    uint32 newGuardianIndex
)
```

??? interface "Parameters"

    `oldGuardianIndex` ++"uint32"++

    The previous active Guardian set index.

    ---

    `newGuardianIndex` ++"uint32"++

    The new active Guardian set index.

## Functions

### publishMessage

Publishes a message to Wormhole's Guardian Network. *(Defined in [Implementation.sol](https://github.com/wormhole-foundation/wormhole/blob/main/ethereum/contracts/Implementation.sol){target=\_blank})*

```solidity
function publishMessage(
    uint32 nonce,
    bytes memory payload,
    uint8 consistencyLevel
) public payable returns (uint64 sequence)
```

??? interface "Parameters"

    `nonce` ++"uint32"++

    Custom sequence identifier for the emitter.

    ---

    `payload` ++"bytes"++

    Arbitrary user data to be included in the message.

    ---

    `consistencyLevel` ++"uint8"++

    Finality requirement for Guardian attestation (e.g., safe or finalized).

??? interface "Returns"

    `sequence` ++"uint64"++

    Unique sequence number assigned to this message.

### getCurrentGuardianSetIndex

Returns the index of the currently active Guardian set. *(Defined in [Getters.sol](https://github.com/wormhole-foundation/wormhole/blob/main/ethereum/contracts/Getters.sol){target=\_blank})*

Each VAA includes the index of the Guardian set that signed it. This function allows contracts to retrieve the current index, ensuring the VAA is verified against the correct set.

```solidity
function getCurrentGuardianSetIndex() external view returns (uint32)
```

??? interface "Returns"

    `index` ++"uint32"++

    The index of the active Guardian set used to verify signatures.

### getGuardianSet

Retrieves metadata for a given Guardian set index. *(Defined in [Getters.sol](https://github.com/wormhole-foundation/wormhole/blob/main/ethereum/contracts/Getters.sol){target=\_blank})*

```solidity
function getGuardianSet(uint32 index) external view returns (address[] memory keys, uint32 expirationTime)
```

??? interface "Parameters"

    `index` ++"uint32"++

    Guardian set index to query.

??? interface "Returns"

    `keys` ++"address[]"++

    Public keys of the guardians in this set.

    ---

    `expirationTime` ++"uint32"++

    Timestamp after which the Guardian set is considered expired.

### getGuardianSetExpiry

Returns the expiration time of a specific Guardian set index. *(Defined in [Getters.sol](https://github.com/wormhole-foundation/wormhole/blob/main/ethereum/contracts/Getters.sol){target=\_blank})*

```solidity
function getGuardianSetExpiry(uint32 index) external view returns (uint32)
```

??? interface "Parameters"

    `index` ++"uint32"++

    The index of the Guardian set to query.

??? interface "Returns"

    `expiry` ++"uint32"++

    UNIX timestamp after which the set is no longer valid.

### messageFee

Returns the current fee (in native tokens) required to publish a message. *(Defined in [Getters.sol](https://github.com/wormhole-foundation/wormhole/blob/main/ethereum/contracts/Getters.sol){target=\_blank})*

```solidity
function messageFee() public view returns (uint256)
```

??? interface "Returns"

    `fee` ++"uint256"++

    Fee in Wei required to publish a message successfully. Must be sent as `msg.value`.

### nextSequence

Retrieves the next sequence number for a given emitter address. *(Defined in [Getters.sol](https://github.com/wormhole-foundation/wormhole/blob/main/ethereum/contracts/Getters.sol){target=\_blank})*

```solidity
function nextSequence(address emitter) external view returns (uint64)
```

??? interface "Parameters"

    `emitter` ++"address"++

    The address for which the next sequence will be issued.

??? interface "Returns"

    `sequence` ++"uint64"++

    The next sequence number for the specified emitter.

### parseAndVerifyVM

Verifies signatures and parses a signed VAA. *(Defined in [Messages.sol](https://github.com/wormhole-foundation/wormhole/blob/main/ethereum/contracts/Messages.sol){target=\_blank})*

```solidity
function parseAndVerifyVM(bytes memory encodedVM)
    external
    view
    returns (
        VM memory vm,
        bool valid,
        string memory reason
    )
```

??? interface "Parameters"

    `encodedVM` ++"bytes"++

    Serialized signed VAA from Guardians.

??? interface "Returns"

    `vm` ++"VM memory"++

    Full parsed VAA contents

    ---

    `valid` ++"bool"++

    Whether the VAA is valid according to the current Guardian set.

    ---

    `reason` ++"string"++

    Reason for invalidity if `valid` is false (invalid).

### verifyVM

Performs low-level VAA signature verification. *(Defined in [Messages.sol](https://github.com/wormhole-foundation/wormhole/blob/main/ethereum/contracts/Messages.sol){target=\_blank})*

```solidity
function verifyVM(bytes memory encodedVM)
    public view returns (bool isValid, string memory reason)
```

??? interface "Parameters"

    `encodedVM` ++"bytes"++

    Serialized signed VAA to verify.

??? interface "Returns"

    `isValid` ++"bool"++

    `true` if the signatures are valid and meet the quorum.

    ---

    `reason` ++"string"++

    Explanation for failure if `isValid` is `false`.

### verifySignatures

Used to verify individual Guardian signatures against a VAA digest. *(Defined in [Messages.sol](https://github.com/wormhole-foundation/wormhole/blob/main/ethereum/contracts/Messages.sol){target=\_blank})*

```solidity
function verifySignatures(
    bytes32 hash,
    Structs.Signature[] memory signatures,
    GuardianSet memory guardianSet
) public view returns (bool)
```

??? interface "Parameters"

    `hash` ++"bytes32"++

    The message digest to verify.

    ---

    `signatures` ++"Structs.Signature[]"++

    An array of Guardian signatures.

    ---

    `guardianSet` ++"GuardianSet memory"++

    Guardian set to validate against.

??? interface "Returns"

    `isValid` ++"bool"++

    `true` if the required number of valid signatures is present.

### quorum

Returns the number of Guardian signatures required to reach quorum. *(Defined in [Governance.sol](https://github.com/wormhole-foundation/wormhole/blob/main/ethereum/contracts/Governance.sol){target=\_blank})*

```solidity
function quorum() public view returns (uint8)
```

??? interface "Returns"

    `quorum` ++"uint8"++

    Number of valid Guardian signatures required to reach consensus for VAA verification.

### chainId

Returns Wormhole chain ID used internally by the protocol. *(Defined in [Getters.sol](https://github.com/wormhole-foundation/wormhole/blob/main/ethereum/contracts/Getters.sol){target=\_blank})*

```solidity
function chainId() public view returns (uint16)
```

??? interface "Returns"

    `id` ++"uint16"++

    Wormhole-specific chain identifier. 

### evmChainId

Returns the EVM chain ID (i.e., value from `block.chainid`). *(Defined in [Getters.sol](https://github.com/wormhole-foundation/wormhole/blob/main/ethereum/contracts/Getters.sol){target=\_blank})*

```solidity
function evmChainId() public view returns (uint256)
```

??? interface "Returns"

    `id` ++"uint256"++

    Native EVM chain ID for the current network.

## Errors

### Invalid Fee

Reverts when the message fee (`msg.value`) sent is not equal to the required fee returned by `messageFee()`. *(Defined in [Implementation.sol](https://github.com/wormhole-foundation/wormhole/blob/main/ethereum/contracts/Implementation.sol){target=\_blank})*

### Unsupported

Reverts on any call to the fallback function. The contract does not support arbitrary calls. *(Defined in [Implementation.sol](https://github.com/wormhole-foundation/wormhole/blob/main/ethereum/contracts/Implementation.sol){target=\_blank})*

### The Wormhole Contract Does Not Accept Assets

Reverts when native tokens (ETH) are sent directly to the contract via the `receive()` function. *(Defined in [Implementation.sol](https://github.com/wormhole-foundation/wormhole/blob/main/ethereum/contracts/Implementation.sol){target=\_blank})*

### Already Initialized

Reverts when trying to call `initialize()` on an implementation that has already been initialized. *(Defined in [Implementation.sol](https://github.com/wormhole-foundation/wormhole/blob/main/ethereum/contracts/Implementation.sol){target=\_blank}, via `initializer` modifier)*

### Unknown Chain ID

Reverts inside the `initialize()` function if the chain ID stored by the contract does not match any known Wormhole chain. *(Defined in [Implementation.sol](https://github.com/wormhole-foundation/wormhole/blob/main/ethereum/contracts/Implementation.sol){target=\_blank})*

### Invalid Fork

Reverts when attempting to perform a governance action intended only for forked chains on a non-forked chain. *(Defined in [Governance.sol](https://github.com/wormhole-foundation/wormhole/blob/main/ethereum/contracts/Governance.sol){target=\_blank})*

### Invalid Module

Reverts if the VAA’s module field doesn’t match the expected "Core" module. *(Defined in [Governance.sol](https://github.com/wormhole-foundation/wormhole/blob/main/ethereum/contracts/Governance.sol){target=\_blank})*

### Invalid Chain

Reverts if the VAA’s target chain doesn’t match the chain on which this contract is deployed. *(Defined in [Governance.sol](https://github.com/wormhole-foundation/wormhole/blob/main/ethereum/contracts/Governance.sol){target=\_blank})*

### New Guardian Set is Empty

Reverts when trying to register a new Guardian set that has no keys. *(Defined in [Governance.sol](https://github.com/wormhole-foundation/wormhole/blob/main/ethereum/contracts/Governance.sol){target=\_blank})*

### Index Must Increase in Steps of 1

Reverts when the new Guardian set index is not exactly one greater than the current. *(Defined in [Governance.sol](https://github.com/wormhole-foundation/wormhole/blob/main/ethereum/contracts/Governance.sol){target=\_blank})*

### Not a Fork

Reverts when trying to recover chain ID on a non-forked chain. *(Defined in [Governance.sol](https://github.com/wormhole-foundation/wormhole/blob/main/ethereum/contracts/Governance.sol){target=\_blank})*

### Invalid EVM Chain

Reverts if the recovered chain ID doesn't match the current `block.chainid`. *(Defined in [Governance.sol](https://github.com/wormhole-foundation/wormhole/blob/main/ethereum/contracts/Governance.sol){target=\_blank})*

### Governance Action Already Consumed

Reverts when the same governance VAA is submitted more than once. *(Defined in [Governance.sol](https://github.com/wormhole-foundation/wormhole/blob/main/ethereum/contracts/Governance.sol){target=\_blank})*

### Wrong Governance Contract

Reverts when the governance VAA’s emitter address doesn't match the expected governance contract address. *(Defined in [Governance.sol](https://github.com/wormhole-foundation/wormhole/blob/main/ethereum/contracts/Governance.sol){target=\_blank})*

### Wrong Governance Chain

Reverts when the governance VAA’s emitter chain doesn't match the expected governance chain (Solana). *(Defined in [Governance.sol](https://github.com/wormhole-foundation/wormhole/blob/main/ethereum/contracts/Governance.sol){target=\_blank})*

### Not Signed by Current Guardian Set

Reverts if the Guardian set index in the VAA doesn’t match the current Guardian set. *(Defined in [Governance.sol](https://github.com/wormhole-foundation/wormhole/blob/main/ethereum/contracts/Governance.sol){target=\_blank})*


---

Page Title: Core Contract (Solana)

- Resolved Markdown: https://wormhole.com/docs/ai/pages/products-messaging-reference-core-contract-solana.md
- Canonical (HTML): https://wormhole.com/docs/products/messaging/reference/core-contract-solana/
- Summary: Reference for the Wormhole Core program on Solana. Covers architecture, PDA accounts, and instructions for posting, verifying, and processing VAAs.
- Word Count: 2162; Token Estimate: 4527

# Core Contract (Solana)

The [Wormhole Core Program on Solana](https://github.com/wormhole-foundation/wormhole/blob/main/solana/bridge/program/src/lib.rs){target=\_blank} is a native Solana program responsible for posting, verifying, and relaying Wormhole messages (VAAs). It implements core messaging functionality, Guardian set updates, and upgradeability.

## Structure Overview

The Wormhole Core program on Solana is implemented using modular Rust files. Logic is separated across instruction dispatch, account definitions, core types, and signature verification.

```text
lib.rs
├── instructions.rs
├── accounts.rs
├── api.rs
│   ├── post_message
│   ├── verify_signatures
│   ├── post_vaa
│   ├── upgrade_contract
│   └── upgrade_guardian_set
├── types.rs
└── vaa.rs
```

**Key Components:**

 - **lib.rs**: Program entry point and instruction dispatcher. Registers all handlers and exposes the on-chain processor.
 - **instructions.rs**: Defines the `WormholeInstruction` enum and maps it to individual instruction handlers.
 - **accounts.rs**: Specifies the account constraints and validation logic for each instruction.
 - **api.rs**: Contains the main logic for processing instructions such as message posting, VAA verification, upgrades, and governance actions.
 - **types.rs**: Defines shared structs and enums used throughout the program, including configuration and `GuardianSet` formats.
 - **vaa.rs**: Implements VAA parsing, hashing, and signature-related logic used to verify Wormhole messages.
 - **error.rs** (not listed above): Defines custom error types used across the program for precise failure handling.
 - **wasm.rs** (not listed above): Provides WebAssembly bindings for testing and external tooling; not used on-chain.

## State Accounts

Below are on-chain PDAs used to store persistent state for the core contract. All are derived using deterministic seeds with the program ID.

 - **`bridge` ++"BridgeData"++**: Stores global config like the active Guardian set index, message fee, and Guardian set expiration time. (Derived at PDA seed `["Bridge"]`)
 - **`guardianSets` ++"GuardianSetData"++**: Mapping of Guardian sets by index. Each Guardian set includes public key hashes and creation/expiration times. (Derived at PDA seed `["GuardianSet", index]`)
 - **`sequences` ++"SequenceTracker"++**: Tracks the last sequence number used by each emitter, enforcing strict message ordering. (Derived at PDA seed `["Sequence", emitter]`)
 - **`postedVAAs` ++"PostedVAAData"++**: Stores verified and finalized VAAs, preventing replay. (Derived at PDA seed `["PostedVAA", hash]`)
 - **`claims` ++"ClaimData"++**: Tracks consumed governance VAAs to ensure replay protection. (Derived at PDA seed `["Claim", emitter, sequence]`)
 - **`feeCollector` ++"FeeCollector"++**: Holds lamports collected via message fees, and can be drained via governance. (Derived at PDA seed `["fee_collector"]`)

## Instructions

### initialize

Initializes the Wormhole Core contract on Solana with a Guardian set and fee configuration. This should be called only once at deployment time. *(Defined in [api/initialize.rs](https://github.com/wormhole-foundation/wormhole/blob/main/solana/bridge/program/src/api/initialize.rs){target=\_blank})*

```rust
initialize(
    payer: Pubkey,
    fee: u64,
    guardian_set_expiration_time: u32,
    initial_guardians: &[[u8; 20]]
)
```

??? interface "Accounts"

    - **`Bridge`**: PDA to store global configuration.
    - **`GuardianSet`**: PDA for Guardian set at index 0.
    - **`FeeCollector`**: PDA to collect message posting fees.
    - **`Payer`**: Funds account creation.
    - **`Clock`, `Rent`, `SystemProgram`**: Solana system accounts.

??? interface "Parameters"

    `fee` ++"u64"++

    Fee in lamports required to post messages.

    ---

    `guardian_set_expiration_time` ++"u32"++

    Time in seconds after which the Guardian set expires.

    ---

    `initial_guardians` ++"[[u8; 20]]"++

    List of Guardian public key hashes (Ethereum-style addresses).

### post_message

Posts a Wormhole message to the Solana Core contract. *(Defined in [api/post_message.rs](https://github.com/wormhole-foundation/wormhole/blob/main/solana/bridge/program/src/api/post_message.rs){target=\_blank})*

```rust
PostMessage {
    nonce: u32,
    payload: Vec<u8>,
    consistency_level: u8
}
```

??? interface "Accounts"

    - **`Bridge`**: PDA for global config.
    - **`Message`**: PDA where the posted message will be stored.
    - **`Emitter`**: The emitting account (must sign).
    - **`Sequence`**: PDA tracking the emitter’s message sequence.
    - **`Payer`**: Pays for account creation and fees.
    - **`FeeCollector`**: PDA that collects message fees.
    - **`Clock`, `Rent`, `SystemProgram`**: Solana system accounts.

??? interface "Parameters"

    `nonce` ++"u32"++

    Unique nonce to disambiguate messages with the same payload.

    ---

    `payload` ++"Vec<u8>"++

    The arbitrary message payload to be posted.

    ---

    `consistency_level` ++"u8"++

    Level of finality required before the message is processed.

    `1` = Confirmed, `32` = Finalized.

### post_message_unreliable

Posts a Wormhole message without requiring reliable delivery. Used for lightweight publishing when finality isn't critical. *(Defined in [api/post_message.rs](https://github.com/wormhole-foundation/wormhole/blob/main/solana/bridge/program/src/api/post_message.rs){target=\_blank})*

```rust
PostMessageUnreliable {
    nonce: u32,
    payload: Vec<u8>,
    consistency_level: u8
}
```

??? interface "Accounts"

    - **`Bridge`**: PDA for global config.
    - **`Message`**: PDA where the posted message will be stored.
    - **`Emitter`**: The emitting account (must sign).
    - **`Sequence`**: PDA tracking the emitter’s message sequence.
    - **`Payer`**: Pays for account creation and fees.
    - **`FeeCollector`**: PDA that collects message fees.
    - **`Clock`, `Rent`, `SystemProgram`**: Solana system accounts.

??? interface "Parameters"

    `nonce` ++"u32"++

    Unique nonce to disambiguate messages with the same payload.

    ---

    `payload` ++"Vec<u8>"++

    The arbitrary message payload to be posted.

    ---

    `consistency_level` ++"u8"++

    Level of finality required before the message is processed. `1` = Confirmed, `32` = Finalized.

### verify_signatures

Verifies Guardian signatures over a VAA body hash. This is the first step in VAA processing and is required before posting the VAA. *(Defined in [api/verify_signature.rs](https://github.com/wormhole-foundation/wormhole/blob/main/solana/bridge/program/src/api/verify_signature.rs){target=\_blank})*

```rust
VerifySignatures {
    signers: [i8; 19]
}
```

??? interface "Accounts"

    - **`Payer`**: Pays for account creation and fees.
    - **`GuardianSet`**: PDA holding the current Guardian set.
    - **`SignatureSet`**: PDA that will store the verified signature data.
    - **`InstructionsSysvar`**: Required to access prior instructions (e.g., secp256k1 sigverify).
    - **`Rent`, `SystemProgram`**: Solana system accounts.

??? interface "Parameters"

    `signers` ++"[i8; 19]"++

    A mapping from Guardian index to its position in the instruction payload (or -1 if not present).

    Used to correlate secp256k1 verify instructions with Guardian set entries.

### post_vaa

Finalizes a VAA after signature verification. This stores the message on-chain and marks it as consumed. *(Defined in [api/post_vaa.rs](https://github.com/wormhole-foundation/wormhole/blob/main/solana/bridge/program/src/api/post_vaa.rs){target=\_blank})*

```rust
PostVAA {
    version: u8,
    guardian_set_index: u32,
    timestamp: u32,
    nonce: u32,
    emitter_chain: u16,
    emitter_address: [u8; 32],
    sequence: u64,
    consistency_level: u8,
    payload: Vec<u8>
}
```

??? interface "Accounts"

    - **`GuardianSet`**: PDA of the Guardian set used to verify the VAA.
    - **`Bridge`**: Global Wormhole state.
    - **`SignatureSet`**: Verified signature PDA (from verify_signatures).
    - **`PostedVAA`**: PDA where the VAA will be stored.
    - **`Payer`**: Funds the account creation.
    - **`Clock`, `Rent`, `SystemProgram`**: Solana system accounts.

??? interface "Parameters"

    `version` ++"u8"++

    VAA protocol version.

    ---

    `guardian_set_index` ++"u32"++

    Index of the Guardian Set that signed this VAA.

    ---

    `timestamp` ++"u32"++

    The time the emitter submitted the message.

    ---

    `nonce` ++"u32"++

    Unique identifier for the message.

    ---

    `emitter_chain` ++"u16"++

    ID of the chain where the message originated.

    ---

    `emitter_address` ++"[u8; 32]"++

    Address of the contract or account that emitted the message.

    ---

    `sequence` ++"u64"++

    Monotonically increasing sequence number for the emitter.

    ---

    `consistency_level` ++"u8"++

    Required confirmation level before the message is accepted.
    
    `1` = Confirmed, `32` = Finalized.

    ---

    `payload` ++"Vec<u8>"++

    Arbitrary data being transferred in the message.

### set_fees

Updates the message posting fee for the core bridge contract. *(Defined in [api/governance.rs](https://github.com/wormhole-foundation/wormhole/blob/main/solana/bridge/program/src/api/governance.rs){target=\_blank})*

```rust
SetFees {}
```

This function is called via governance and requires a valid governance VAA. The VAA payload must contain the new fee value.

??? interface "Accounts"

    - **`Payer`**: Funds transaction execution.
    - **`Bridge`**: PDA storing global Wormhole state.
    - **`Message`**: The PostedVAA account containing the governance message.
    - **`Claim`**: PDA that ensures this governance message hasn't been processed already.
    - **`SystemProgram`**: Required by Solana for creating/initializing accounts.

### transfer_fees

Transfers the accumulated message posting fees from the contract to a specified recipient. *(Defined in [api/governance.rs](https://github.com/wormhole-foundation/wormhole/blob/main/solana/bridge/program/src/api/governance.rs){target=\_blank})*

```rust
TransferFees {}
```

This function is triggered via a governance VAA and transfers the fee balance from the `FeeCollector` to the recipient address specified in the VAA payload.

??? interface "Accounts"

    - **`Payer`**: Funds transaction execution.
    - **`Bridge`**: PDA storing global Wormhole state.
    - **`Message`**: PostedVAA account containing the governance message.
    - **`FeeCollector`**: PDA holding the accumulated fees.
    - **`Recipient`**: The account that will receive the fees.
    - **`Claim`**: PDA that ensures this governance message hasn't been processed already.
    - **`Rent`, `SystemProgram`**: Standard Solana system accounts.

### upgrade_contract

Upgrades the deployed Wormhole program using a governance VAA. *(Defined in [api/governance.rs](https://github.com/wormhole-foundation/wormhole/blob/main/solana/bridge/program/src/api/governance.rs){target=\_blank})*

```rust
UpgradeContract {}
```

This instruction allows authorized governance messages to trigger an upgrade of the on-chain Wormhole program logic to a new address.

??? interface "Accounts"

    - **`Payer`**: Funds transaction execution.
    - **`Bridge`**: PDA storing global Wormhole state.
    - **`Message`**: PostedVAA account containing the governance message.
    - **`Claim`**: PDA that ensures this governance message hasn't been processed already.
    - **`UpgradeAuthority`**: PDA with authority to perform the upgrade (seeded with "upgrade").
    - **`Spill`**: Account that receives remaining funds from the upgrade buffer.
    - **`NewContract`**: Account holding the new program data.
    - **`ProgramData`**: Metadata account for the upgradable program.
    - **`Program`**: Current program to be upgraded.
    - **`Rent`, `Clock`**: System accounts used during the upgrade process.
    - **`BPFLoaderUpgradeable`**: Solana system program for upgrades.
    - **`SystemProgram`**: Required by Solana for creating/initializing accounts.

### upgrade_guardian_set

Upgrades the current Guardian set using a governance VAA. *(Defined in [api/governance.rs](https://github.com/wormhole-foundation/wormhole/blob/main/solana/bridge/program/src/api/governance.rs){target=\_blank})*

```rust
UpgradeGuardianSet {}
```

This instruction replaces the active Guardian set with a new one, allowing the Wormhole network to rotate its validator keys securely through governance.

??? interface "Accounts"

    - **`Payer`**: Funds transaction execution.
    - **`Bridge`**: PDA storing global Wormhole state.
    - **`Message`**: PostedVAA account containing the governance message.
    - **`Claim`**: PDA that ensures this governance message hasn't been processed already.
    - **`GuardianSetOld`**: Current (active) Guardian set PDA.
    - **`GuardianSetNew`**: PDA for the newly proposed Guardian set.
    - **`SystemProgram`**: Standard Solana system accounts.

## Errors

### GuardianSetMismatch

The Guardian set index does not match the expected value. *(Defined in [error.rs](https://github.com/wormhole-foundation/wormhole/blob/main/solana/bridge/program/src/error.rs){target=\_blank})*

### InstructionAtWrongIndex

The instruction was found at the wrong index. *(Defined in [error.rs](https://github.com/wormhole-foundation/wormhole/blob/main/solana/bridge/program/src/error.rs){target=\_blank})*

### InsufficientFees

Insufficient fees were provided to post the message. *(Defined in [error.rs](https://github.com/wormhole-foundation/wormhole/blob/main/solana/bridge/program/src/error.rs){target=\_blank})*

### InvalidFeeRecipient

The recipient address does not match the one specified in the governance VAA. *(Defined in [error.rs](https://github.com/wormhole-foundation/wormhole/blob/main/solana/bridge/program/src/error.rs){target=\_blank})*

### InvalidGovernanceAction

The action specified in the governance payload is invalid. *(Defined in [error.rs](https://github.com/wormhole-foundation/wormhole/blob/main/solana/bridge/program/src/error.rs){target=\_blank})*

### InvalidGovernanceChain

The governance VAA was not emitted by a valid governance chain. *(Defined in [error.rs](https://github.com/wormhole-foundation/wormhole/blob/main/solana/bridge/program/src/error.rs){target=\_blank})*

### InvalidGovernanceKey

The emitter address in the governance VAA is not the expected governance key. *(Defined in [error.rs](https://github.com/wormhole-foundation/wormhole/blob/main/solana/bridge/program/src/error.rs){target=\_blank})*

### InvalidGovernanceModule

The module string in the governance VAA header is invalid. *(Defined in [error.rs](https://github.com/wormhole-foundation/wormhole/blob/main/solana/bridge/program/src/error.rs){target=\_blank})*

### InvalidGovernanceWithdrawal

Fee withdrawal would cause the fee collector account to drop below rent-exempt balance. *(Defined in [error.rs](https://github.com/wormhole-foundation/wormhole/blob/main/solana/bridge/program/src/error.rs){target=\_blank})*

### InvalidGuardianSetUpgrade

The Guardian set upgrade VAA is invalid (e.g., skipped index or mismatched current index). *(Defined in [error.rs](https://github.com/wormhole-foundation/wormhole/blob/main/solana/bridge/program/src/error.rs){target=\_blank})*

### InvalidHash

The hash computed from the VAA does not match the expected result. *(Defined in [error.rs](https://github.com/wormhole-foundation/wormhole/blob/main/solana/bridge/program/src/error.rs){target=\_blank})*

### InvalidSecpInstruction

The SECP256k1 instruction used for signature verification is malformed. *(Defined in [error.rs](https://github.com/wormhole-foundation/wormhole/blob/main/solana/bridge/program/src/error.rs){target=\_blank})*

### MathOverflow

An arithmetic overflow occurred during computation. *(Defined in [error.rs](https://github.com/wormhole-foundation/wormhole/blob/main/solana/bridge/program/src/error.rs){target=\_blank})*

### PostVAAConsensusFailed

Not enough valid signatures were collected to achieve quorum. *(Defined in [error.rs](https://github.com/wormhole-foundation/wormhole/blob/main/solana/bridge/program/src/error.rs){target=\_blank})*

### PostVAAGuardianSetExpired

The Guardian set used to verify the VAA has already expired. *(Defined in [error.rs](https://github.com/wormhole-foundation/wormhole/blob/main/solana/bridge/program/src/error.rs){target=\_blank})*

### TooManyGuardians

The Guardian set exceeds the maximum allowed number of guardians. *(Defined in [error.rs](https://github.com/wormhole-foundation/wormhole/blob/main/solana/bridge/program/src/error.rs){target=\_blank})*

### VAAAlreadyExecuted

The VAA has already been executed and cannot be processed again. *(Defined in [error.rs](https://github.com/wormhole-foundation/wormhole/blob/main/solana/bridge/program/src/error.rs){target=\_blank})*

### VAAInvalid

The VAA is structurally invalid or fails to decode. *(Defined in [error.rs](https://github.com/wormhole-foundation/wormhole/blob/main/solana/bridge/program/src/error.rs){target=\_blank})*

### InvalidPayloadLength

The payload length is incorrect or malformed. *(Defined in [error.rs](https://github.com/wormhole-foundation/wormhole/blob/main/solana/bridge/program/src/error.rs){target=\_blank})*

### EmitterChanged

The emitter address changed unexpectedly. *(Defined in [error.rs](https://github.com/wormhole-foundation/wormhole/blob/main/solana/bridge/program/src/error.rs){target=\_blank})*


---

Page Title: Core Contracts

- Resolved Markdown: https://wormhole.com/docs/ai/pages/protocol-infrastructure-core-contracts.md
- Canonical (HTML): https://wormhole.com/docs/protocol/infrastructure/core-contracts/
- Summary: Discover Wormhole's Core Contracts, which enable multichain communication with message sending, receiving, and multicast features for efficient synchronization.
- Word Count: 1040; Token Estimate: 1399

# Core Contracts

The Wormhole Core Contract is deployed across each supported blockchain network. This contract is a fundamental component of the Wormhole interoperability protocol and acts as the foundational layer enabling secure and efficient multichain messaging. All multichain applications either interact directly with the Core Contract or with another contract that does.

This page summarizes the key functions of the Core Contract and outlines how the Core Contract works.

## Key Functions 

Key functions of the Wormhole Core Contract include the following:

- **Multichain messaging**: Standardizes and secures the format of messages to facilitate consistent communication for message transfer between Wormhole-connected blockchain networks, allowing developers to leverage the unique features of each network.
- **Verification and validation**: Verifies and validates all VAAs received on the target chain by confirming the Guardian signature to ensure the message is legitimate and has not been manipulated or altered.
- **Guardian Network coordination**: Coordinates with Wormhole's Guardian Network to facilitate secure, trustless communication across chains and ensure that only validated interactions are processed to enhance the protocol's overall security and reliability.
- **Event emission for monitoring**: Emits events for every multichain message processed, allowing for network activity monitoring like tracking message statuses, debugging, and applications that can react to multichain events in real time.

## How the Core Contract Works

The Wormhole Core Contract is central in facilitating secure and efficient multichain transactions. It enables communication between different blockchain networks by packaging transaction data into standardized messages, verifying their authenticity, and ensuring they are executed correctly on the destination chain.

The following describes the role of the Wormhole Core Contract in message transfers:

1. **Message submission**: When a user initiates a multichain transaction, the Wormhole Core Contract on the source chain packages the transaction data into a standardized message payload and submits it to the Guardian Network for verification.
2. **Guardian verification**: Guardians independently observe and sign the message. On chains where all Guardians perform direct on-chain observation, each Guardian signs based on its own verification of the event. On delegated chains, a delegated subset signs and broadcasts signed delegate observations to the rest of the network. Canonical Guardians wait for delegate quorum before contributing their signatures. Once a supermajority of 13 out of 19 Guardians have signed, the signatures are combined with the message and metadata to produce a VAA.
3. **Message reception and execution**: On the target chain, the Wormhole Core Contract receives the verified message, checks the Guardians' signatures, and executes the corresponding actions like minting tokens, updating states, or calling specific smart contract functions.

For a closer look at how messages flow between chains and all of the components involved, you can refer to the [Architecture Overview](/docs/protocol/architecture/) page.

### Message Submission

You can send multichain messages by calling a function against the source chain Core Contract, which then publishes the message. Message publishing strategies can differ by chain; however, generally, the Core Contract posts the following items to the blockchain logs:

- **`emitterAddress`**: The contract which made the call to publish the message.
- **`sequenceNumber`**: A unique number that increments for every message for a given emitter (and implicitly chain).
- **`consistencyLevel`**: The level of finality to reach before the Guardians will observe and attest the emitted event. This is a defense against reorgs and rollbacks since a transaction, once considered "final,"  is guaranteed not to have the state changes it caused rolled back. Since different chains use different consensus mechanisms, each one has different finality assumptions, so this value is treated differently on a chain-by-chain basis. See the options for finality for each chain in the [Wormhole Finality](/docs/products/reference/consistency-levels/){target=\_blank} reference page.

There are no fees to publish a message except when publishing on Solana, but this is subject to change in the future.

### Message Reception

When you receive a multichain message on the target chain Core Contract, you generally must parse and verify the [components of a VAA](/docs/protocol/infrastructure/vaas#vaa-format){target=\_blank}. Receiving and verifying a VAA ensures that the Guardian Network properly attests to the message and maintains the integrity and authenticity of the data transmitted between chains. The Core Contract does not distinguish between chains with direct observation and delegated chains; it verifies only that a valid 13-of-19 VAA has been produced.

## Multicast

Multicast refers to simultaneously broadcasting a single message or transaction across different blockchains with no destination address or chain for the sending and receiving functions. VAAs 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 where they are used.

This multicast-by-default model makes it easy to synchronize state across the entire ecosystem. A blockchain can make its data available to every chain in a single action with low latency, which reduces the complexity of the n^2 problems encountered by routing data to many blockchains.

This doesn't mean an application _cannot_ specify a destination address or chain. For example, the [Wrapped Token Transfers (WTT)](/docs/products/token-transfers/wrapped-token-transfers/overview/){target=\_blank} and [Executor](/docs/protocol/infrastructure/relayers/executor-framework/){target=\_blank} contracts require that some destination details be passed and verified on the destination chain.

Because the VAA creation is separate from relaying, the multicast model does not incur an additional cost when a single chain is targeted. If the data isn't needed on a certain blockchain, don't relay it there, and it won't cost anything.

## Next Steps

<div class="grid cards" markdown>

-   :octicons-book-16:{ .lg .middle } **Verified Action Approvals (VAA)**

    ---

    Learn about Verified Action Approvals (VAAs) in Wormhole, their structure, validation, and their role in multichain communication.

    [:custom-arrow: Learn About VAAs](/docs/protocol/infrastructure/vaas/)

- :octicons-tools-16:{ .lg .middle } **Get Started with Core Contracts**

    ---

    This guide walks through the key methods of the Core Contracts, providing you with the knowledge needed to integrate them into your multichain contracts.

    [:custom-arrow: Build with Core Contracts](/docs/products/messaging/guides/core-contracts/)

-   :octicons-tools-16:{ .lg .middle } **Wormhole Dev Arena**

    ---

    A structured learning hub with hands-on tutorials across the Wormhole ecosystem.

    [:custom-arrow: Explore the Dev Arena](https://arena.wormhole.com/ecosystem){target=\_blank}

</div>


---

Page Title: Create Cross-Chain Contracts

- Resolved Markdown: https://wormhole.com/docs/ai/pages/products-messaging-tutorials-cross-chain-contracts.md
- Canonical (HTML): https://wormhole.com/docs/products/messaging/tutorials/cross-chain-contracts/
- Summary: Learn how to create cross-chain contracts using Wormhole's Solidity SDK. Deploy contracts on Avalanche Fuji and Base Sepolia and send messages across chains.
- Word Count: 4045; Token Estimate: 7197

# Create Cross-Chain Messaging Contracts

:simple-github: [Source code on GitHub](https://github.com/wormhole-foundation/demo-wormhole-messaging){target=\_blank}

Wormhole's cross-chain messaging allows smart contracts to interact seamlessly across multiple blockchains. This enables developers to build decentralized applications that leverage the strengths of different networks, whether it's Avalanche, Celo, Ethereum, or beyond. In this tutorial, we'll explore using [Wormhole's Solidity SDK](https://github.com/wormhole-foundation/wormhole-solidity-sdk){target=\_blank} to create cross-chain contracts to send and receive messages across chains.

Wormhole's messaging infrastructure simplifies data transmission, event triggering, and transaction initiation across blockchains. In this tutorial, we'll guide you through a simple yet powerful hands-on demonstration that showcases this practical capability. We'll deploy contracts on two testnets, Avalanche Fuji and Base Sepolia, and send messages from one chain to another. This tutorial is perfect for those new to cross-chain development and seeking hands-on experience with Wormhole's powerful toolkit.

By the end of this tutorial, you will have not only built a fully functioning cross-chain message sender and receiver using Solidity but also developed a comprehensive understanding of how to interact with the relayer, manage cross-chain costs, and ensure your smart contracts are configured correctly on both source and target chains.

This tutorial assumes a basic understanding of Solidity and smart contract development. Before diving in, it may be helpful to review [the basics of Wormhole](/docs/protocol/introduction/){target=\_blank} to familiarize yourself with the protocol.

## Wormhole Overview

We'll interact with two key Wormhole components: the [relayer](/docs/protocol/infrastructure/relayer/){target=\_blank} and the [Wormhole Core Contracts](/docs/protocol/infrastructure/core-contracts/){target=\_blank}. The relayer handles cross-chain message delivery and ensures the message is accurately received on the target chain. This allows smart contracts to communicate across blockchains without developers worrying about the underlying complexity.

Additionally, we'll rely on the relayer to automatically determine cross-chain transaction costs and facilitate payments. This feature simplifies cross-chain development by allowing you to specify only the target chain and the message. The relayer handles the rest, ensuring that the message is transmitted with the appropriate fee.

![Wormhole architecture detailed diagram: source to target chain communication.](/docs/images/protocol/architecture/architecture-1.webp)

## Prerequisites

Before starting this tutorial, ensure you have the following:

- [Node.js and npm](https://docs.npmjs.com/downloading-and-installing-node-js-and-npm){target=\_blank} installed on your machine.
- [Foundry](https://getfoundry.sh/introduction/installation/){target=\_blank} for deploying contracts.
- Testnet tokens for [Avalanche-Fuji](https://core.app/tools/testnet-faucet/?token=C){target=\_blank} and [Base-Sepolia](https://docs.base.org/docs/tools/network-faucets/){target=\_blank} to cover gas fees.
- Wallet private key.

## Build Cross-Chain Messaging Contracts

In this section, we'll deploy two smart contracts: one to send a message from Avalanche Fuji and another to receive it on Base Sepolia. The contracts interact with the relayer to transmit messages across chains.

At a high level, our contracts will:

1. Send a message from Avalanche to Base Sepolia using the relayer.
2. Receive and process the message on Base Sepolia, logging the content of the message.

Before diving into the deployment steps, let's first break down key parts of the contracts.

### Sender Contract: MessageSender

The `MessageSender` contract is responsible for quoting the cost of sending a message cross-chain and then sending that message. 

Key functions include:

 - **`quoteCrossChainCost`**: Calculates the cost of delivering a message to the target chain using the relayer.
 - **`sendMessage`**: Encodes the message and sends it to the target chain and contract address using the relayer.

Here's the core of the contract:

```solidity
    function sendMessage(
        uint16 targetChain,
        address targetAddress,
        string memory message
    ) external payable {
        uint256 cost = quoteCrossChainCost(targetChain);

        require(
            msg.value >= cost,
            "Insufficient funds for cross-chain delivery"
        );

        wormholeRelayer.sendPayloadToEvm{value: cost}(
            targetChain,
            targetAddress,
            abi.encode(message, msg.sender),
            0,
            GAS_LIMIT
        );
    }
```

You can find the full code for the `MessageSender.sol` below.

??? code "MessageSender.sol"

    ```solidity
    // SPDX-License-Identifier: MIT
    pragma solidity ^0.8.18;

    import "lib/wormhole-solidity-sdk/src/interfaces/IWormholeRelayer.sol";

    contract MessageSender {
        IWormholeRelayer public wormholeRelayer;
        uint256 constant GAS_LIMIT = 50000;

        constructor(address _wormholeRelayer) {
            wormholeRelayer = IWormholeRelayer(_wormholeRelayer);
        }

        function quoteCrossChainCost(
            uint16 targetChain
        ) public view returns (uint256 cost) {
            (cost, ) = wormholeRelayer.quoteEVMDeliveryPrice(
                targetChain,
                0,
                GAS_LIMIT
            );
        }

        function sendMessage(
            uint16 targetChain,
            address targetAddress,
            string memory message
        ) external payable {
            uint256 cost = quoteCrossChainCost(targetChain);

            require(
                msg.value >= cost,
                "Insufficient funds for cross-chain delivery"
            );

            wormholeRelayer.sendPayloadToEvm{value: cost}(
                targetChain,
                targetAddress,
                abi.encode(message, msg.sender),
                0,
                GAS_LIMIT
            );
        }
    }
    ```

### Receiver Contract: MessageReceiver

The `MessageReceiver` contract handles incoming cross-chain messages. When a message arrives, it decodes the payload and logs the message content. It ensures that only authorized contracts can send and process messages, adding an extra layer of security in cross-chain communication.

#### Emitter Validation and Registration

In cross-chain messaging, validating the sender is essential to prevent unauthorized contracts from sending messages. The `isRegisteredSender` modifier ensures that messages can only be processed if they come from the registered contract on the source chain. This guards against malicious messages and enhances security.

Key implementation details include:

 - **`registeredSender`**: Stores the address of the registered sender contract.
 - **`setRegisteredSender`**: Registers the sender's contract address on the source chain. It ensures that only registered contracts can send messages, preventing unauthorized senders.
 - **`isRegisteredSender`**: Restricts the processing of messages to only those from registered senders, preventing unauthorized cross-chain communication.

```solidity
    mapping(uint16 => bytes32) public registeredSenders;
    modifier isRegisteredSender(uint16 sourceChain, bytes32 sourceAddress) {
        require(
            registeredSenders[sourceChain] == sourceAddress,
            "Not registered sender"
        );
        _;
    }

    function setRegisteredSender(
        uint16 sourceChain,
        bytes32 sourceAddress
    ) public {
        require(
            msg.sender == registrationOwner,
            "Not allowed to set registered sender"
        );
        registeredSenders[sourceChain] = sourceAddress;
    }
```

#### Message Processing

The `receiveWormholeMessages` is the core function that processes the received message. It checks that the relayer sent the message, decodes the payload, and emits an event with the message content. It is essential to verify the message sender to prevent unauthorized messages.

```solidity
    function receiveWormholeMessages(
        bytes memory payload,
        bytes[] memory,
        bytes32 sourceAddress,
        uint16 sourceChain,
        bytes32
    ) public payable override isRegisteredSender(sourceChain, sourceAddress) {
        require(
            msg.sender == address(wormholeRelayer),
            "Only the Wormhole relayer can call this function"
        );

        // Decode the payload to extract the message
        string memory message = abi.decode(payload, (string));

        // Example use of sourceChain for logging
        if (sourceChain != 0) {
            emit SourceChainLogged(sourceChain);
        }

        // Emit an event with the received message
        emit MessageReceived(message);
    }
```

You can find the full code for the `MessageReceiver.sol` below.

??? code "MessageReceiver.sol"

    ```solidity
    // SPDX-License-Identifier: MIT
    pragma solidity ^0.8.18;

    import "lib/wormhole-solidity-sdk/src/interfaces/IWormholeRelayer.sol";
    import "lib/wormhole-solidity-sdk/src/interfaces/IWormholeReceiver.sol";

    contract MessageReceiver is IWormholeReceiver {
        IWormholeRelayer public wormholeRelayer;
        address public registrationOwner;

        // Mapping to store registered senders for each chain
        mapping(uint16 => bytes32) public registeredSenders;

        event MessageReceived(string message);
        event SourceChainLogged(uint16 sourceChain);

        constructor(address _wormholeRelayer) {
            wormholeRelayer = IWormholeRelayer(_wormholeRelayer);
            registrationOwner = msg.sender; // Set contract deployer as the owner
        }

        modifier isRegisteredSender(uint16 sourceChain, bytes32 sourceAddress) {
            require(
                registeredSenders[sourceChain] == sourceAddress,
                "Not registered sender"
            );
            _;
        }

        function setRegisteredSender(
            uint16 sourceChain,
            bytes32 sourceAddress
        ) public {
            require(
                msg.sender == registrationOwner,
                "Not allowed to set registered sender"
            );
            registeredSenders[sourceChain] = sourceAddress;
        }

        // Update receiveWormholeMessages to include the source address check
        function receiveWormholeMessages(
            bytes memory payload,
            bytes[] memory,
            bytes32 sourceAddress,
            uint16 sourceChain,
            bytes32
        ) public payable override isRegisteredSender(sourceChain, sourceAddress) {
            require(
                msg.sender == address(wormholeRelayer),
                "Only the Wormhole relayer can call this function"
            );

            // Decode the payload to extract the message
            string memory message = abi.decode(payload, (string));

            // Example use of sourceChain for logging
            if (sourceChain != 0) {
                emit SourceChainLogged(sourceChain);
            }

            // Emit an event with the received message
            emit MessageReceived(message);
        }
    }
    ```

## Deploy Contracts

This section will guide you through deploying the cross-chain messaging contracts on the Avalanche Fuji and Base Sepolia Testnets. Follow these steps to get your contracts up and running.

### Deployment Tools
We use _Foundry_ to deploy our smart contracts. However, you can use any tool you're comfortable with, such as:

 - [Remix](https://remix.ethereum.org/){target=\_blank} for a browser-based IDE.
 - [Hardhat](https://hardhat.org/hardhat-runner/docs/getting-started#installation){target=\_blank} for a more extensive JavaScript/TypeScript workflow.
 - [Foundry](https://getfoundry.sh/introduction/installation/){target=\_blank} for a CLI-focused experience with built-in scripting and testing features.

The contracts and deployment steps remain the same regardless of your preferred tool. The key is to ensure you have the necessary Testnet funds and are deploying to the right networks.

### Repository Setup

To get started with cross-chain messaging using Wormhole, first clone the [GitHub repository](https://github.com/wormhole-foundation/demo-wormhole-messaging){target=\_blank}. This repository includes everything you need to deploy, interact, and test the message flow between chains.

This demo focuses on using the scripts, so it's best to take a look at them, starting with `deploySender.ts`, `deployReceiver.ts`, and `sendMessage.ts`.

To configure the dependencies properly, run the following command:

```bash
npm install
```

The repository includes:

- Two Solidity contracts:

    - **`MessageSender.sol`**: Contract that sends the cross-chain message from Avalanche.
    - **`MessageReceiver.sol`**: Contract that receives the cross-chain message on Base Sepolia.

- Deployment scripts located in the `script` directory:

    - **`deploySender.ts`**: Deploys the `MessageSender` contract to Avalanche.
    - **`deployReceiver.ts`**: Deploys the `MessageReceiver` contract to Base Sepolia.
    - **`sendMessage.ts`**: Sends a message from Avalanche to Base Sepolia.

- Configuration files and ABI JSON files for easy deployment and interaction:

    - **`chains.json`**: Configuration file that stores key information for the supported Testnets, including the relayer addresses, RPC URLs, and chain IDs. You likely won't need to modify this file unless you're working with different networks.

 - A dedicated `interfaces` directory inside the `src` folder for TypeScript type definitions:

    - **`ChainsConfig.ts`**: Defines the types for the `chains.json` configuration file.
    - **`DeployedContracts.ts`**: Contains types for deployed contract addresses and related information.
    - **`MessageJsons.ts`**: Includes types for ABI and bytecode JSONs used by the deployment scripts.
    - **`index.ts`**: Serves as an export aggregator for the interfaces, simplifying imports in other files.

### Important Setup Steps

1. **Add your private key**: Create a `.env` file in the root of the project and add your private key.
    
    ```env
    touch .env
    ```

    Inside `.env`, add your private key in the following format:

    ```env
    PRIVATE_KEY=INSERT_PRIVATE_KEY
    ```

2. **Compile the contracts**: Ensure everything is set up correctly by compiling the contracts.

    ```bash
    forge build
    ```

The expected output should be similar to this:

<div id="termynal" data-termynal>
	<span data-ty="input"><span class="file-path"></span>forge build</span>
	<span data-ty> > [⠒] Compiling...</span>
	<span data-ty> > [⠰] Compiling 30 files with 0.8.23</span>
	<span data-ty> [⠔] Solc 0.8.23 finished in 2.29s</span>
	<span data-ty>Compiler run successful!</span>
	<span data-ty="input"><span class="file-path"></span></span>
</div>
### Deployment Process

Both deployment scripts, `deploySender.ts` and `deployReceiver.ts`, perform the following key tasks:

1. **Load configuration and contract details**: Each script begins by loading the necessary configuration details, such as the network's RPC URL and the contract's ABI and bytecode. This information is essential for deploying the contract to the correct blockchain network.

    === "`chains.json`"

        ```json
        {
            "chains": [
                {
                    "description": "Avalanche testnet fuji",
                    "chainId": 6,
                    "rpc": "https://api.avax-test.network/ext/bc/C/rpc",
                    "tokenBridge": "0x61E44E506Ca5659E6c0bba9b678586fA2d729756",
                    "wormholeRelayer": "0xA3cF45939bD6260bcFe3D66bc73d60f19e49a8BB",
                    "wormhole": "0x7bbcE28e64B3F8b84d876Ab298393c38ad7aac4C"
                },
                {
                    "description": "Base Sepolia testnet",
                    "chainId": 10004,
                    "rpc": "https://sepolia.base.org",
                    "tokenBridge": "0x86F55A04690fd7815A3D802bD587e83eA888B239",
                    "wormholeRelayer": "0x93BAD53DDfB6132b0aC8E37f6029163E63372cEE",
                    "wormhole": "0x79A1027a6A159502049F10906D333EC57E95F083"
                }
            ]
        }
        ```

    === "`deploySender.ts`"

        ```typescript
          // Load the chain configuration from JSON
          const chains: ChainsConfig = JSON.parse(
            fs.readFileSync(
              path.resolve(__dirname, '../deploy-config/chains.json'),
              'utf8'
            )
          );

          // Get the Avalanche Fuji configuration
          const avalancheChain = chains.chains.find((chain) =>
            chain.description.includes('Avalanche testnet')
          );
        ```

    === "`deployReceiver.ts`"

        ```typescript
          // Load the chain configuration from the JSON file
          const chains: ChainsConfig = JSON.parse(
            fs.readFileSync(
              path.resolve(__dirname, '../deploy-config/chains.json'),
              'utf8'
            )
          );

          // Get the Base Sepolia configuration
          const baseSepoliaChain = chains.chains.find((chain) =>
            chain.description.includes('Base Sepolia testnet')
          );
        ```

    !!! note
        The `chains.json` file contains the configuration details for the Avalanche Fuji and Base Sepolia Testnets. You can modify this file to add more networks if needed. For a complete list of contract addresses, visit the [reference page](/docs/products/reference/contract-addresses/){target=\_blank}.

2. **Set up provider and wallet**: The scripts establish a connection to the blockchain using a provider and create a wallet instance using a private key. This wallet is responsible for signing the deployment transaction.

    === "`deploySender.ts`"

        ```typescript
          const provider = new ethers.JsonRpcProvider(avalancheChain.rpc);
          const wallet = new ethers.Wallet(process.env.PRIVATE_KEY, provider);
        ```

    === "`deployReceiver.ts`"

        ```typescript
          const provider = new ethers.JsonRpcProvider(baseSepoliaChain.rpc);
          const wallet = new ethers.Wallet(process.env.PRIVATE_KEY, provider);
        ```

3. **Deploy the contract**: The contract is deployed to the network specified in the configuration. Upon successful deployment, the contract address is returned, which is crucial for interacting with the contract later on.

    === "`deploySender.ts`"

        ```typescript
          const senderContract = await MessageSender.deploy(
            avalancheChain.wormholeRelayer
          );
          await senderContract.waitForDeployment();
        ```

    === "`deployReceiver.ts`"

        ```typescript
          const receiverContract = await MessageReceiver.deploy(
            baseSepoliaChain.wormholeRelayer
          );
          await receiverContract.waitForDeployment();
        ```

4. **Register the `MessageSender` on the target chain**: After you deploy the `MessageReceiver` contract on the Base Sepolia network, the sender contract address from Avalanche Fuji needs to be registered. This ensures that only messages from the registered `MessageSender` contract are processed.

    This additional step is essential to enforce emitter validation, preventing unauthorized senders from delivering messages to the `MessageReceiver` contract

    ```typescript
      // Retrieve the address of the MessageSender from the deployedContracts.json file
      const avalancheSenderAddress = deployedContracts.avalanche?.MessageSender;
      if (!avalancheSenderAddress) {
        throw new Error('Avalanche MessageSender address not found.');
      }

      // Define the source chain ID for Avalanche Fuji
      const sourceChainId = 6;

      // Call setRegisteredSender on the MessageReceiver contract
      const tx = await (receiverContract as any).setRegisteredSender(
        sourceChainId,
        ethers.zeroPadValue(avalancheSenderAddress, 32)
      );
      await tx.wait();
    ```

You can find the full code for the `deploySender.ts` and `deployReceiver.ts` below.

??? code "deploySender.ts"

    ```typescript
    import { ethers } from 'ethers';
    import fs from 'fs';
    import path from 'path';
    import dotenv from 'dotenv';
    import {
      ChainsConfig,
      DeployedContracts,
      MessageSenderJson,
    } from './interfaces';

    dotenv.config();

    async function main(): Promise<void> {
      // Load the chain configuration from JSON
      const chains: ChainsConfig = JSON.parse(
        fs.readFileSync(
          path.resolve(__dirname, '../deploy-config/chains.json'),
          'utf8'
        )
      );

      // Get the Avalanche Fuji configuration
      const avalancheChain = chains.chains.find((chain) =>
        chain.description.includes('Avalanche testnet')
      );
      if (!avalancheChain) {
        throw new Error(
          'Avalanche testnet configuration not found in chains.json.'
        );
      }

      // Set up the provider and wallet
      const provider = new ethers.JsonRpcProvider(avalancheChain.rpc);
      const wallet = new ethers.Wallet(process.env.PRIVATE_KEY, provider);

      // Load the ABI and bytecode of the MessageSender contract
      const messageSenderJson: MessageSenderJson = JSON.parse(
        fs.readFileSync(
          path.resolve(__dirname, '../out/MessageSender.sol/MessageSender.json'),
          'utf8'
        )
      );

      const { abi, bytecode } = messageSenderJson;

      // Create a ContractFactory for MessageSender
      const MessageSender = new ethers.ContractFactory(abi, bytecode, wallet);

      // Deploy the contract using the Wormhole Relayer address for Avalanche Fuji
      const senderContract = await MessageSender.deploy(
        avalancheChain.wormholeRelayer
      );
      await senderContract.waitForDeployment();

      console.log('MessageSender deployed to:', senderContract.target); // `target` is the address in ethers.js v6

      // Update the deployedContracts.json file
      const deployedContractsPath = path.resolve(
        __dirname,
        '../deploy-config/deployedContracts.json'
      );
      const deployedContracts: DeployedContracts = JSON.parse(
        fs.readFileSync(deployedContractsPath, 'utf8')
      );

      deployedContracts.avalanche = {
        MessageSender: senderContract.target as any,
        deployedAt: new Date().toISOString(),
      };

      fs.writeFileSync(
        deployedContractsPath,
        JSON.stringify(deployedContracts, null, 2)
      );
    }

    main().catch((error) => {
      console.error(error);
      process.exit(1);
    });
    ```

??? code "deployReceiver.ts"

    ```typescript
    import { ethers } from 'ethers';
    import fs from 'fs';
    import path from 'path';
    import dotenv from 'dotenv';
    import {
      ChainsConfig,
      DeployedContracts,
      MessageReceiverJson,
    } from './interfaces';

    dotenv.config();

    async function main(): Promise<void> {
      // Load the chain configuration from the JSON file
      const chains: ChainsConfig = JSON.parse(
        fs.readFileSync(
          path.resolve(__dirname, '../deploy-config/chains.json'),
          'utf8'
        )
      );

      // Get the Base Sepolia configuration
      const baseSepoliaChain = chains.chains.find((chain) =>
        chain.description.includes('Base Sepolia testnet')
      );
      if (!baseSepoliaChain) {
        throw new Error('Base Sepolia testnet configuration not found.');
      }

      // Set up the provider and wallet
      const provider = new ethers.JsonRpcProvider(baseSepoliaChain.rpc);
      const wallet = new ethers.Wallet(process.env.PRIVATE_KEY, provider);

      // Load the ABI and bytecode of the MessageReceiver contract
      const messageReceiverJson: MessageReceiverJson = JSON.parse(
        fs.readFileSync(
          path.resolve(
            __dirname,
            '../out/MessageReceiver.sol/MessageReceiver.json'
          ),
          'utf8'
        )
      );

      const { abi, bytecode } = messageReceiverJson;

      // Create a ContractFactory for MessageReceiver
      const MessageReceiver = new ethers.ContractFactory(abi, bytecode, wallet);

      // Deploy the contract using the Wormhole Relayer address for Base Sepolia
      const receiverContract = await MessageReceiver.deploy(
        baseSepoliaChain.wormholeRelayer
      );
      await receiverContract.waitForDeployment();

      console.log('MessageReceiver deployed to:', receiverContract.target); // `target` is the contract address in ethers.js v6

      // Update the deployedContracts.json file
      const deployedContractsPath = path.resolve(
        __dirname,
        '../deploy-config/deployedContracts.json'
      );
      const deployedContracts: DeployedContracts = JSON.parse(
        fs.readFileSync(deployedContractsPath, 'utf8')
      );

      // Retrieve the address of the MessageSender from the deployedContracts.json file
      const avalancheSenderAddress = deployedContracts.avalanche?.MessageSender;
      if (!avalancheSenderAddress) {
        throw new Error('Avalanche MessageSender address not found.');
      }

      // Define the source chain ID for Avalanche Fuji
      const sourceChainId = 6;

      // Call setRegisteredSender on the MessageReceiver contract
      const tx = await (receiverContract as any).setRegisteredSender(
        sourceChainId,
        ethers.zeroPadValue(avalancheSenderAddress, 32)
      );
      await tx.wait();

      console.log(
        `Registered MessageSender (${avalancheSenderAddress}) for Avalanche chain (${sourceChainId})`
      );

      deployedContracts.baseSepolia = {
        MessageReceiver: receiverContract.target as any,
        deployedAt: new Date().toISOString(),
      };

      fs.writeFileSync(
        deployedContractsPath,
        JSON.stringify(deployedContracts, null, 2)
      );
    }

    main().catch((error) => {
      console.error(error);
      process.exit(1);
    });
    ```

### Deploy the Sender Contract

The sender contract will handle quoting and sending messages cross-chain.

1. Run the following command to deploy the sender contract:

    ```bash
    npm run deploy:sender
    ```

2. Once deployed, the contract address will be displayed. You may check the contract on the [Avalanche Fuji Explorer](https://testnet.snowtrace.io/){target=\_blank}.

<div id="termynal" data-termynal>
	<span data-ty="input"
		><span class="file-path"></span>npm run deploy:sender</span
	>
	<span data-ty> > wormhole-cross-chain@1.0.0 deploy:sender</span>
	<span data-ty> > node script/deploySender.ts</span>
	<span data-ty> MessageSender deployed to: 0xf5c474f335fFf617fA6FD04DCBb17E20ee0cEfb1</span>
	<span data-ty="input"><span class="file-path"></span></span>
</div>
### Deploy the Receiver Contract

The receiver contract listens for cross-chain messages and logs them when received.

1. Deploy the receiver contract with this command:
    
    ```bash
    npm run deploy:receiver
    ```

2. After deployment, note down the contract address. You may check the contract on the [Base Sepolia Explorer](https://sepolia.basescan.org/){target=\_blank}.


## Send a Cross-Chain Message

Now that both the sender and receiver contracts are deployed, let's move on to the next exciting step: sending a cross-chain message from Avalanche Fuji to Base Sepolia.

In this example, we will use the `sendMessage.ts` script to transmit a message from the sender contract on Avalanche to the receiver contract on Base Sepolia. The script uses [Ethers.js](https://docs.ethers.org/v6/){target=\_blank} to interact with the deployed contracts, calculate the cross-chain cost dynamically, and handle the transaction.

Let's break down the script step by step.

1. **Load configuration files**:

    1. **`chains.json`**: Contains details about the supported Testnet chains, such as RPC URLs and relayer addresses.
    2. **`deployedContracts.json`**: Stores the addresses of the deployed sender and receiver contracts. This file is dynamically updated when contracts are deployed, but users can also manually add their own deployed contract addresses if needed.

    ```typescript
      const chains: ChainsConfig = JSON.parse(
        fs.readFileSync(
          path.resolve(__dirname, '../deploy-config/chains.json'),
          'utf8'
        )
      );

      const deployedContracts: DeployedContracts = JSON.parse(
        fs.readFileSync(
          path.resolve(__dirname, '../deploy-config/deployedContracts.json'),
          'utf8'
        )
      );
    ```

2. **Configure the provider and signer**: The script first reads the chain configurations and extracts the contract addresses. One essential step in interacting with a blockchain is setting up a _provider_. A provider is your connection to the blockchain network. It allows your script to interact with the blockchain, retrieve data, and send transactions. In this case, we're using a JSON-RPC provider.

    Next, we configure the wallet, which will be used to sign transactions. The wallet is created using the private key and the provider. This ensures that all transactions sent from this wallet are broadcast to the Avalanche Fuji network.
        
    ```typescript
      const provider = new ethers.JsonRpcProvider(avalancheChain.rpc);
      const wallet = new ethers.Wallet(process.env.PRIVATE_KEY, provider);
    ```

    After setting up the wallet, the script loads the ABI for the `MessageSender.sol` contract and creates an instance of it.

    ```typescript
      const messageSenderJson = JSON.parse(
        fs.readFileSync(
          path.resolve(__dirname, '../out/MessageSender.sol/MessageSender.json'),
          'utf8'
        )
      );
    ```

3. **Set up the message details**: The next part of the script defines the target chain (Base Sepolia) and the target address (the receiver contract on Base Sepolia).

    ```typescript
      const targetChain = 10004; // Wormhole chain ID for Base Sepolia
      const targetAddress = deployedContracts.baseSepolia.MessageReceiver;
    ```

    You can customize the message that will be sent across chains.

    ```typescript
      const message = 'Hello from Avalanche to Base Sepolia!';
    ```

4. **Estimate cross-chain cost**: Before sending the message, we dynamically calculate the cross-chain cost using the `quoteCrossChainCost` function.

    ```typescript
      const txCost = await MessageSender.quoteCrossChainCost(targetChain);
    ```

    This ensures that the transaction includes enough funds to cover the gas fees for the cross-chain message.

5. **Send a message**: With everything set up, the message is sent using the `sendMessage` function.

    ```typescript
      const tx = await MessageSender.sendMessage(
        targetChain,
        targetAddress,
        message,
        {
          value: txCost,
        }
      );
    ```

    After sending, the script waits for the transaction to be confirmed.

    ```typescript
      await tx.wait();
    ```

6. **Run the script**: To send the message, run the following command:

    ```bash
    npm run send:message
    ```

If everything is set up correctly, the message will be sent from the Avalanche Fuji Testnet to the Base Sepolia Testnet. You can monitor the transaction and verify that the message was received on Base Sepolia using the [Wormhole Explorer](https://wormholescan.io/#/?network=TESTNET){target=\_blank}.

The console should output something similar to this:

<div id="termynal" data-termynal>
	<span data-ty="input"
		><span class="file-path"></span>npm run send:message</span
	>
	<span data-ty> > wormhole-cross-chain@1.0.0 send:message</span>
	<span data-ty> > node script/sendMessage.ts</span>
	<span data-ty
		>Sender Contract Address: 0xD720BFF42a0960cfF1118454A907a44dB358f2b1</span
	>
	<span data-ty
		>Receiver Contract Address: 0x692550997C252cC5044742D1A2BD91E4f4b46D39</span
	>
	<span data-ty>...</span>
	<span data-ty>Transaction sent, waiting for confirmation...</span>
	<span data-ty>...</span>
	<span data-ty
		>Message sent! Transaction hash:
		0x9d359a66ba42baced80062229c0b02b4f523fe304aff3473dcf53117aee13fb6</span
	>
	<span data-ty
		>You may see the transaction status on the Wormhole Explorer:
		https://wormholescan.io/#/tx/0x9d359a66ba42baced80062229c0b02b4f523fe304aff3473dcf53117aee13fb6?network=TESTNET</span
	>
	<span data-ty="input"><span class="file-path"></span></span>
</div>
You can find the full code for the `sendMessage.ts` below.

??? code "sendMessage.ts"

    ```solidity
    import { ethers } from 'ethers';
    import fs from 'fs';
    import path from 'path';
    import dotenv from 'dotenv';
    import { ChainsConfig, DeployedContracts } from './interfaces';

    dotenv.config();

    async function main(): Promise<void> {
      // Load the chain configuration and deployed contract addresses
      const chains: ChainsConfig = JSON.parse(
        fs.readFileSync(
          path.resolve(__dirname, '../deploy-config/chains.json'),
          'utf8'
        )
      );

      const deployedContracts: DeployedContracts = JSON.parse(
        fs.readFileSync(
          path.resolve(__dirname, '../deploy-config/deployedContracts.json'),
          'utf8'
        )
      );

      console.log(
        'Sender Contract Address: ',
        deployedContracts.avalanche.MessageSender
      );
      console.log(
        'Receiver Contract Address: ',
        deployedContracts.baseSepolia.MessageReceiver
      );
      console.log('...');

      // Get the Avalanche Fuji configuration
      const avalancheChain = chains.chains.find((chain) =>
        chain.description.includes('Avalanche testnet')
      );

      if (!avalancheChain) {
        throw new Error(
          'Avalanche testnet configuration not found in chains.json.'
        );
      }

      // Set up the provider and wallet
      const provider = new ethers.JsonRpcProvider(avalancheChain.rpc);
      const wallet = new ethers.Wallet(process.env.PRIVATE_KEY, provider);

      // Load the ABI of the MessageSender contract
      const messageSenderJson = JSON.parse(
        fs.readFileSync(
          path.resolve(__dirname, '../out/MessageSender.sol/MessageSender.json'),
          'utf8'
        )
      );

      const abi = messageSenderJson.abi;

      // Create a contract instance for MessageSender
      const MessageSender = new ethers.Contract(
        deployedContracts.avalanche.MessageSender, // Automatically use the deployed address
        abi,
        wallet
      );

      // Define the target chain and target address (the Base Sepolia receiver contract)
      const targetChain = 10004; // Wormhole chain ID for Base Sepolia
      const targetAddress = deployedContracts.baseSepolia.MessageReceiver;

      // The message you want to send
      const message = 'Hello from Avalanche to Base Sepolia!';

      // Dynamically quote the cross-chain cost
      const txCost = await MessageSender.quoteCrossChainCost(targetChain);

      // Send the message (make sure to send enough gas in the transaction)
      const tx = await MessageSender.sendMessage(
        targetChain,
        targetAddress,
        message,
        {
          value: txCost,
        }
      );

      console.log('Transaction sent, waiting for confirmation...');
      await tx.wait();
      console.log('...');

      console.log('Message sent! Transaction hash:', tx.hash);
      console.log(
        `You may see the transaction status on the Wormhole Explorer: https://wormholescan.io/#/tx/${tx.hash}?network=TESTNET`
      );
    }

    main().catch((error) => {
      console.error(error);
      process.exit(1);
    });
    ```

## Conclusion

You're now fully equipped to build cross-chain contracts using the Wormhole protocol! With this tutorial, you've learned how to:

- Deploy sender and receiver contracts on different testnets.
- Send a cross-chain message from one blockchain to another.
- Monitor the status of your cross-chain transactions using Wormholescan and the Wormhole Solidity SDK.

Looking for more? Check out the [Wormhole Tutorial Demo repository](https://github.com/wormhole-foundation/demo-tutorials){target=\_blank} for additional examples.


---

Page Title: Cross-Chain Token Transfers

- Resolved Markdown: https://wormhole.com/docs/ai/pages/products-messaging-tutorials-cross-chain-token-contracts.md
- Canonical (HTML): https://wormhole.com/docs/products/messaging/tutorials/cross-chain-token-contracts/
- Summary: Learn how to create cross-chain token transfers using Wormhole's Solidity SDK. Build and deploy smart contracts to send tokens from one blockchain to another.
- Word Count: 7064; Token Estimate: 12503

# Create Cross-Chain Token Transfer Contracts

:simple-github: [Source code on GitHub](https://github.com/wormhole-foundation/demo-cross-chain-token-transfer){target=\_blank}

In this tutorial, you'll learn how to create a simple cross-chain token transfer system using the Wormhole protocol via the [Wormhole Solidity SDK](https://github.com/wormhole-foundation/wormhole-solidity-sdk){target=\_blank}. We'll guide you through building and deploying smart contracts that enable seamless token transfers of IERC-20 tokens between blockchains. Whether you're a developer looking to explore cross-chain applications or just interested in the Wormhole protocol, this guide will help you understand the fundamentals.

By the end of this tutorial, you'll have a working cross-chain token transfer system built with the powerful tools provided by the Wormhole Solidity SDK, which you can further customize and integrate into your projects.

## Prerequisites

Before you begin, ensure you have the following:

- [Node.js and npm](https://docs.npmjs.com/downloading-and-installing-node-js-and-npm){target=\_blank} installed on your machine.
- [Foundry](https://getfoundry.sh/introduction/installation/){target=\_blank} for deploying contracts.
- Testnet tokens for [Avalanche-Fuji](https://core.app/tools/testnet-faucet/?token=C){target=\_blank} and [Base Sepolia](https://faucets.chain.link/base-sepolia){target=\_blank} to cover gas fees.
- [USDC Testnet](https://faucet.circle.com/){target=\_blank} tokens on Avalanche-Fuji or/and Base Sepolia for cross-chain transfer.
- Wallet private key.

## Valid Tokens for Transfer

It's important to note that this tutorial leverages [Wormhole's TokenBridge](https://github.com/wormhole-foundation/wormhole/blob/6130bbb6f456b42b789a71f7ea2fd049d632d2fb/ethereum/contracts/bridge/TokenBridge.sol){target=\_blank} to transfer tokens between chains. So, the tokens you'd like to transfer must have an attestation on the `TokenBridge` contract of the target blockchain.

To simplify this process, we've included a tool for verifying if a token has an attestation on the target chain. This tool uses the [`wrappedAsset`](https://github.com/wormhole-foundation/wormhole/blob/6130bbb6f456b42b789a71f7ea2fd049d632d2fb/ethereum/contracts/bridge/BridgeGetters.sol#L50-L52){target=\_blank} function from the `TokenBridge` contract. If the token has an attestation, the `wrappedAsset` function returns the address of the wrapped token on the target chain; otherwise, it returns the zero address.

???- tip "Check Token Attestation"
    1. Clone the [repository](https://github.com/wormhole-foundation/demo-cross-chain-token-transfer){target=\_blank} and navigate to the project directory:

        ```bash
        git clone https://github.com/wormhole-foundation/demo-cross-chain-token-transfer.git
        cd cross-chain-token-transfers
        ```

    2. Install the dependencies:

        ```bash
        npm install
        ```
    
    3. Run the script to check token attestation:

        ```bash
        npm run verify
        ```

    4. Follow the prompts:

        1. Enter the RPC URL of the target chain.
        2. Enter the `TokenBridge` contract address on the target chain.
        3. Enter the token contract address on the source chain.
        4. Enter the source chain ID.

    5. The expected output when the token has an attestation:
        
        <div id="termynal" data-termynal>
        	<span data-ty="input"><span class="file-path"></span>npm run verify</span>
        	<span data-ty> > cross-chain-token-transfer@1.0.0 verify</span>
        	<span data-ty> > npx ts-node script/check-attestation.ts</span>
          <span data-ty> </span>
        	<span data-ty> Enter the TARGET chain RPC URL: https://base-sepolia-rpc.publicnode.com</span>
        	<span data-ty> Enter the WTT contract address on the TARGET chain: 0x05...E153</span>
          <span data-ty> Enter the token contract address on the SOURCE chain: 0x54...bc65</span>
          <span data-ty> Enter the SOURCE chain ID: 6</span>
          <span data-ty> The token is attested on the target chain. Wrapped token address: 0xDDB349c976cA2C873644F21f594767Eb5390C831</span>
        	<span data-ty="input"><span class="file-path"></span></span>
        </div>
    Using this tool ensures that you only attempt to transfer tokens with verified attestations, avoiding any potential issues during the cross-chain transfer process.

## Project Setup

Let's start by initializing a new Foundry project. This will set up a basic structure for our smart contracts.

1. Open your terminal and run the following command to initialize a new Foundry project:
    
    ```bash
    forge init cross-chain-token-transfers
    ```

    This will create a new directory named `cross-chain-token-transfers` with a basic project structure. This also initializes a new `git` repository.

2. Navigate into the newly created project directory:

    ```bash
    cd cross-chain-token-transfers
    ```

3. Install the Wormhole Solidity SDK:

    ```bash
    forge install wormhole-foundation/wormhole-solidity-sdk
    ```

    To ease development, we'll use the Wormhole Solidity SDK, which provides useful helpers for cross-chain development.
    This SDK includes the `TokenSender` and `TokenReceiver` abstract classes, which simplify sending and receiving tokens across chains.

## Build Cross-Chain Contracts

In this section, we'll build two smart contracts to send tokens from a source chain and receive them on a target chain. These contracts will interact with the Wormhole protocol to facilitate secure and seamless cross-chain token transfers.

At a high level, our contracts will:

1. Send tokens from one blockchain to another using the Wormhole protocol.
2. Receive and process the tokens on the target chain, ensuring they are correctly transferred to the intended recipient.

Before diving into the contract implementation steps, let’s first break down the key parts of the contracts.

### Sender Contract: CrossChainSender

The `CrossChainSender` contract calculates the cost of sending tokens across chains and then facilitates the actual token transfer.

Let's start writing the `CrossChainSender` contract:

1. Create a new file named `CrossChainSender.sol` in the `/src` directory:
    
    ```bash
    touch src/CrossChainSender.sol
    ```

2. Open the file. First, we'll start with the imports and the contract setup:

    ```solidity
    // SPDX-License-Identifier: MIT
    pragma solidity ^0.8.13;

    import "lib/wormhole-solidity-sdk/src/WormholeRelayerSDK.sol";
    import "lib/wormhole-solidity-sdk/src/interfaces/IERC20.sol";

    contract CrossChainSender is TokenSender {
        uint256 constant GAS_LIMIT = 250_000;

        constructor(
            address _wormholeRelayer,
            address _tokenBridge,
            address _wormhole
        ) TokenBase(_wormholeRelayer, _tokenBridge, _wormhole) {}
    }
    ```

    This sets up the basic structure of the contract, including the necessary imports and the constructor that initializes the contract with the Wormhole-related addresses.

    With the contract structure in place, define the following functions within its body to enable multichain token transfers.

3. Next, let's add a function that estimates the cost of sending tokens across chains:

    ```solidity
        function quoteCrossChainDeposit(
            uint16 targetChain
        ) public view returns (uint256 cost) {
            uint256 deliveryCost;
            (deliveryCost, ) = wormholeRelayer.quoteEVMDeliveryPrice(
                targetChain,
                0,
                GAS_LIMIT
            );

            cost = deliveryCost + wormhole.messageFee();
        }
    ```

    This function, `quoteCrossChainDeposit`, helps calculate the cost of transferring tokens to a different chain. It factors in the delivery cost and the cost of publishing a message via the Wormhole protocol.

4. Finally, we'll add the function that sends the tokens across chains:

    ```solidity
        function sendCrossChainDeposit(
            uint16 targetChain,
            address targetReceiver,
            address recipient,
            uint256 amount,
            address token
        ) public payable {
            uint256 cost = quoteCrossChainDeposit(targetChain);
            require(
                msg.value == cost,
                "msg.value must equal quoteCrossChainDeposit(targetChain)"
            );

            IERC20(token).transferFrom(msg.sender, address(this), amount);

            bytes memory payload = abi.encode(recipient);

            sendTokenWithPayloadToEvm(
                targetChain,
                targetReceiver,
                payload,
                0,
                GAS_LIMIT,
                token,
                amount
            );
        }
    ```

    This `sendCrossChainDeposit` function is where the actual token transfer happens. It sends the tokens to the recipient on the target chain using the Wormhole protocol.

Here’s a breakdown of what happens in each step of the `sendCrossChainDeposit` function:

1. **Cost calculation**: The function starts by calculating the cost of the cross-chain transfer using `quoteCrossChainDeposit`(`targetChain`). This cost includes both the delivery fee and the Wormhole message fee. The `sendCrossChainDeposit` function then checks that the user has sent the correct amount of Ether to cover this cost (`msg.value`).

2. **Token transfer to contract**: The next step is to transfer the specified amount of tokens from the user to the contract itself using `IERC-20(token).transferFrom(msg.sender, address(this), amount)`. This ensures that the contract has custody of the tokens before initiating the cross-chain transfer.

3. **Payload encoding**: The recipient's address on the target chain is encoded into a payload using `abi.encode(recipient)`. This payload will be sent along with the token transfer, so the target contract knows who should receive the tokens on the destination chain.

4. **Cross-chain transfer**: The `sendTokenWithPayloadToEvm` function is called to initiate the cross-chain token transfer. This function does the following:
    - Specifies the `targetChain` (the Wormhole chain ID of the destination blockchain).
    - Sends the `targetReceiver` contract address on the target chain that will receive the tokens.
    - Attaches the payload containing the recipient's address.
    - Sets the `GAS_LIMIT` for the transaction.
    - Passes the token `address` and `amount` to transfer.

    This triggers the Wormhole protocol to handle the cross-chain messaging and token transfer, ensuring the tokens and payload reach the correct destination on the target chain.

You can find the complete code for the `CrossChainSender.sol` below.

??? code "CrossChainSender.sol"

    ```solidity
    // SPDX-License-Identifier: MIT
    pragma solidity ^0.8.13;

    import "lib/wormhole-solidity-sdk/src/WormholeRelayerSDK.sol";
    import "lib/wormhole-solidity-sdk/src/interfaces/IERC20.sol";

    contract CrossChainSender is TokenSender {
        uint256 constant GAS_LIMIT = 250_000;

        constructor(
            address _wormholeRelayer,
            address _tokenBridge,
            address _wormhole
        ) TokenBase(_wormholeRelayer, _tokenBridge, _wormhole) {}

        // Function to get the estimated cost for cross-chain deposit
        function quoteCrossChainDeposit(
            uint16 targetChain
        ) public view returns (uint256 cost) {
            uint256 deliveryCost;
            (deliveryCost, ) = wormholeRelayer.quoteEVMDeliveryPrice(
                targetChain,
                0,
                GAS_LIMIT
            );

            cost = deliveryCost + wormhole.messageFee();
        }

        // Function to send tokens and payload across chains
        function sendCrossChainDeposit(
            uint16 targetChain,
            address targetReceiver,
            address recipient,
            uint256 amount,
            address token
        ) public payable {
            uint256 cost = quoteCrossChainDeposit(targetChain);
            require(
                msg.value == cost,
                "msg.value must equal quoteCrossChainDeposit(targetChain)"
            );

            IERC20(token).transferFrom(msg.sender, address(this), amount);

            bytes memory payload = abi.encode(recipient);

            sendTokenWithPayloadToEvm(
                targetChain,
                targetReceiver,
                payload,
                0,
                GAS_LIMIT,
                token,
                amount
            );
        }
    }
    ```

### Receiver Contract: CrossChainReceiver

The `CrossChainReceiver` contract is designed to handle the receipt of tokens and payloads from another blockchain. It ensures that the tokens are correctly transferred to the designated recipient on the receiving chain.

Let's start writing the `CrossChainReceiver` contract:

1. Create a new file named `CrossChainReceiver.sol` in the `/src` directory:

    ```bash
    touch src/CrossChainReceiver.sol
    ```

2. Open the file. First, we'll start with the imports and the contract setup:

    ```solidity
    // SPDX-License-Identifier: MIT
    pragma solidity ^0.8.13;

    import "lib/wormhole-solidity-sdk/src/WormholeRelayerSDK.sol";
    import "lib/wormhole-solidity-sdk/src/interfaces/IERC20.sol";

    contract CrossChainReceiver is TokenReceiver {
        // The Wormhole relayer and registeredSenders are inherited from the Base.sol contract

        constructor(
            address _wormholeRelayer,
            address _tokenBridge,
            address _wormhole
        ) TokenBase(_wormholeRelayer, _tokenBridge, _wormhole) {}
    }
    ```

    Similar to the `CrossChainSender` contract, this sets up the basic structure of the contract, including the necessary imports and the constructor that initializes the contract with the Wormhole-related addresses.

3. Next, let's add a function inside the contract to handle receiving the payload and tokens:

    ```solidity
        function receivePayloadAndTokens(
            bytes memory payload,
            TokenReceived[] memory receivedTokens,
            bytes32 sourceAddress,
            uint16 sourceChain,
            bytes32 // deliveryHash
        )
            internal
            override
            onlyWormholeRelayer
            isRegisteredSender(sourceChain, sourceAddress)
        {
            require(receivedTokens.length == 1, "Expected 1 token transfer");

            // Decode the recipient address from the payload
            address recipient = abi.decode(payload, (address));

            // Transfer the received tokens to the intended recipient
            IERC20(receivedTokens[0].tokenAddress).transfer(
                recipient,
                receivedTokens[0].amount
            );
        }
    ```

    This `receivePayloadAndTokens` function processes the tokens and payload sent from another chain, decodes the recipient address, and transfers the tokens to them using the Wormhole protocol. This function also validates the emitter (`sourceAddress`) to ensure the message comes from a trusted sender.

    This function ensures that:

    - It only processes one token transfer at a time.
    - The `sourceAddress` is checked against a list of registered senders using the `isRegisteredSender` modifier, which verifies if the emitter is allowed to send tokens to this contract.
    - The recipient address is decoded from the payload, and the received tokens are transferred to them using the ERC-20 interface.

After we call `sendTokenWithPayloadToEvm` on the source chain, the message goes through the standard Wormhole message lifecycle. Once a [VAA (Verifiable Action Approval)](/docs/protocol/infrastructure/vaas/){target=\_blank} is available, the delivery provider will call `receivePayloadAndTokens` on the target chain and target address specified, with the appropriate inputs.

??? tip "Understanding the `TokenReceived` Struct"

    Let’s delve into the fields provided to us in the `TokenReceived` struct:

    ```solidity
    struct TokenReceived {
        bytes32 tokenHomeAddress;
        uint16 tokenHomeChain;
        address tokenAddress;
        uint256 amount;
        uint256 amountNormalized;
    }
    ```

    - **`tokenHomeAddress`**: The original address of the token on its native chain. This is the same as the token field in the call to `sendTokenWithPayloadToEvm` unless the original token sent is a Wormhole-wrapped token. In that case, this will be the address of the original version of the token (on its native chain) in Wormhole address format (left-padded with 12 zeros).

    - **`tokenHomeChain`**: The Wormhole chain ID corresponding to the home address above. This will typically be the source chain unless the original token sent is a Wormhole-wrapped asset, which will be the chain of the unwrapped version of the token.

    - **`tokenAddress`**: The address of the IERC-20 token on the target chain that has been transferred to this contract. If `tokenHomeChain` equals the target chain, this will be the same as `tokenHomeAddress`; otherwise, it will be the Wormhole-wrapped version of the token sent.

    - **`amount`**: The token amount sent to you with the same units as the original token. Since `TokenBridge` only sends with eight decimals of precision, if your token has 18 decimals, this will be the "amount" you sent, rounded down to the nearest multiple of 10^10.

    - **`amountNormalized`**: The amount of token divided by (1 if decimals ≤ 8, else 10^(decimals - 8)).

You can find the complete code for the `CrossChainReceiver.sol` contract below:

??? code "CrossChainReceiver.sol"

    ```solidity
    // SPDX-License-Identifier: MIT
    pragma solidity ^0.8.13;

    import "lib/wormhole-solidity-sdk/src/WormholeRelayerSDK.sol";
    import "lib/wormhole-solidity-sdk/src/interfaces/IERC20.sol";

    contract CrossChainReceiver is TokenReceiver {
        // The Wormhole relayer and registeredSenders are inherited from the Base.sol contract

        constructor(
            address _wormholeRelayer,
            address _tokenBridge,
            address _wormhole
        ) TokenBase(_wormholeRelayer, _tokenBridge, _wormhole) {}

        // Function to receive the cross-chain payload and tokens with emitter validation
        function receivePayloadAndTokens(
            bytes memory payload,
            TokenReceived[] memory receivedTokens,
            bytes32 sourceAddress,
            uint16 sourceChain,
            bytes32 // deliveryHash
        )
            internal
            override
            onlyWormholeRelayer
            isRegisteredSender(sourceChain, sourceAddress)
        {
            require(receivedTokens.length == 1, "Expected 1 token transfer");

            // Decode the recipient address from the payload
            address recipient = abi.decode(payload, (address));

            // Transfer the received tokens to the intended recipient
            IERC20(receivedTokens[0].tokenAddress).transfer(
                recipient,
                receivedTokens[0].amount
            );
        }
    }
    ```

## Deploy the Contracts

Now that you've written the `CrossChainSender` and `CrossChainReceiver` contracts, it's time to deploy them to your chosen networks.

1. **Set up deployment configuration**: Before deploying, you must configure the networks and the deployment environment. This information is stored in a configuration file.

    1. Create a directory named deploy-config in the root of your project:

        ```bash
        mkdir deploy-config
        ```

    2. Create a `config.json` file in the `deploy-config` directory:

        ```bash
        touch deploy-config/config.json
        ```

    3. Open the `config.json` file and add the following configuration:

        ```json
        {
            "chains": [
                {
                    "description": "Avalanche testnet fuji",
                    "chainId": 6,
                    "rpc": "https://api.avax-test.network/ext/bc/C/rpc",
                    "tokenBridge": "0x61E44E506Ca5659E6c0bba9b678586fA2d729756",
                    "wormholeRelayer": "0xA3cF45939bD6260bcFe3D66bc73d60f19e49a8BB",
                    "wormhole": "0x7bbcE28e64B3F8b84d876Ab298393c38ad7aac4C"
                },
                {
                    "description": "Base Sepolia",
                    "chainId": 10004,
                    "rpc": "https://base-sepolia-rpc.publicnode.com",
                    "tokenBridge": "0x86F55A04690fd7815A3D802bD587e83eA888B239",
                    "wormholeRelayer": "0x93BAD53DDfB6132b0aC8E37f6029163E63372cEE",
                    "wormhole": "0x79A1027a6A159502049F10906D333EC57E95F083"
                }
            ]
        }
        ```

        This file specifies the details for each chain where you plan to deploy your contracts, including the RPC URL, the `TokenBridge` address, the relayer, and the Wormhole Core contract.

        For a complete list of Wormhole contract addresses on various blockchains, refer to the [Wormhole Contract Addresses](/docs/products/reference/contract-addresses/){target=\_blank}.

        !!! note
            You can add your desired chains to this file by specifying the required fields for each chain. In this example, we use the Avalanche Fuji and Base Sepolia Testnets.

    4. Create a `contracts.json` file in the `deploy-config` directory:

        ```bash
        echo '{}' > deploy-config/contracts.json
        ```

        This file can be left blank initially. It will be automatically updated with the deployed contract addresses after a successful deployment.

2. **Set up your Node.js environment**: You'll need to set up your Node.js environment to run the deployment script.

    1. Initialize a Node.js project:

        ```bash
        npm init -y
        ```

    2. Create a `.gitignore` file to ensure your private key isn't accidentally exposed or committed to version control:

    ```bash
    echo ".env" >> .gitignore
    ```
    
    3. Install the necessary dependencies:

        ```bash
        npm install ethers dotenv readline-sync @types/readline-sync
        ```

        These dependencies are required for the deployment script to work properly.

3. **Compile your smart contracts**: Compile your smart contracts using Foundry. This ensures that your contracts are up-to-date and ready for deployment.

    - Run the following command to compile your contracts:

        ```bash
        forge build
        ```

        This will generate the necessary ABI and bytecode files in a directory named `/out`.

    The expected output should be similar to this:

    <div id="termynal" data-termynal>
    	<span data-ty="input"><span class="file-path"></span>forge build</span>
    	<span data-ty> > [⠒] Compiling...</span>
    	<span data-ty> > [⠰] Compiling 30 files with 0.8.23</span>
    	<span data-ty> > [⠔] Solc 0.8.23 finished in 2.29s</span>
    	<span data-ty>Compiler run successful!</span>
    	<span data-ty="input"><span class="file-path"></span></span>
    </div>
4. **Write the deployment script**: You’ll need a script to automate the deployment of your contracts. Let’s create the deployment script.

    1. Create a new file named `deploy.ts` in the `/script` directory:

        ```bash
        touch script/deploy.ts
        ```

    2. Open the file and load imports and configuration:

        ```typescript
        import { BytesLike, ethers } from 'ethers';
        import * as fs from 'fs';
        import * as path from 'path';
        import * as dotenv from 'dotenv';
        import readlineSync from 'readline-sync';

        dotenv.config();
        ```

        Import the required libraries and modules to interact with Ethereum, handle file paths, load environment variables, and enable user interaction via the terminal.

    3. Define interfaces to use for chain configuration and contract deployment:

        ```typescript
        interface ChainConfig {
          description: string;
          chainId: number;
          rpc: string;
          tokenBridge: string;
          wormholeRelayer: string;
          wormhole: string;
        }

        interface DeployedContracts {
          [chainId: number]: {
            networkName: string;
            CrossChainSender?: string;
            CrossChainReceiver?: string;
            deployedAt: string;
          };
        }
        ```

        These interfaces define the structure of the chain configuration and the contract deployment details.

    4. Load and select the chains for deployment:

        ```typescript
        function loadConfig(): ChainConfig[] {
          const configPath = path.resolve(__dirname, '../deploy-config/config.json');
          return JSON.parse(fs.readFileSync(configPath, 'utf8')).chains;
        }

        function selectChain(
          chains: ChainConfig[],
          role: 'source' | 'target'
        ): ChainConfig {
          console.log(`\nSelect the ${role.toUpperCase()} chain:`);
          chains.forEach((chain, index) => {
            console.log(`${index + 1}: ${chain.description}`);
          });

          const chainIndex =
            readlineSync.questionInt(
              `\nEnter the number for the ${role.toUpperCase()} chain: `
            ) - 1;
          return chains[chainIndex];
        }
        ```

        The `loadConfig` function reads the chain configuration from the `config.json` file, and the `selectChain` function allows the user to choose the source and target chains for deployment interactively. The user is prompted in the terminal to select which chains to use, making the process interactive and user-friendly.

    5. Define the main function for deployment and load the chain configuration:

        ```typescript
        async function main() {
          const chains = loadConfig();

          const sourceChain = selectChain(chains, 'source');
          const targetChain = selectChain(chains, 'target');
        ```

        - The `main` function is the entry point for the deployment script.
        - We then call the `loadConfig` function we previously defined to load the chain configuration from the `config.json` file.

    6. Set up provider and wallet: 
    
        ```typescript
          const sourceProvider = new ethers.JsonRpcProvider(sourceChain.rpc);
          const targetProvider = new ethers.JsonRpcProvider(targetChain.rpc);
          const wallet = new ethers.Wallet(process.env.PRIVATE_KEY!, sourceProvider);
        ```
        
        The scripts establish a connection to the blockchain using a provider and create a wallet instance using a private key. This wallet is responsible for signing the deployment transaction on the source chain.

    7. Read the compiled contracts:

        ```typescript
          const senderJson = JSON.parse(
            fs.readFileSync(
              path.resolve(
                __dirname,
                '../out/CrossChainSender.sol/CrossChainSender.json'
              ),
              'utf8'
            )
          );
        ```

        - This code reads the `CrossChainSender.json` file, the compiled output of the `CrossChainSender.sol` contract.
        - The file is in the `../out/` directory, which contains the ABI (Application Binary Interface) and bytecode generated during contract compilation.
        - It uses the `fs.readFileSync` function to read the file and `JSON.parse` to convert the file contents (in JSON format) into a JavaScript object.

    8. Extract the contract ABI and bytecode:

        ```typescript
          const abi = senderJson.abi;
          const bytecode = senderJson.bytecode;
        ```

        - **ABI (Application Binary Interface)**: Defines the structure of the contract’s functions, events, and data types, allowing the front end to interact with the contract on the blockchain.
        - **Bytecode**: This is the compiled machine code that will be deployed to the blockchain to create the contract.

    9. Create the Contract Factory:

        ```typescript
          const CrossChainSenderFactory = new ethers.ContractFactory(
            abi,
            bytecode,
            wallet
          );
        ```

        - **`ethers.ContractFactory`**: Creates a new contract factory using the ABI, bytecode, and a wallet (representing the signer). The contract factory is responsible for deploying instances of the contract to the blockchain.
        - This is a crucial step for deploying the contract since the factory will create and deploy the `CrossChainSender` contract.

    10. Deploy the `CrossChainSender` and `CrossChainReceiver` contracts:

        === "`CrossChainSender`"
            ```typescript
              try {
                const senderContract = await CrossChainSenderFactory.deploy(
                  sourceChain.wormholeRelayer,
                  sourceChain.tokenBridge,
                  sourceChain.wormhole
                );
                await senderContract.waitForDeployment();
            ```

        === "`CrossChainReceiver`"
            ```typescript
                const targetWallet = new ethers.Wallet(
                  process.env.PRIVATE_KEY!,
                  targetProvider
                );
                const receiverJson = JSON.parse(
                  fs.readFileSync(
                    path.resolve(
                      __dirname,
                      '../out/CrossChainReceiver.sol/CrossChainReceiver.json'
                    ),
                    'utf8'
                  )
                );
                const CrossChainReceiverFactory = new ethers.ContractFactory(
                  receiverJson.abi,
                  receiverJson.bytecode,
                  targetWallet
                );

                const receiverContract = await CrossChainReceiverFactory.deploy(
                  targetChain.wormholeRelayer,
                  targetChain.tokenBridge,
                  targetChain.wormhole
                );
                await receiverContract.waitForDeployment();
            ```

        Both functions deploy the respective contracts to the selected chains.

        For the `CrossChainReceiver` contract:

        - It defines the wallet related to the target chain.
        - The logic reads the compiled ABI and bytecode from the JSON file generated during compilation.
        - It creates a new contract factory using the ABI, bytecode, and wallet.
        - It deploys the contract to the selected chain passing in the relayer, `TokenBridge`, and Wormhole addresses.

    11. Save the deployed contract addresses:

        === "`senderAddress`"
            ```typescript
                const senderAddress = (senderContract as ethers.Contract).target;
                console.log(
                  `CrossChainSender on ${sourceChain.description}: ${senderAddress}`
                );
            ```

        === "`receiverAddress`"
            ```typescript
                const receiverAddress = (receiverContract as ethers.Contract).target;
                console.log(
                  `CrossChainReceiver on ${targetChain.description}: ${receiverAddress}`
                );
            ```

        You may display the deployed contract addresses in the terminal or save them to a JSON file for future reference.

    12. Register the `CrossChainSender` address on the target chain:

        ```typescript
            const CrossChainReceiverContract = new ethers.Contract(
              receiverAddress,
              receiverJson.abi,
              targetWallet
            );

            const tx = await CrossChainReceiverContract.setRegisteredSender(
              sourceChain.chainId,
              ethers.zeroPadValue(senderAddress as BytesLike, 32)
            );

            await tx.wait();
        ```

        After you deploy the `CrossChainReceiver` contract on the target network, the sender contract address from the source chain needs to be registered. This ensures that only messages from the registered `CrossChainSender` contract are processed.

        This additional step is essential to enforce emitter validation, preventing unauthorized senders from delivering messages to the `CrossChainReceiver` contract.

    13. Save the deployment details:

        ???- example "Save Deployment Details Example"
            ```typescript
                const deployedContractsPath = path.resolve(
                  __dirname,
                  '../deploy-config/contracts.json'
                );
                let deployedContracts: DeployedContracts = {};

                if (fs.existsSync(deployedContractsPath)) {
                  deployedContracts = JSON.parse(
                    fs.readFileSync(deployedContractsPath, 'utf8')
                  );
                }

                // Update the contracts.json file:
                // If a contract already exists on a chain, update its address; otherwise, add a new entry.
                if (!deployedContracts[sourceChain.chainId]) {
                  deployedContracts[sourceChain.chainId] = {
                    networkName: sourceChain.description,
                    deployedAt: new Date().toISOString(),
                  };
                }
                deployedContracts[sourceChain.chainId].CrossChainSender =
                  senderAddress.toString();
                deployedContracts[sourceChain.chainId].deployedAt =
                  new Date().toISOString();

                if (!deployedContracts[targetChain.chainId]) {
                  deployedContracts[targetChain.chainId] = {
                    networkName: targetChain.description,
                    deployedAt: new Date().toISOString(),
                  };
                }
                deployedContracts[targetChain.chainId].CrossChainReceiver =
                  receiverAddress.toString();
                deployedContracts[targetChain.chainId].deployedAt =
                  new Date().toISOString();

                // Save the updated contracts.json file
                fs.writeFileSync(
                  deployedContractsPath,
                  JSON.stringify(deployedContracts, null, 2)
                );
            ```
        
        Add your desired logic to save the deployed contract addresses in a JSON file (or another format). This will be important later when transferring tokens, as you'll need these addresses to interact with the deployed contracts.

    14. Handle errors and finalize the script:

        ```typescript
          } catch (error: any) {
            if (error.code === 'INSUFFICIENT_FUNDS') {
              console.error(
                'Error: Insufficient funds for deployment. Please make sure your wallet has enough funds to cover the gas fees.'
              );
            } else {
              console.error('An unexpected error occurred:', error.message);
            }
            process.exit(1);
          }
        }

        main().catch((error) => {
          console.error(error);
          process.exit(1);
        });
        ```

        The try-catch block wraps the deployment logic to catch any errors that may occur.

        - If the error is due to insufficient funds, it logs a clear message about needing more gas fees.
        - For any other errors, it logs the specific error message to help with debugging.

        The `process.exit(1)` ensures that the script exits with a failure status code if any error occurs.

    You can find the full code for the `deploy.ts` file below:

    ??? code "deploy.ts"

        ```solidity
        import { BytesLike, ethers } from 'ethers';
        import * as fs from 'fs';
        import * as path from 'path';
        import * as dotenv from 'dotenv';
        import readlineSync from 'readline-sync';

        dotenv.config();

        interface ChainConfig {
          description: string;
          chainId: number;
          rpc: string;
          tokenBridge: string;
          wormholeRelayer: string;
          wormhole: string;
        }

        interface DeployedContracts {
          [chainId: number]: {
            networkName: string;
            CrossChainSender?: string;
            CrossChainReceiver?: string;
            deployedAt: string;
          };
        }

        function loadConfig(): ChainConfig[] {
          const configPath = path.resolve(__dirname, '../deploy-config/config.json');
          return JSON.parse(fs.readFileSync(configPath, 'utf8')).chains;
        }

        function selectChain(
          chains: ChainConfig[],
          role: 'source' | 'target'
        ): ChainConfig {
          console.log(`\nSelect the ${role.toUpperCase()} chain:`);
          chains.forEach((chain, index) => {
            console.log(`${index + 1}: ${chain.description}`);
          });

          const chainIndex =
            readlineSync.questionInt(
              `\nEnter the number for the ${role.toUpperCase()} chain: `
            ) - 1;
          return chains[chainIndex];
        }

        async function main() {
          const chains = loadConfig();

          const sourceChain = selectChain(chains, 'source');
          const targetChain = selectChain(chains, 'target');

          const sourceProvider = new ethers.JsonRpcProvider(sourceChain.rpc);
          const targetProvider = new ethers.JsonRpcProvider(targetChain.rpc);
          const wallet = new ethers.Wallet(process.env.PRIVATE_KEY!, sourceProvider);

          const senderJson = JSON.parse(
            fs.readFileSync(
              path.resolve(
                __dirname,
                '../out/CrossChainSender.sol/CrossChainSender.json'
              ),
              'utf8'
            )
          );

          const abi = senderJson.abi;
          const bytecode = senderJson.bytecode;

          const CrossChainSenderFactory = new ethers.ContractFactory(
            abi,
            bytecode,
            wallet
          );

          try {
            const senderContract = await CrossChainSenderFactory.deploy(
              sourceChain.wormholeRelayer,
              sourceChain.tokenBridge,
              sourceChain.wormhole
            );
            await senderContract.waitForDeployment();

            // Safely access the deployed contract's address
            const senderAddress = (senderContract as ethers.Contract).target;
            console.log(
              `CrossChainSender on ${sourceChain.description}: ${senderAddress}`
            );

            const targetWallet = new ethers.Wallet(
              process.env.PRIVATE_KEY!,
              targetProvider
            );
            const receiverJson = JSON.parse(
              fs.readFileSync(
                path.resolve(
                  __dirname,
                  '../out/CrossChainReceiver.sol/CrossChainReceiver.json'
                ),
                'utf8'
              )
            );
            const CrossChainReceiverFactory = new ethers.ContractFactory(
              receiverJson.abi,
              receiverJson.bytecode,
              targetWallet
            );

            const receiverContract = await CrossChainReceiverFactory.deploy(
              targetChain.wormholeRelayer,
              targetChain.tokenBridge,
              targetChain.wormhole
            );
            await receiverContract.waitForDeployment();

            // Safely access the deployed contract's address
            const receiverAddress = (receiverContract as ethers.Contract).target;
            console.log(
              `CrossChainReceiver on ${targetChain.description}: ${receiverAddress}`
            );

            // Register the sender contract in the receiver contract
            console.log(
              `Registering CrossChainSender (${senderAddress}) as a valid sender in CrossChainReceiver (${receiverAddress})...`
            );

            const CrossChainReceiverContract = new ethers.Contract(
              receiverAddress,
              receiverJson.abi,
              targetWallet
            );

            const tx = await CrossChainReceiverContract.setRegisteredSender(
              sourceChain.chainId,
              ethers.zeroPadValue(senderAddress as BytesLike, 32)
            );

            await tx.wait();
            console.log(
              `CrossChainSender registered as a valid sender on ${targetChain.description}`
            );

            // Load existing deployed contract addresses from contracts.json
            const deployedContractsPath = path.resolve(
              __dirname,
              '../deploy-config/contracts.json'
            );
            let deployedContracts: DeployedContracts = {};

            if (fs.existsSync(deployedContractsPath)) {
              deployedContracts = JSON.parse(
                fs.readFileSync(deployedContractsPath, 'utf8')
              );
            }

            // Update the contracts.json file:
            // If a contract already exists on a chain, update its address; otherwise, add a new entry.
            if (!deployedContracts[sourceChain.chainId]) {
              deployedContracts[sourceChain.chainId] = {
                networkName: sourceChain.description,
                deployedAt: new Date().toISOString(),
              };
            }
            deployedContracts[sourceChain.chainId].CrossChainSender =
              senderAddress.toString();
            deployedContracts[sourceChain.chainId].deployedAt =
              new Date().toISOString();

            if (!deployedContracts[targetChain.chainId]) {
              deployedContracts[targetChain.chainId] = {
                networkName: targetChain.description,
                deployedAt: new Date().toISOString(),
              };
            }
            deployedContracts[targetChain.chainId].CrossChainReceiver =
              receiverAddress.toString();
            deployedContracts[targetChain.chainId].deployedAt =
              new Date().toISOString();

            // Save the updated contracts.json file
            fs.writeFileSync(
              deployedContractsPath,
              JSON.stringify(deployedContracts, null, 2)
            );
          } catch (error: any) {
            if (error.code === 'INSUFFICIENT_FUNDS') {
              console.error(
                'Error: Insufficient funds for deployment. Please make sure your wallet has enough funds to cover the gas fees.'
              );
            } else {
              console.error('An unexpected error occurred:', error.message);
            }
            process.exit(1);
          }
        }

        main().catch((error) => {
          console.error(error);
          process.exit(1);
        });
        ```

5. **Add your private key**: You'll need to provide your private key. It allows your deployment script to sign the transactions that deploy the smart contracts to the blockchain. Without it, the script won't be able to interact with the blockchain on your behalf.

    Create a `.env` file in the root of the project and add your private key:

    ```bash
    touch .env
    ```

    Inside `.env`, add your private key in the following format:

    ```env
    PRIVATE_KEY=INSERT_PRIVATE_KEY
    ```
    
6. **Run the deployment script**:

    1. Open a terminal and run the following command:

        ```bash
        npx ts-node script/deploy.ts
        ```

        This will execute the deployment script, deploying both contracts to the selected chains.

    2. Check the deployment output:

        - You will see the deployed contract addresses printed in the terminal if successful. The `contracts.json` file will be updated with these addresses.
        - If you encounter an error, the script will provide feedback, such as insufficient funds for gas.

If you followed the logic provided in the full code above, your terminal output should look something like this:

<div id="termynal" data-termynal>
	<span data-ty="input"><span class="file-path"></span>npx ts-node deploy.ts</span>
	<span data-ty> > cross-chain-token-transfer@1.0.0 deploy</span>
	<span data-ty> > npx ts-node script/deploy.ts</span>
	<span data-ty> Select the SOURCE chain:</span>
	<span data-ty> 1: Avalanche testnet fuji</span>
  <span data-ty> 2: Base Sepolia</span>
  <span data-ty> </span>
  <span data-ty> Enter the number for the SOURCE chain: 1</span>
  <span data-ty> </span>
  <span data-ty> Select the TARGET chain:</span>
  <span data-ty> 1: Avalanche testnet fuji</span>
  <span data-ty> 2: Base Sepolia</span>
  <span data-ty> </span>
  <span data-ty> Enter the number for the TARGET chain: 2</span>
  <span data-ty> CrossChainSender Avalanche testnet fuji: 0x1Cac52a183D02F9002fdb37b13eC2fAB950d44E3</span>
  <span data-ty> CrossChainReceiver Base Sepolia: 0xD720BFF42a0960cfF1118454A907a44dB358f2b1</span>
  <span data-ty> </span>
  <span data-ty> Registering CrossChainSender (0x1Cac52a183D02F9002fdb37b13eC2fAB950d44E3) as a valid sender in CrossChainReceiver (0xD720BFF42a0960cfF1118454A907a44dB358f2b1)...</span>
  <span data-ty> </span>
  <span data-ty> CrossChainSender registered as a valid sender on Base Sepolia</span>
	<span data-ty="input"><span class="file-path"></span></span>
</div>
## Transfer Tokens Across Chains

### Quick Recap

Up to this point, you've set up a new Solidity project using Foundry, developed two key contracts (`CrossChainSender` and `CrossChainReceiver`), and created a deployment script to deploy these contracts to different blockchain networks. The deployment script also saves the new contract addresses for easy reference. With everything in place, it's time to transfer tokens using the deployed contracts.

In this step, you'll write a script to transfer tokens across chains using the `CrossChainSender` and `CrossChainReceiver` contracts you deployed earlier. This script will interact with the contracts and facilitate the cross-chain token transfer.

### Transfer Script

1. Set up the transfer script:

    1. Create a new file named `transfer.ts` in the `/script` directory:

        ```bash
        touch script/transfer.ts
        ```

    2. Open the file. Start with the necessary imports, interfaces and configurations:

        ```typescript
        import { ethers } from 'ethers';
        import * as fs from 'fs';
        import * as path from 'path';
        import * as dotenv from 'dotenv';
        import readlineSync from 'readline-sync';

        dotenv.config();

        interface ChainConfig {
          description: string;
          chainId: number;
          rpc: string;
          tokenBridge: string;
          wormholeRelayer: string;
          wormhole: string;
        }

        interface DeployedContracts {
          [chainId: number]: {
            networkName: string;
            CrossChainSender?: string;
            CrossChainReceiver?: string;
            deployedAt: string;
          };
        }
        ```

        These imports include the essential libraries for interacting with Ethereum, handling file paths, loading environment variables, and managing user input.

    3. Load configuration and contracts:


        ```typescript
        function loadConfig(): ChainConfig[] {
          const configPath = path.resolve(__dirname, '../deploy-config/config.json');
          return JSON.parse(fs.readFileSync(configPath, 'utf8')).chains;
        }

        function loadDeployedContracts(): DeployedContracts {
          const contractsPath = path.resolve(
            __dirname,
            '../deploy-config/contracts.json'
          );
          if (
            !fs.existsSync(contractsPath) ||
            fs.readFileSync(contractsPath, 'utf8').trim() === ''
          ) {
            console.error(
              'No contracts found. Please deploy contracts first before transferring tokens.'
            );
            process.exit(1);
          }
          return JSON.parse(fs.readFileSync(contractsPath, 'utf8'));
        }
        ```

        These functions load the network and contract details that were saved during deployment.

    4. Allow users to select source and target chains:

        Refer to the deployed contracts and create logic as desired. In our example, we made this process interactive, allowing users to select the source and target chains from all the historically deployed contracts. This interactive approach helps ensure the correct chains are selected for the token transfer.

        ```typescript
        function selectSourceChain(deployedContracts: DeployedContracts): {
          chainId: number;
          networkName: string;
        } {
          const sourceOptions = Object.entries(deployedContracts).filter(
            ([, contracts]) => contracts.CrossChainSender
          );

          if (sourceOptions.length === 0) {
            console.error('No source chains available with CrossChainSender deployed.');
            process.exit(1);
          }

          console.log('\nSelect the source chain:');
          sourceOptions.forEach(([chainId, contracts], index) => {
            console.log(`${index + 1}: ${contracts.networkName}`);
          });

          const selectedIndex =
            readlineSync.questionInt(`\nEnter the number for the source chain: `) - 1;
          return {
            chainId: Number(sourceOptions[selectedIndex][0]),
            networkName: sourceOptions[selectedIndex][1].networkName,
          };
        }

        function selectTargetChain(deployedContracts: DeployedContracts): {
          chainId: number;
          networkName: string;
        } {
          const targetOptions = Object.entries(deployedContracts).filter(
            ([, contracts]) => contracts.CrossChainReceiver
          );

          if (targetOptions.length === 0) {
            console.error(
              'No target chains available with CrossChainReceiver deployed.'
            );
            process.exit(1);
          }

          console.log('\nSelect the target chain:');
          targetOptions.forEach(([chainId, contracts], index) => {
            console.log(`${index + 1}: ${contracts.networkName}`);
          });

          const selectedIndex =
            readlineSync.questionInt(`\nEnter the number for the target chain: `) - 1;
          return {
            chainId: Number(targetOptions[selectedIndex][0]),
            networkName: targetOptions[selectedIndex][1].networkName,
          };
        }
        ```

2. Implement the token transfer logic:

    1. **Create the `main` function**: Add the token transfer logic, including the chain and contract details, wallet and provider for the source chain, and the `CrossChainSender` contract for interaction.
    
        ```typescript
        async function main() {
          const chains = loadConfig();
          const deployedContracts = loadDeployedContracts();

          // Select the source chain (only show chains with CrossChainSender deployed)
          const { chainId: sourceChainId, networkName: sourceNetworkName } =
            selectSourceChain(deployedContracts);
          const sourceChain = chains.find((chain) => chain.chainId === sourceChainId)!;

          // Select the target chain (only show chains with CrossChainReceiver deployed)
          const { chainId: targetChainId, networkName: targetNetworkName } =
            selectTargetChain(deployedContracts);
          const targetChain = chains.find((chain) => chain.chainId === targetChainId)!;

          // Set up providers and wallets
          const sourceProvider = new ethers.JsonRpcProvider(sourceChain.rpc);
          const wallet = new ethers.Wallet(process.env.PRIVATE_KEY!, sourceProvider);

          // Load the ABI from the JSON file (use the compiled ABI from Forge or Hardhat)
          const CrossChainSenderArtifact = JSON.parse(
            fs.readFileSync(
              path.resolve(
                __dirname,
                '../out/CrossChainSender.sol/CrossChainSender.json'
              ),
              'utf8'
            )
          );

          const abi = CrossChainSenderArtifact.abi;

          // Create the contract instance using the full ABI
          const CrossChainSender = new ethers.Contract(
            deployedContracts[sourceChainId].CrossChainSender!,
            abi,
            wallet
          );
        ```

    2. **Ask the user for token transfer details**: You'll now ask the user for the token contract address, the recipient address on the target chain, and the amount of tokens to transfer.

        ```typescript
          const tokenAddress = readlineSync.question(
            'Enter the token contract address: '
          );
          const recipientAddress = readlineSync.question(
            'Enter the recipient address on the target chain: '
          );

          // Get the token contract
          const tokenContractDecimals = new ethers.Contract(
            tokenAddress,
            [
              'function decimals() view returns (uint8)',
              'function approve(address spender, uint256 amount) public returns (bool)',
            ],
            wallet
          );

          // Fetch the token decimals
          const decimals = await tokenContractDecimals.decimals();

          // Get the amount from the user, then parse it according to the token's decimals
          const amount = ethers.parseUnits(
            readlineSync.question('Enter the amount of tokens to transfer: '),
            decimals
          );
        ```

        This section of the script prompts the user for the token contract address and the recipient's address, fetches the token's decimal value, and parses the amount accordingly.

    3. **Initiate the transfer**: Finally, initiate the cross-chain transfer and log the details.

        ```typescript
          const cost = await CrossChainSender.quoteCrossChainDeposit(targetChainId);

          // Approve the CrossChainSender contract to transfer tokens on behalf of the user
          const tokenContract = new ethers.Contract(
            tokenAddress,
            ['function approve(address spender, uint256 amount) public returns (bool)'],
            wallet
          );

          const approveTx = await tokenContract.approve(
            deployedContracts[sourceChainId].CrossChainSender!,
            amount
          );
          await approveTx.wait();
          console.log(`Approved tokens for cross-chain transfer.`);

          // Initiate the cross-chain transfer
          const transferTx = await CrossChainSender.sendCrossChainDeposit(
            targetChainId,
            deployedContracts[targetChainId].CrossChainReceiver!,
            recipientAddress,
            amount,
            tokenAddress,
            { value: cost } // Attach the necessary fee for cross-chain transfer
          );
          await transferTx.wait();
          console.log(
            `Transfer initiated from ${sourceNetworkName} to ${targetNetworkName}. Transaction Hash: ${transferTx.hash}`
          );
        }
        ```

        This part of the script first approves the token transfer, then initiates the cross-chain transfer using the `CrossChainSender` contract, and finally logs the transaction hash for the user to track.

    4. **Finalize the script**: Call the `main` function and handle any errors that may occur during the token transfer process.

        ```typescript
        main().catch((error) => {
          console.error(error);
          process.exit(1);
        });
        ```

You can find the full code for the `transfer.ts` file below:

??? code "transfer.ts"

    ```solidity
    import { ethers } from 'ethers';
    import * as fs from 'fs';
    import * as path from 'path';
    import * as dotenv from 'dotenv';
    import readlineSync from 'readline-sync';

    dotenv.config();

    interface ChainConfig {
      description: string;
      chainId: number;
      rpc: string;
      tokenBridge: string;
      wormholeRelayer: string;
      wormhole: string;
    }

    interface DeployedContracts {
      [chainId: number]: {
        networkName: string;
        CrossChainSender?: string;
        CrossChainReceiver?: string;
        deployedAt: string;
      };
    }

    function loadConfig(): ChainConfig[] {
      const configPath = path.resolve(__dirname, '../deploy-config/config.json');
      return JSON.parse(fs.readFileSync(configPath, 'utf8')).chains;
    }

    function loadDeployedContracts(): DeployedContracts {
      const contractsPath = path.resolve(
        __dirname,
        '../deploy-config/contracts.json'
      );
      if (
        !fs.existsSync(contractsPath) ||
        fs.readFileSync(contractsPath, 'utf8').trim() === ''
      ) {
        console.error(
          'No contracts found. Please deploy contracts first before transferring tokens.'
        );
        process.exit(1);
      }
      return JSON.parse(fs.readFileSync(contractsPath, 'utf8'));
    }

    function selectSourceChain(deployedContracts: DeployedContracts): {
      chainId: number;
      networkName: string;
    } {
      const sourceOptions = Object.entries(deployedContracts).filter(
        ([, contracts]) => contracts.CrossChainSender
      );

      if (sourceOptions.length === 0) {
        console.error('No source chains available with CrossChainSender deployed.');
        process.exit(1);
      }

      console.log('\nSelect the source chain:');
      sourceOptions.forEach(([chainId, contracts], index) => {
        console.log(`${index + 1}: ${contracts.networkName}`);
      });

      const selectedIndex =
        readlineSync.questionInt(`\nEnter the number for the source chain: `) - 1;
      return {
        chainId: Number(sourceOptions[selectedIndex][0]),
        networkName: sourceOptions[selectedIndex][1].networkName,
      };
    }

    function selectTargetChain(deployedContracts: DeployedContracts): {
      chainId: number;
      networkName: string;
    } {
      const targetOptions = Object.entries(deployedContracts).filter(
        ([, contracts]) => contracts.CrossChainReceiver
      );

      if (targetOptions.length === 0) {
        console.error(
          'No target chains available with CrossChainReceiver deployed.'
        );
        process.exit(1);
      }

      console.log('\nSelect the target chain:');
      targetOptions.forEach(([chainId, contracts], index) => {
        console.log(`${index + 1}: ${contracts.networkName}`);
      });

      const selectedIndex =
        readlineSync.questionInt(`\nEnter the number for the target chain: `) - 1;
      return {
        chainId: Number(targetOptions[selectedIndex][0]),
        networkName: targetOptions[selectedIndex][1].networkName,
      };
    }

    async function main() {
      const chains = loadConfig();
      const deployedContracts = loadDeployedContracts();

      // Select the source chain (only show chains with CrossChainSender deployed)
      const { chainId: sourceChainId, networkName: sourceNetworkName } =
        selectSourceChain(deployedContracts);
      const sourceChain = chains.find((chain) => chain.chainId === sourceChainId)!;

      // Select the target chain (only show chains with CrossChainReceiver deployed)
      const { chainId: targetChainId, networkName: targetNetworkName } =
        selectTargetChain(deployedContracts);
      const targetChain = chains.find((chain) => chain.chainId === targetChainId)!;

      // Set up providers and wallets
      const sourceProvider = new ethers.JsonRpcProvider(sourceChain.rpc);
      const wallet = new ethers.Wallet(process.env.PRIVATE_KEY!, sourceProvider);

      // Load the ABI from the JSON file (use the compiled ABI from Forge or Hardhat)
      const CrossChainSenderArtifact = JSON.parse(
        fs.readFileSync(
          path.resolve(
            __dirname,
            '../out/CrossChainSender.sol/CrossChainSender.json'
          ),
          'utf8'
        )
      );

      const abi = CrossChainSenderArtifact.abi;

      // Create the contract instance using the full ABI
      const CrossChainSender = new ethers.Contract(
        deployedContracts[sourceChainId].CrossChainSender!,
        abi,
        wallet
      );

      // Display the selected chains
      console.log(
        `\nInitiating transfer from ${sourceNetworkName} to ${targetNetworkName}.`
      );

      // Ask the user for token transfer details
      const tokenAddress = readlineSync.question(
        'Enter the token contract address: '
      );
      const recipientAddress = readlineSync.question(
        'Enter the recipient address on the target chain: '
      );

      // Get the token contract
      const tokenContractDecimals = new ethers.Contract(
        tokenAddress,
        [
          'function decimals() view returns (uint8)',
          'function approve(address spender, uint256 amount) public returns (bool)',
        ],
        wallet
      );

      // Fetch the token decimals
      const decimals = await tokenContractDecimals.decimals();

      // Get the amount from the user, then parse it according to the token's decimals
      const amount = ethers.parseUnits(
        readlineSync.question('Enter the amount of tokens to transfer: '),
        decimals
      );

      // Calculate the cross-chain transfer cost
      const cost = await CrossChainSender.quoteCrossChainDeposit(targetChainId);

      // Approve the CrossChainSender contract to transfer tokens on behalf of the user
      const tokenContract = new ethers.Contract(
        tokenAddress,
        ['function approve(address spender, uint256 amount) public returns (bool)'],
        wallet
      );

      const approveTx = await tokenContract.approve(
        deployedContracts[sourceChainId].CrossChainSender!,
        amount
      );
      await approveTx.wait();
      console.log(`Approved tokens for cross-chain transfer.`);

      // Initiate the cross-chain transfer
      const transferTx = await CrossChainSender.sendCrossChainDeposit(
        targetChainId,
        deployedContracts[targetChainId].CrossChainReceiver!,
        recipientAddress,
        amount,
        tokenAddress,
        { value: cost } // Attach the necessary fee for cross-chain transfer
      );
      await transferTx.wait();
      console.log(
        `Transfer initiated from ${sourceNetworkName} to ${targetNetworkName}. Transaction Hash: ${transferTx.hash}`
      );
    }

    main().catch((error) => {
      console.error(error);
      process.exit(1);
    });
    ```

### Transfer Tokens

Now that your transfer script is ready, it’s time to execute it and perform a cross-chain token transfer.

1. **Run the transfer script**: Open your terminal and run the transfer script.

    ```bash
    npx ts-node script/transfer.ts
    ```

    This command will start the script, prompting you to select the source and target chains, input the token address, recipient address, and the amount of tokens to transfer.

2. **Follow the prompts**: The script will guide you through selecting the source and target chains and entering the necessary details for the token transfer. Once you provide all the required information, the script will initiate the token transfer.

3. **Verify the transaction**: After running the script, you should see a confirmation message with the transaction hash. You can use this transaction hash to check the transfer status on the respective blockchain explorers.

You can verify the transaction on the [Wormhole Explorer](https://wormholescan.io/){target=\_blank} using the link provided in the terminal output. This explorer also offers the option to add the transferred token to your MetaMask wallet automatically.

If you followed the logic provided in the `transfer.ts` file above, your terminal output should look something like this:

<div id="termynal" data-termynal>
	<span data-ty="input"><span class="file-path"></span>npx ts-node transfer.ts</span>
	<span data-ty> > cross-chain-token-transfer@1.0.0 transfer</span>
	<span data-ty> > npx ts-node script/transfer.ts</span>
  <span data-ty> </span>
	<span data-ty> Select the source chain:</span>
	<span data-ty> 1: Avalanche testnet fuji</span>
  <span data-ty> 2: Base Sepolia</span>
  <span data-ty> </span>
  <span data-ty> Enter the number for the SOURCE chain: 1</span>
  <span data-ty> </span>
  <span data-ty> Select the target chain:</span>
  <span data-ty> 1: Avalanche testnet fuji</span>
  <span data-ty> 2: Base Sepolia</span>
  <span data-ty> </span>
  <span data-ty> Enter the number for the TARGET chain: 2</span>
  <span data-ty> </span>
  <span data-ty> Initiating transfer from Avalanche testnet fuji to Base Sepolia</span>
  <span data-ty> Enter the token contract address: 0x5425890298aed601595a70ab815c96711a31bc65</span>
  <span data-ty> Enter the recipient address on the target chain: INSERT_YOUR_WALLET_ADDRESS</span>
  <span data-ty> Enter the amount of tokens to transfer: 2</span>
  <span data-ty> Approved tokens for cross-chain transfer.</span>
  <span data-ty> Transfer initiated from Avalanche testnet fuji to Base Sepolia. Transaction Hash: 0x4a923975d955c1f226a1c2f61a1a0fa1ab1a9e229dc29ceaeadf8ef40acd071f</span>
	<span data-ty="input"><span class="file-path"></span></span>
</div>
!!! note
    In this example, we demonstrated a token transfer from the Avalanche Fuji Testnet to the Base Sepolia Testnet. We sent two units of USDC Testnet tokens using the token contract address `0x5425890298aed601595a70ab815c96711a31bc65`. You can replace these details with those relevant to your project or use the same for testing purposes.

## Resources

If you'd like to explore the complete project or need a reference while following this tutorial, you can find the complete codebase in the [Cross-Chain Token Transfers GitHub repository](https://github.com/wormhole-foundation/demo-cross-chain-token-transfer){target=\_blank}. The repository includes all the scripts, contracts, and configurations needed to deploy and transfer tokens across chains using the Wormhole protocol.

## Conclusion

Congratulations! You've successfully built and deployed a cross-chain token transfer system using Solidity and the Wormhole protocol. You've learned how to:

 - Set up a new Solidity project using Foundry.
 - Develop smart contracts to send and receive tokens across chains.
 - Write deployment scripts to manage and deploy contracts on different networks.

Looking for more? Check out the [Wormhole Tutorial Demo repository](https://github.com/wormhole-foundation/demo-tutorials){target=\_blank} for additional examples.


---

Page Title: Delegated Guardian Set

- Resolved Markdown: https://wormhole.com/docs/ai/pages/products-reference-delegated-guardian-set.md
- Canonical (HTML): https://wormhole.com/docs/products/reference/delegated-guardian-set/
- Summary: This page documents the chains for which a delegated guardian set is configured, where a subset of Guardians observes events on behalf of the full Guardian Set.
- Word Count: 249; Token Estimate: 502

# Delegated Guardian Set

For certain chains, the full set of 19 Guardian nodes is not required to each maintain full-node infrastructure. Instead, a **delegated guardian set** is configured — a configurable subset of Guardians designated to observe events on specific chains. The remaining Canonical Guardians rely on attested observations gossiped by Delegated Guardians to participate in VAA signing. See [the Delegated Guardian Sets whitepaper](https://github.com/wormhole-foundation/wormhole/blob/main/whitepapers/0017_delegated_guardian_sets.md) for the full specification.

The following table lists which chains use a delegated guardian set and the guardian set they are delegated to.

| Chain ID | Name       | Quorum | GS Size |
|----------|------------|--------|---------|
| 4        | BSC        | 5 /7   | 7       |
| 5        | Polygon    | 5 /7   | 7       |
| 6        | Avalanche  | 5 /7   | 7       |
| 8        | Algorand   | 5 /7   | 7       |
| 13       | Klaytn     | 5 /7   | 7       |
| 14       | Celo       | 5 /7   | 7       |
| 15       | Near       | 5 /7   | 7       |
| 16       | Moonbeam   | 5 /7   | 7       |
| 19       | Injective  | 5 /7   | 7       |
| 21       | Sui        | 5 /7   | 7       |
| 22       | Aptos      | 5 /7   | 7       |
| 23       | Arbitrum   | 5 /7   | 7       |
| 32       | Sei        | 5 /7   | 7       |
| 38       | Linea      | 5 /7   | 7       |
| 39       | Berachain  | 5 /7   | 7       |
| 40       | SeiEVM     | 5 /7   | 7       |
| 44       | Unichain   | 5 /7   | 7       |
| 45       | Worldchain | 5 /7   | 7       |
| 47       | HyperEVM   | 5 /7   | 7       |
| 48       | Monad      | 5 /7   | 7       |
| 50       | Mezo       | 5 /7   | 7       |
| 51       | Fogo       | 5 /7   | 7       |
| 55       | Plume      | 5 /7   | 7       |
| 57       | XRPLEVM    | 5 /7   | 7       |
| 59       | CreditCoin | 5 /7   | 7       |
| 63       | Moca       | 5 /7   | 7       |
| 64       | MegaETH    | 5 /7   | 7       |
| 67       | ZeroGravity| 5 /7   | 7       |
| 69       | Nexus      | 5 /7   | 7       |


---

Page Title: Ecosystem

- Resolved Markdown: https://wormhole.com/docs/ai/pages/protocol-ecosystem.md
- Canonical (HTML): https://wormhole.com/docs/protocol/ecosystem/
- Summary: Explore Wormhole's modular ecosystem of cross-chain tools for messaging, bridging, governance, and developer integration.
- Word Count: 564; Token Estimate: 909

# The Wormhole Ecosystem

[Wormhole](/docs/protocol/introduction/){target=\_blank} is a cross-chain messaging protocol connecting decentralized applications across multiple blockchains. It offers a suite of interoperability tools, each addressing different multichain challenges, and allows developers to mix and match these products as needed.

Whether you’re looking for a simple UI-based bridging experience, a native token transfer flow without wrapped assets, real-time cross-chain data queries, or an advanced settlement layer for complex asset movements, Wormhole has a product designed for that purpose. Every solution integrates with Wormhole’s core messaging network, ensuring each module can operate independently or in combination with others.

This page will guide you through the structural layout of these tools—how they fit together, can be used independently, and can be layered to build robust, multichain applications.

## Ecosystem Overview

The diagram shows a high-level view of Wormhole’s modular stack, illustrating how different tools are grouped into four layers:

- **Application and user-facing products**: The top layer includes user-centric solutions such as [Connect](/docs/products/connect/overview/){target=\_blank} (a simple bridging interface).
- **Asset and data transfer layer**: Below it sits the core bridging and data solutions—[NTT](/docs/products/token-transfers/native-token-transfers/overview/){target=\_blank}, [WTT](/docs/products/token-transfers/wrapped-token-transfers/overview/){target=\_blank}, [Queries](/docs/products/queries/overview/){target=\_blank}, [Settlement](/docs/products/settlement/overview/){target=\_blank}, and [MultiGov](/docs/products/multigov/overview/){target=\_blank}—that handle the movement of tokens, real-time data fetching, advanced cross-chain settlements, and cross-chain governance.
- **Integration layer**: The [TypeScript SDK](/docs/tools/typescript-sdk/get-started/){target=\_blank} and [WormholeScan API](https://wormholescan.io/#/){target=\_blank} provide developer-friendly libraries and APIs to integrate cross-chain capabilities into applications.
- **Foundation layer**: At the base, the [Wormhole messaging](/docs/products/messaging/overview/){target=\_blank} system and the [core contracts](/docs/protocol/infrastructure/core-contracts/){target=\_blank} secure the entire network, providing essential verification and cross-chain message delivery.

![Wormhole ecosystem diagram](/docs/images/protocol/ecosystem/ecosystem-1.webp)

## Bringing It All Together: Interoperability in Action

Wormhole’s modularity makes it easy to adopt just the pieces you need. If you want to quickly add bridging to a dApp, use Connect at the top layer while relying on the Foundation Layer behind the scenes. Or if your app needs to send raw messages between chains, integrate the Messaging layer directly via the Integration Layer (TypeScript or Solidity SDK). You can even layer on additional features—like real-time data calls from Queries or more flexible bridging flows with Native Token Transfers.

Ultimately, these components aren’t siloed but designed to be combined. You could, for instance, fetch a balance from one chain using Queries and then perform an on-chain swap on another chain using Settlement. Regardless of your approach, each Wormhole product is powered by the same Guardian-secured messaging backbone, ensuring all cross-chain interactions remain reliable and secure.

## Next Steps

<div class="grid cards" markdown>

-   :octicons-book-16:{ .lg .middle } **Visit the Product Comparison**

    ---

    Unsure which bridging solution you need? Match your requirements with the right Wormhole tool.

    [:custom-arrow: Compare Products](/docs/products/overview/)

-   :octicons-tools-16:{ .lg .middle } **Wormhole Dev Arena**

    ---

    A structured learning hub with hands-on tutorials across the Wormhole ecosystem.

    [:custom-arrow: Explore the Dev Arena](https://arena.wormhole.com/ecosystem){target=\_blank}

</div>


---

Page Title: Executor Addresses

- Resolved Markdown: https://wormhole.com/docs/ai/pages/products-messaging-reference-executor-addresses.md
- Canonical (HTML): https://wormhole.com/docs/products/messaging/reference/executor-addresses/
- Summary: Reference list of deployed Executor contract addresses across integrations, including CCTP, NTT, WTT, and referrer variants.
- Word Count: 2682; Token Estimate: 7713

# Executor Addresses

## Executor



=== "Mainnet"

    <table data-full-width="true" markdown><thead><th>Chain Name</th><th>Contract Address</th></thead><tbody><tr><td>Ethereum</td><td><code>0x84EEe8dBa37C36947397E1E11251cA9A06Fc6F8a</code></td></tr><tr><td>Solana</td><td><code>execXUrAsMnqMmTHj5m7N1YQgsDz3cwGLYCYyuDRciV</code></td></tr><tr><td>0G (Zero Gravity)</td><td><code>0xcD2BffD0C0289e8C0cb89c458dB1B74f1892Fa6c</code></td></tr><tr><td>Aptos</td><td><code>0x11aa75c059e1a7855be66b931bf340a2e0973274ac16b5f519c02ceafaf08a18</code></td></tr><tr><td>Arbitrum</td><td><code>0x3980f8318fc03d79033Bbb421A622CDF8d2Eeab4</code></td></tr><tr><td>Avalanche</td><td><code>0x4661F0E629E4ba8D04Ee90080Aee079740B00381</code></td></tr><tr><td>Base</td><td><code>0x9E1936E91A4a5AE5A5F75fFc472D6cb8e93597ea</code></td></tr><tr><td>Berachain</td><td><code>0x0Dd7a5a32311b8D87A615Cc7f079B632D3d5e2D3</code></td></tr><tr><td>BNB Smart Chain</td><td><code>0xeC8cCCD058DbF28e5D002869Aa9aFa3992bf4ee0</code></td></tr><tr><td>Celo</td><td><code>0xe6Ea5087c6860B94Cf098a403506262D8F28cF05</code></td></tr><tr><td>CreditCoin</td><td><code>0xd2e420188f17607Aa6344ee19c3e76Cf86CA7BDe</code></td></tr><tr><td>Fogo</td><td><code>execXUrAsMnqMmTHj5m7N1YQgsDz3cwGLYCYyuDRciV</code></td></tr><tr><td>HyperEVM :material-alert:{ title='⚠️ The HyperEVM integration is experimental, as its node software is not open source. Use Wormhole messaging on HyperEVM with caution.' }</td><td><code>0xd7717899cc4381033Bc200431286D0AC14265F78</code></td></tr><tr><td>Ink</td><td><code>0x3e44a5F45cbD400acBEF534F51e616043B211Ddd</code></td></tr><tr><td>Linea</td><td><code>0x23aF2B5296122544A9A7861da43405D5B15a9bD3</code></td></tr><tr><td>MegaETH</td><td><code>0xD405E0A1f3f9edc25Ea32d0B079d6118328b2EcB</code></td></tr><tr><td>Mezo</td><td><code>0x0f9b8E144Cc5C5e7C0073829Afd30F26A50c5606</code></td></tr><tr><td>Moca</td><td><code>0x7b8097af5459846c5A72fCc960D94F31C05915aD</code></td></tr><tr><td>Monad</td><td><code>0xC04dE634982cAdF2A677310b73630B7Ac56A3f65</code></td></tr><tr><td>Moonbeam</td><td><code>0x85D06449C78064c2E02d787e9DC71716786F8D19</code></td></tr><tr><td>Optimism</td><td><code>0x85B704501f6AE718205C0636260768C4e72ac3e7</code></td></tr><tr><td>Polygon</td><td><code>0x0B23efA164aB3eD08e9a39AC7aD930Ff4F5A5e81</code></td></tr><tr><td>Scroll</td><td><code>0xcFAdDE24640e395F5A71456A825D0D7C3741F075</code></td></tr><tr><td>SeiEVM</td><td><code>0x25f1c923fb7a5aefa5f0a2b419fc70f2368e66e5</code></td></tr><tr><td>Sonic</td><td><code>0x3Fdc36b4260Da38fBDba1125cCBD33DD0AC74812</code></td></tr><tr><td>Sui</td><td><code>0xdb0fe8bb1e2b5be628adbea0636063325073e1070ee11e4281457dfd7f158235</code></td></tr><tr><td>Unichain</td><td><code>0x764dD868eAdD27ce57BCB801E4ca4a193d231Aed</code></td></tr><tr><td>World Chain</td><td><code>0x8689b4E6226AdC8fa8FF80aCc3a60AcE31e8804B</code></td></tr><tr><td>XRPL-EVM</td><td><code>0x8345E90Dcd92f5Cf2FAb0C8E2A56A5bc2c30d896</code></td></tr></tbody></table>

=== "Testnet"

    <table data-full-width="true" markdown><thead><th>Chain Name</th><th>Contract Address</th></thead><tbody><tr><td>Ethereum Sepolia</td><td><code>0xD0fb39f5a3361F21457653cB70F9D0C9bD86B66B</code></td></tr><tr><td>Solana</td><td><code>execXUrAsMnqMmTHj5m7N1YQgsDz3cwGLYCYyuDRciV</code></td></tr><tr><td>0G (Zero Gravity)</td><td><code>0x7C43825EeB76DF7aAf3e1D2e8f684d4876F0CC05</code></td></tr><tr><td>Aptos</td><td><code>0x139717c339f08af674be77143507a905aa28cbc67a0e53e7095c07b630d73815</code></td></tr><tr><td>Arbitrum Sepolia</td><td><code>0xBF161de6B819c8af8f2230Bcd99a9B3592f6F87b</code></td></tr><tr><td>Avalanche</td><td><code>0x4661F0E629E4ba8D04Ee90080Aee079740B00381</code></td></tr><tr><td>Base Sepolia</td><td><code>0x51B47D493CBA7aB97e3F8F163D6Ce07592CE4482</code></td></tr><tr><td>BNB Smart Chain</td><td><code>0xeC8cCCD058DbF28e5D002869Aa9aFa3992bf4ee0</code></td></tr><tr><td>Converge</td><td><code>0xAab9935349B9c08e0e970720F6D640d5B91C293E</code></td></tr><tr><td>Fogo</td><td><code>execXUrAsMnqMmTHj5m7N1YQgsDz3cwGLYCYyuDRciV</code></td></tr><tr><td>Linea</td><td><code>0x4f6c3a93a80DdC691312974DAAbf9B6e4Bb44111</code></td></tr><tr><td>Mezo</td><td><code>0x0f9b8E144Cc5C5e7C0073829Afd30F26A50c5606</code></td></tr><tr><td>Moca</td><td><code>0xc4a03f2c47caA4b961101bAD6338DEf37376F052</code></td></tr><tr><td>Monad Testnet</td><td><code>0xe37D3E162B4B1F17131E4e0e6122DbA31243382f</code></td></tr><tr><td>Optimism Sepolia</td><td><code>0x5856651eB82aeb6979B4954317194d48e1891b3c</code></td></tr><tr><td>Plume</td><td><code>0x8fc2FbA8F962fbE89a9B02f03557a011c335A455</code></td></tr><tr><td>Polygon Amoy</td><td><code>0x7056721C33De437f0997F67BC87521cA86b721d3</code></td></tr><tr><td>SeiEVM</td><td><code>0x25f1c923Fb7A5aEFA5F0A2b419fC70f2368e66e5</code></td></tr><tr><td>Sui</td><td><code>0x4000cfe2955d8355b3d3cf186f854fea9f787a457257056926fde1ec977670eb</code></td></tr><tr><td>Unichain</td><td><code>0x764dD868eAdD27ce57BCB801E4ca4a193d231Aed</code></td></tr><tr><td>XRPL-EVM</td><td><code>0x4d9525D94D275dEB495b7C8840b154Ae04cfaC2A</code></td></tr></tbody></table>

## CCTP with Executor



=== "Mainnet v1"

    <table data-full-width="true" markdown><thead><th>Chain Name</th><th>Contract Address</th></thead><tbody><tr><td>Ethereum</td><td><code>0x6DDE92942DbB24F7c9B75765b74a33446980C1e3</code></td></tr><tr><td>Solana</td><td><code>CXGRA5SCc8jxDbaQPZrmmZNu2JV34DP7gFW4m31uC1zs</code></td></tr><tr><td>Aptos</td><td><code>0xc89bf3746dfc70bb3f2de7c35a98f327a40b9d55a443743a5935c5e3de90b7ac</code></td></tr><tr><td>Arbitrum</td><td><code>0x772373214238F09a494828A5323574E3d7e27558</code></td></tr><tr><td>Avalanche</td><td><code>0x58aC806cd205083E7E048E196f36Ff6C4Ae17bE5</code></td></tr><tr><td>Base</td><td><code>0x4D1Cc8921e297155044C01761f581fa52a24C33d</code></td></tr><tr><td>Optimism</td><td><code>0x6826c075973a4393CEf0e131c4B16869426563a7</code></td></tr><tr><td>Polygon</td><td><code>0x7e6Ae241101B355447A4B471D0C6968b132eC4Ab</code></td></tr><tr><td>Sui</td><td><code>N/A*</code></td></tr><tr><td>Unichain</td><td><code>0xa997Ef229E4D2a1fEca249eB41fBf5D4b2217d6E</code></td></tr></tbody></table>

=== "Testnet v1"

    <table data-full-width="true" markdown><thead><th>Chain Name</th><th>Contract Address</th></thead><tbody><tr><td>Ethereum Sepolia</td><td><code>0x2fcc7b2332d924764f17f1cf5eda1cd4b36751a2</code></td></tr><tr><td>Solana</td><td><code>CXGRA5SCc8jxDbaQPZrmmZNu2JV34DP7gFW4m31uC1zs</code></td></tr><tr><td>Aptos</td><td><code>0x14a12d1fd6ef371b70c2113155534ec152ec7f779e281b54866c796c9a4a58d3</code></td></tr><tr><td>Arbitrum Sepolia</td><td><code>0x8158305d331594f3e8d18c33ca4e6d3cdc109b75</code></td></tr><tr><td>Avalanche</td><td><code>0x62819ab61cc7fcc864af7bcfc92e6c1965eb69a6</code></td></tr><tr><td>Base Sepolia</td><td><code>0x96846c31e4f87c0f186a322926c61d4183439f0a</code></td></tr><tr><td>Optimism Sepolia</td><td><code>0xe17de8e29f1f0941b541b053829af74ac81c89a6</code></td></tr><tr><td>Polygon</td><td><code>0xdce63172e9ad15243c97acafd01cc4fdda98bead</code></td></tr><tr><td>Unichain Sepolia</td><td><code>0x2c1354296a11029056e0d7d7abbdd58743dbaf59</code></td></tr></tbody></table>

=== "Mainnet v2"

    <table data-full-width="true" markdown><thead><th>Chain Name</th><th>Contract Address</th></thead><tbody><tr><td>Ethereum</td><td><code>0xDD68aBa3E04CB1a05082402B9325753314803005</code></td></tr><tr><td>Solana</td><td><code>Supported</code></td></tr><tr><td>Arbitrum</td><td><code>0x760feC4425B46E3D8FEf8E2CE49786e5a6f74446</code></td></tr><tr><td>Avalanche</td><td><code>0xE42aE9e352157fcEf74E971F2C5c74A5963a71D7</code></td></tr><tr><td>Base</td><td><code>0x52892976559fB2fc8b7f850440eD9AA5Dc26f7D9</code></td></tr><tr><td>Codex</td><td><code>0x0684286448140F75d4C3D2F2c02BF66f98CdEA51</code></td></tr><tr><td>HyperEVM :material-alert:{ title='⚠️ The HyperEVM integration is experimental, as its node software is not open source. Use Wormhole messaging on HyperEVM with caution.' }</td><td><code>0x001319beBA062d918d7007E4D2D76a0A9cc439Db</code></td></tr><tr><td>Ink</td><td><code>0xef0B43b49315A4aDF11bA2617Be81a304c5D6ecc</code></td></tr><tr><td>Linea</td><td><code>0x257dBB6AD7C7AC19360bEe1A107ebE631D568776</code></td></tr><tr><td>Monad</td><td><code>0x1FdCCf65318b34CFd3F5903fFb747C17e76330ac</code></td></tr><tr><td>Optimism</td><td><code>0x9b51579e67D4ab18D79609105509ad37B2a0D342</code></td></tr><tr><td>Plume</td><td><code>0x9be9C6B420eAfaaC1162D680fd7E61446b38Cf29</code></td></tr><tr><td>Polygon</td><td><code>0x5116F1358ae2445f571AA702dA1feB5e13094E59</code></td></tr><tr><td>SeiEVM</td><td><code>0xe067C0D378C50CDc34bCd973F202736D5A19e5D2</code></td></tr><tr><td>Sonic</td><td><code>0x8A850b2077F1eFccA89eAa9c35b45C4dC9227cdb</code></td></tr><tr><td>Sui</td><td><code>N/A*</code></td></tr><tr><td>Unichain</td><td><code>0xaf7f4FbB6C220baf57ABC7babF81D47Fd628bdb4</code></td></tr><tr><td>World Chain</td><td><code>0xAA4841e5d9652593852403E3ce9e8003f8D579D0</code></td></tr></tbody></table>

=== "Testnet v2"

    <table data-full-width="true" markdown><thead><th>Chain Name</th><th>Contract Address</th></thead><tbody><tr><td>Ethereum Sepolia</td><td><code>0xc58475c97ebde9cf4fefa0d4fb2774df81905d43</code></td></tr><tr><td>Solana</td><td><code>Supported</code></td></tr><tr><td>Arbitrum Sepolia</td><td><code>0xf601f9988d62943cb842baae1e46be9b17d0b2a4</code></td></tr><tr><td>Avalanche</td><td><code>0x10018394905f70daa1d740040d64cbed5a82301e</code></td></tr><tr><td>Base Sepolia</td><td><code>0x1effdcfedc6d45e44b3133257debfb522adb1cae</code></td></tr><tr><td>Ink</td><td><code>0x63993ee08bda32ecb0ba5cdc751b404f5c5c0458</code></td></tr><tr><td>Linea Sepolia</td><td><code>0xe8Ad216e23fc9425E65aB315F0EC13737e75afEF</code></td></tr><tr><td>Monad Testnet</td><td><code>0x358bAd031d7A217ebA2d471cad5fD611AeC2aF17</code></td></tr><tr><td>Optimism Sepolia</td><td><code>0x49f386393c26439b74e62f5794062925dfb7c1db</code></td></tr><tr><td>Polygon</td><td><code>0x05da7c69db265b37b4d3530d476ec4b33bd9dd45</code></td></tr><tr><td>SeiEVM</td><td><code>0xDC735908C3eCF29f40D8CA5f6407F2d94d316a9F</code></td></tr><tr><td>Unichain Sepolia</td><td><code>0xf082af7668f000f60bc519b378f6363708fc302b</code></td></tr></tbody></table>

## NTT with Executor



=== "Mainnet"

    <table data-full-width="true" markdown><thead><th>Chain Name</th><th>Contract Address</th></thead><tbody><tr><td>Ethereum</td><td><code>0xD2D9c936165a85F27a5a7e07aFb974D022B89463</code><br>Multi Ntt: <code>0x03dB430D830601DB368991eE55DAa9A708df7912</code></td></tr><tr><td>Solana</td><td><code>nex1gkSWtRBheEJuQZMqHhbMG5A45qPU76KqnCZNVHR</code></td></tr><tr><td>0G</td><td><code>0xe175a8b838f3cdb2e1aaf4ff74c05cf2f3aea9a8</code></td></tr><tr><td>Arbitrum</td><td><code>0x0Af42A597b0C201D4dcf450DcD0c06d55ddC1C77</code></td></tr><tr><td>Avalanche</td><td><code>0x4e9Af03fbf1aa2b79A2D4babD3e22e09f18Bb8EE</code></td></tr><tr><td>Base</td><td><code>0x83216747fC21b86173D800E2960c0D5395de0F30</code></td></tr><tr><td>Berachain</td><td><code>0x0a2AF374Cc9CCCbB0Acc4E34B20b9d02a0f08c30</code></td></tr><tr><td>BNB Smart Chain</td><td><code>0x39B57Dd9908F8be02CfeE283b67eA1303Bc29fe1</code></td></tr><tr><td>Celo</td><td><code>0x3d69869fcB9e1CD1F4020b637fb8256030BAc8fC</code></td></tr><tr><td>CreditCoin</td><td><code>0x5454b995719626256C96fb57454b044ffb3Da2F9</code></td></tr><tr><td>Fogo</td><td><code>nex1gkSWtRBheEJuQZMqHhbMG5A45qPU76KqnCZNVHR</code></td></tr><tr><td>HyperEVM :material-alert:{ title='⚠️ The HyperEVM integration is experimental, as its node software is not open source. Use Wormhole messaging on HyperEVM with caution.' }</td><td><code>0x431017B1718b86898C7590fFcCC380DEf0456393</code></td></tr><tr><td>Ink</td><td><code>0x420370DC2ECC4D44b47514B7859fd11809BbeFF5</code></td></tr><tr><td>Linea</td><td><code>0xEAa5AddB5b8939Eb73F7faF46e193EefECaF13E9</code></td></tr><tr><td>MegaETH</td><td><code>0x3EFEc0c7Ee79135330DD03e995872f84b1AD49b6</code></td></tr><tr><td>Mezo</td><td><code>0x484b5593BbB90383f94FB299470F09427cf6cfE2</code></td></tr><tr><td>Moca</td><td><code>0xE612837749a0690BA2BCe490D6eFb5F8Fc347df3</code></td></tr><tr><td>Monad</td><td><code>0xc3F3dDa544815a440633176c7598f5B97500793e</code><br>Multi Ntt: <code>0xFEA937F7124E19124671f1685671d3f04a9Af4E4</code></td></tr><tr><td>Moonbeam</td><td><code>0x1365593C8bae71a55e48E105a2Bb76d5928c7DE3</code></td></tr><tr><td>Optimism</td><td><code>0x85C0129bE5226C9F0Cf4e419D2fefc1c3FCa25cF</code></td></tr><tr><td>Plume</td><td><code>0x6Eb53371f646788De6B4D0225a4Ed1d9267188AD</code></td></tr><tr><td>Polygon</td><td><code>0x6762157b73941e36cEd0AEf54614DdE545d0F990</code></td></tr><tr><td>Scroll</td><td><code>0x055625d48968f99409244E8c3e03FbE73B235a62</code></td></tr><tr><td>SeiEVM</td><td><code>0x3F2D6441C7a59Dfe80f8e14142F9E28F6D440445</code></td></tr><tr><td>Sonic</td><td><code>0xaCa00703bb87F31D6F9fCcc963548b48FA46DfeB</code></td></tr><tr><td>Sui</td><td><code>N/A*</code></td></tr><tr><td>Unichain</td><td><code>0x607723D6353Dae3ef62B7B277Cfabd0F4bc6CB4C</code></td></tr><tr><td>World Chain</td><td><code>0x66b1644400D51e104272337226De3EF1A820eC79</code></td></tr><tr><td>XRPL-EVM</td><td><code>0x6bBd1ff3bB303F88835A714EE3241bF45DE26d29</code></td></tr></tbody></table>

=== "Testnet"

    <table data-full-width="true" markdown><thead><th>Chain Name</th><th>Contract Address</th></thead><tbody><tr><td>Ethereum Sepolia</td><td><code>0x54DD7080aE169DD923fE56d0C4f814a0a17B8f41</code></td></tr><tr><td>Solana</td><td><code>nex1gkSWtRBheEJuQZMqHhbMG5A45qPU76KqnCZNVHR</code></td></tr><tr><td>0G Galileo</td><td><code>0xA8CA118f4C8d44Ab651Dad52B5E1a212e5d5c55b</code></td></tr><tr><td>Arbitrum Sepolia</td><td><code>0xd048170F1ECB8D47E499D3459aC379DA023E2C1B</code></td></tr><tr><td>Avalanche</td><td><code>0x4e9Af03fbf1aa2b79A2D4babD3e22e09f18Bb8EE</code></td></tr><tr><td>Base Sepolia</td><td><code>0x5845E08d890E21687F7Ebf7CbAbD360cD91c6245</code></td></tr><tr><td>BNB Smart Chain</td><td><code>0x39B57Dd9908F8be02CfeE283b67eA1303Bc29fe1</code></td></tr><tr><td>Celo</td><td><code>0x3d69869fcB9e1CD1F4020b637fb8256030BAc8fC</code></td></tr><tr><td>Converge</td><td><code>0x3d8c26b67BDf630FBB44F09266aFA735F1129197</code></td></tr><tr><td>Fogo</td><td><code>nex1gkSWtRBheEJuQZMqHhbMG5A45qPU76KqnCZNVHR</code></td></tr><tr><td>Ink</td><td><code>0xF420BFFf922D11c2bBF587C9dF71b83651fAf8Bc</code></td></tr><tr><td>Linea Sepolia</td><td><code>0xaA469cb84C91D5a63bf4B370dE35f0831F2CE4FF</code></td></tr><tr><td>Mezo</td><td><code>0x484b5593BbB90383f94FB299470F09427cf6cfE2</code></td></tr><tr><td>Moca</td><td><code>0x47f26bF9253Eb398fBAf825D7565FE975D839a71</code></td></tr><tr><td>Monad Testnet</td><td><code>0xc8F014FE6a8521259D9ADDc2170bA9e59305D306</code></td></tr><tr><td>Optimism Sepolia</td><td><code>0xaDB1C56D363FF5A75260c3bd27dd7C1fC8421EF5</code></td></tr><tr><td>Plume</td><td><code>0x6Eb53371f646788De6B4D0225a4Ed1d9267188AD</code></td></tr><tr><td>Polygon</td><td><code>0x2982B9566E912458fE711FB1Fd78158264596937</code></td></tr><tr><td>SeiEVM</td><td><code>0x3F2D6441C7a59Dfe80f8e14142F9E28F6D440445</code></td></tr><tr><td>Unichain Sepolia</td><td><code>0x607723D6353Dae3ef62B7B277Cfabd0F4bc6CB4C</code></td></tr><tr><td>XRPL EVM Testnet</td><td><code>0xcDD9d7C759b29680f7a516d0058de8293b2AC7b1</code></td></tr></tbody></table>

## WTT Executor



=== "Mainnet"

    <table data-full-width="true" markdown><thead><th>Chain Name</th><th>Contract Address</th></thead><tbody><tr><td>Ethereum</td><td><code>0xa8969F3f8D97b3Ed89D4e2EC19B6B0CfD504b212</code></td></tr><tr><td>Solana</td><td><code>tbr7Qje6qBzPwfM52csL5KFi8ps5c5vDyiVVBLYVdRf</code></td></tr><tr><td>0G (Zero Gravity)</td><td><code>0x3dBb4dCf25dBA8F0C2417E1c34e527De0E465ecc</code></td></tr><tr><td>Arbitrum</td><td><code>0x04C98824a64d75CD1E9Bc418088b4c9A99048153</code></td></tr><tr><td>Avalanche</td><td><code>0x8849F05675E034b54506caB84450c8C82694a786</code></td></tr><tr><td>Base</td><td><code>0xD8B736EF27Fc997b1d00F22FE37A58145D3BDA07</code></td></tr><tr><td>Berachain</td><td><code>0xFAeFa20CB3759AEd2310E25015F05d62D8567A3F</code></td></tr><tr><td>BNB Smart Chain</td><td><code>0x2513515340fF71DD5AF02fC1BdB9615704d91524</code></td></tr><tr><td>Celo</td><td><code>0xe478DEe705BEae591395B08934FA19F54df316BE</code></td></tr><tr><td>Fantom</td><td><code>0xcafd2f0a35a4459fa40c0517e17e6fa2939441ca</code></td></tr><tr><td>Fogo</td><td><code>tbr7Qje6qBzPwfM52csL5KFi8ps5c5vDyiVVBLYVdRf</code></td></tr><tr><td>Ink</td><td><code>0x4bFB47F4c8A904d2C24e73601D175FE3a38aAb5B</code></td></tr><tr><td>MegaETH</td><td><code>0x4eEC1c908aD6e778664Efb03386C429fE5710D77</code></td></tr><tr><td>Monad</td><td><code>0xf7E051f93948415952a2239582823028DacA948e</code></td></tr><tr><td>Moonbeam</td><td><code>0xF6b9616C63Fa48D07D82c93CE02B5d9111c51a3d</code></td></tr><tr><td>Optimism</td><td><code>0x37aC29617AE74c750a1e4d55990296BAF9b8De73</code></td></tr><tr><td>Polygon</td><td><code>0x1d98CA4221516B9ac4869F5CeA7E6bb9C41609D6</code></td></tr><tr><td>Scroll</td><td><code>0x05129e142e7d5A518D81f19Db342fBF5f7E26A18</code></td></tr><tr><td>SeiEVM</td><td><code>0x7C129bc8F6188d12c0d1BBDE247F134148B97618</code></td></tr><tr><td>Sui</td><td><code>0x9b68b36399a3cd87680878d72253b3e8fdf82edb8ed74f7ec440b8bddd51f85d</code></td></tr><tr><td>Unichain</td><td><code>0x9Bca817F67f01557aeD615130825A28F4C5f3b87</code></td></tr><tr><td>World Chain</td><td><code>0xc0565Bd29b34603C0383598E16843d95Ae9c4f65</code></td></tr><tr><td>XRPL-EVM</td><td><code>0x37bCc9d175124F77Bfce68589d2a8090eF846B85</code></td></tr></tbody></table>

=== "Testnet"

    <table data-full-width="true" markdown><thead><th>Chain Name</th><th>Contract Address</th></thead><tbody><tr><td>Ethereum Sepolia</td><td><code>0xb0b2119067cF04fa959f654250BD49fE1BD6F53c</code></td></tr><tr><td>Solana</td><td><code>tbr7Qje6qBzPwfM52csL5KFi8ps5c5vDyiVVBLYVdRf</code></td></tr><tr><td>0G (Zero Gravity)</td><td><code>0x57188fC61ce92c8E941504562811660Ab883E895</code></td></tr><tr><td>Arbitrum Sepolia</td><td><code>0xaE8dc4a7438801Ec4edC0B035EcCCcF3807F4CC1</code></td></tr><tr><td>Avalanche</td><td><code>0x10Ce9a35883C44640e8B12fea4Cc1e77F77D8c52</code></td></tr><tr><td>Base Sepolia</td><td><code>0x523d25D33B975ad72283f73B1103354352dBCBb8</code></td></tr><tr><td>BNB Smart Chain</td><td><code>0x26e7e3869b781f360A108728EE8391Cee6051E17</code></td></tr><tr><td>Celo</td><td><code>0x9563a59c15842a6f322b10f69d1dd88b41f2e97b</code></td></tr><tr><td>Fantom</td><td><code>0x9563a59c15842a6f322b10f69d1dd88b41f2e97b</code></td></tr><tr><td>Fogo</td><td><code>tbr7Qje6qBzPwfM52csL5KFi8ps5c5vDyiVVBLYVdRf</code></td></tr><tr><td>Linea</td><td><code>0x1C5CC8522b5eE1e528159989A163167bC9264D07</code></td></tr><tr><td>Mezo</td><td><code>0x2002a44b1106DF83671Fb419A2079a75e2a34808</code></td></tr><tr><td>Moca</td><td><code>0x36b91D24BAba19Af3aD1b5D5E2493A571044f14F</code></td></tr><tr><td>Monad Testnet</td><td><code>0x03D9739c91a26d30f4B35f7e55B9FF995ef13dDb</code></td></tr><tr><td>Moonbeam</td><td><code>0x9563a59c15842a6f322b10f69d1dd88b41f2e97b</code></td></tr><tr><td>Optimism Sepolia</td><td><code>0xD9AA4f8Ac271B3149b8C3d1D0f999Ef7cb9af9EC</code></td></tr><tr><td>Polygon Amoy</td><td><code>0xC5c0bF6A8419b3d47150B2a6146b7Ed598C9d736</code></td></tr><tr><td>SeiEVM</td><td><code>0x595712bA7e4882af338d60ae37058082a5d0331A</code></td></tr><tr><td>Sui</td><td><code>0xb4b86c12d4ee0a813d976fb452b7afb325a2b381d00ccb2e54c5342f5ef2e684</code></td></tr><tr><td>Unichain</td><td><code>0x74D37B2bcD2f8CaB6409c5a5f81C8cF5b4156963</code></td></tr><tr><td>XRPL-EVM</td><td><code>0xb00224c60fe6ab134c8544dc29350286545f8dcc</code></td></tr></tbody></table>

## WTT Executor with Referrer



=== "Mainnet"

    <table data-full-width="true" markdown><thead><th>Chain Name</th><th>Contract Address</th></thead><tbody><tr><td>Ethereum</td><td><code>0x412f30e9f8B4a1e99eaE90209A6b00f5C3cc8739</code></td></tr><tr><td>0G (Zero Gravity)</td><td><code>0x412f30e9f8B4a1e99eaE90209A6b00f5C3cc8739</code></td></tr><tr><td>Arbitrum</td><td><code>0x412f30e9f8B4a1e99eaE90209A6b00f5C3cc8739</code></td></tr><tr><td>Avalanche</td><td><code>0x412f30e9f8B4a1e99eaE90209A6b00f5C3cc8739</code></td></tr><tr><td>Base</td><td><code>0x412f30e9f8B4a1e99eaE90209A6b00f5C3cc8739</code></td></tr><tr><td>Berachain</td><td><code>0x412f30e9f8B4a1e99eaE90209A6b00f5C3cc8739</code></td></tr><tr><td>BNB Smart Chain</td><td><code>0x412f30e9f8B4a1e99eaE90209A6b00f5C3cc8739</code></td></tr><tr><td>Celo</td><td><code>0x412f30e9f8B4a1e99eaE90209A6b00f5C3cc8739</code></td></tr><tr><td>Ink</td><td><code>0x412f30e9f8B4a1e99eaE90209A6b00f5C3cc8739</code></td></tr><tr><td>MegaETH</td><td><code>0x412f30e9f8B4a1e99eaE90209A6b00f5C3cc8739</code></td></tr><tr><td>Monad</td><td><code>0x412f30e9f8B4a1e99eaE90209A6b00f5C3cc8739</code></td></tr><tr><td>Moonbeam</td><td><code>0x412f30e9f8B4a1e99eaE90209A6b00f5C3cc8739</code></td></tr><tr><td>Optimism</td><td><code>0x412f30e9f8B4a1e99eaE90209A6b00f5C3cc8739</code></td></tr><tr><td>Polygon</td><td><code>0x412f30e9f8B4a1e99eaE90209A6b00f5C3cc8739</code></td></tr><tr><td>Scroll</td><td><code>0x412f30e9f8B4a1e99eaE90209A6b00f5C3cc8739</code></td></tr><tr><td>SeiEVM</td><td><code>0x412f30e9f8B4a1e99eaE90209A6b00f5C3cc8739</code></td></tr><tr><td>Unichain</td><td><code>0x412f30e9f8B4a1e99eaE90209A6b00f5C3cc8739</code></td></tr><tr><td>World Chain</td><td><code>0x412f30e9f8B4a1e99eaE90209A6b00f5C3cc8739</code></td></tr><tr><td>XRPL-EVM</td><td><code>0x13a35c075D6Acc1Fb9BddFE5FE38e7672789e4db</code></td></tr></tbody></table>

=== "Testnet"

    <table data-full-width="true" markdown><thead><th>Chain Name</th><th>Contract Address</th></thead><tbody><tr><td>Ethereum Sepolia</td><td><code>0x412f30e9f8B4a1e99eaE90209A6b00f5C3cc8739</code></td></tr><tr><td>0G (Zero Gravity)</td><td><code>0x412f30e9f8B4a1e99eaE90209A6b00f5C3cc8739</code></td></tr><tr><td>Avalanche</td><td><code>0x412f30e9f8B4a1e99eaE90209A6b00f5C3cc8739</code></td></tr><tr><td>Base Sepolia</td><td><code>0x412f30e9f8B4a1e99eaE90209A6b00f5C3cc8739</code></td></tr><tr><td>BNB Smart Chain</td><td><code>0x412f30e9f8B4a1e99eaE90209A6b00f5C3cc8739</code></td></tr><tr><td>Linea</td><td><code>0x412f30e9f8B4a1e99eaE90209A6b00f5C3cc8739</code></td></tr><tr><td>Mezo</td><td><code>0x412f30e9f8B4a1e99eaE90209A6b00f5C3cc8739</code></td></tr><tr><td>Moca</td><td><code>0x412f30e9f8B4a1e99eaE90209A6b00f5C3cc8739</code></td></tr><tr><td>Monad Testnet</td><td><code>0x412f30e9f8B4a1e99eaE90209A6b00f5C3cc8739</code></td></tr><tr><td>Optimism Sepolia</td><td><code>0x412f30e9f8B4a1e99eaE90209A6b00f5C3cc8739</code></td></tr><tr><td>Polygon Amoy</td><td><code>0x412f30e9f8B4a1e99eaE90209A6b00f5C3cc8739</code></td></tr><tr><td>SeiEVM</td><td><code>0x412f30e9f8B4a1e99eaE90209A6b00f5C3cc8739</code></td></tr><tr><td>Unichain</td><td><code>0x412f30e9f8B4a1e99eaE90209A6b00f5C3cc8739</code></td></tr><tr><td>XRPL-EVM</td><td><code>0x17CFAAf9e8a5ABb1eee758dB9040F945c9EAC907</code></td></tr></tbody></table>


---

Page Title: Executor Addresses

- Resolved Markdown: https://wormhole.com/docs/ai/pages/products-reference-executor-addresses.md
- Canonical (HTML): https://wormhole.com/docs/products/reference/executor-addresses/
- Summary: Reference list of deployed Executor contract addresses across integrations, including CCTP, NTT, WTT, and referrer variants.
- Word Count: 3178; Token Estimate: 9141

# Executor Addresses

## Executor



=== "Mainnet"

    <table data-full-width="true" markdown><thead><th>Chain Name</th><th>Contract Address</th></thead><tbody><tr><td>Ethereum</td><td><code>0x84EEe8dBa37C36947397E1E11251cA9A06Fc6F8a</code></td></tr><tr><td>Solana</td><td><code>execXUrAsMnqMmTHj5m7N1YQgsDz3cwGLYCYyuDRciV</code></td></tr><tr><td>0G (Zero Gravity)</td><td><code>0xcD2BffD0C0289e8C0cb89c458dB1B74f1892Fa6c</code></td></tr><tr><td>Aptos</td><td><code>0x11aa75c059e1a7855be66b931bf340a2e0973274ac16b5f519c02ceafaf08a18</code></td></tr><tr><td>Arbitrum</td><td><code>0x3980f8318fc03d79033Bbb421A622CDF8d2Eeab4</code></td></tr><tr><td>Avalanche</td><td><code>0x4661F0E629E4ba8D04Ee90080Aee079740B00381</code></td></tr><tr><td>Base</td><td><code>0x9E1936E91A4a5AE5A5F75fFc472D6cb8e93597ea</code></td></tr><tr><td>Berachain</td><td><code>0x0Dd7a5a32311b8D87A615Cc7f079B632D3d5e2D3</code></td></tr><tr><td>BNB Smart Chain</td><td><code>0xeC8cCCD058DbF28e5D002869Aa9aFa3992bf4ee0</code></td></tr><tr><td>Celo</td><td><code>0xe6Ea5087c6860B94Cf098a403506262D8F28cF05</code></td></tr><tr><td>CreditCoin</td><td><code>0xd2e420188f17607Aa6344ee19c3e76Cf86CA7BDe</code></td></tr><tr><td>Fogo</td><td><code>execXUrAsMnqMmTHj5m7N1YQgsDz3cwGLYCYyuDRciV</code></td></tr><tr><td>HyperEVM :material-alert:{ title='⚠️ The HyperEVM integration is experimental, as its node software is not open source. Use Wormhole messaging on HyperEVM with caution.' }</td><td><code>0xd7717899cc4381033Bc200431286D0AC14265F78</code></td></tr><tr><td>Ink</td><td><code>0x3e44a5F45cbD400acBEF534F51e616043B211Ddd</code></td></tr><tr><td>Linea</td><td><code>0x23aF2B5296122544A9A7861da43405D5B15a9bD3</code></td></tr><tr><td>MegaETH</td><td><code>0xD405E0A1f3f9edc25Ea32d0B079d6118328b2EcB</code></td></tr><tr><td>Mezo</td><td><code>0x0f9b8E144Cc5C5e7C0073829Afd30F26A50c5606</code></td></tr><tr><td>Moca</td><td><code>0x7b8097af5459846c5A72fCc960D94F31C05915aD</code></td></tr><tr><td>Monad</td><td><code>0xC04dE634982cAdF2A677310b73630B7Ac56A3f65</code></td></tr><tr><td>Moonbeam</td><td><code>0x85D06449C78064c2E02d787e9DC71716786F8D19</code></td></tr><tr><td>Optimism</td><td><code>0x85B704501f6AE718205C0636260768C4e72ac3e7</code></td></tr><tr><td>Polygon</td><td><code>0x0B23efA164aB3eD08e9a39AC7aD930Ff4F5A5e81</code></td></tr><tr><td>Scroll</td><td><code>0xcFAdDE24640e395F5A71456A825D0D7C3741F075</code></td></tr><tr><td>SeiEVM</td><td><code>0x25f1c923fb7a5aefa5f0a2b419fc70f2368e66e5</code></td></tr><tr><td>Sonic</td><td><code>0x3Fdc36b4260Da38fBDba1125cCBD33DD0AC74812</code></td></tr><tr><td>Sui</td><td><code>0xdb0fe8bb1e2b5be628adbea0636063325073e1070ee11e4281457dfd7f158235</code></td></tr><tr><td>Unichain</td><td><code>0x764dD868eAdD27ce57BCB801E4ca4a193d231Aed</code></td></tr><tr><td>World Chain</td><td><code>0x8689b4E6226AdC8fa8FF80aCc3a60AcE31e8804B</code></td></tr><tr><td>XRPL-EVM</td><td><code>0x8345E90Dcd92f5Cf2FAb0C8E2A56A5bc2c30d896</code></td></tr></tbody></table>

=== "Testnet"

    <table data-full-width="true" markdown><thead><th>Chain Name</th><th>Contract Address</th></thead><tbody><tr><td>Ethereum Sepolia</td><td><code>0xD0fb39f5a3361F21457653cB70F9D0C9bD86B66B</code></td></tr><tr><td>Solana</td><td><code>execXUrAsMnqMmTHj5m7N1YQgsDz3cwGLYCYyuDRciV</code></td></tr><tr><td>0G (Zero Gravity)</td><td><code>0x7C43825EeB76DF7aAf3e1D2e8f684d4876F0CC05</code></td></tr><tr><td>Aptos</td><td><code>0x139717c339f08af674be77143507a905aa28cbc67a0e53e7095c07b630d73815</code></td></tr><tr><td>Arbitrum Sepolia</td><td><code>0xBF161de6B819c8af8f2230Bcd99a9B3592f6F87b</code></td></tr><tr><td>Avalanche</td><td><code>0x4661F0E629E4ba8D04Ee90080Aee079740B00381</code></td></tr><tr><td>Base Sepolia</td><td><code>0x51B47D493CBA7aB97e3F8F163D6Ce07592CE4482</code></td></tr><tr><td>BNB Smart Chain</td><td><code>0xeC8cCCD058DbF28e5D002869Aa9aFa3992bf4ee0</code></td></tr><tr><td>Converge</td><td><code>0xAab9935349B9c08e0e970720F6D640d5B91C293E</code></td></tr><tr><td>Fogo</td><td><code>execXUrAsMnqMmTHj5m7N1YQgsDz3cwGLYCYyuDRciV</code></td></tr><tr><td>Linea</td><td><code>0x4f6c3a93a80DdC691312974DAAbf9B6e4Bb44111</code></td></tr><tr><td>Mezo</td><td><code>0x0f9b8E144Cc5C5e7C0073829Afd30F26A50c5606</code></td></tr><tr><td>Moca</td><td><code>0xc4a03f2c47caA4b961101bAD6338DEf37376F052</code></td></tr><tr><td>Monad Testnet</td><td><code>0xe37D3E162B4B1F17131E4e0e6122DbA31243382f</code></td></tr><tr><td>Optimism Sepolia</td><td><code>0x5856651eB82aeb6979B4954317194d48e1891b3c</code></td></tr><tr><td>Plume</td><td><code>0x8fc2FbA8F962fbE89a9B02f03557a011c335A455</code></td></tr><tr><td>Polygon Amoy</td><td><code>0x7056721C33De437f0997F67BC87521cA86b721d3</code></td></tr><tr><td>SeiEVM</td><td><code>0x25f1c923Fb7A5aEFA5F0A2b419fC70f2368e66e5</code></td></tr><tr><td>Sui</td><td><code>0x4000cfe2955d8355b3d3cf186f854fea9f787a457257056926fde1ec977670eb</code></td></tr><tr><td>Unichain</td><td><code>0x764dD868eAdD27ce57BCB801E4ca4a193d231Aed</code></td></tr><tr><td>XRPL-EVM</td><td><code>0x4d9525D94D275dEB495b7C8840b154Ae04cfaC2A</code></td></tr></tbody></table>

## CCTP With Executor



=== "Mainnet v1"

    <table data-full-width="true" markdown><thead><th>Chain Name</th><th>Contract Address</th></thead><tbody><tr><td>Ethereum</td><td><code>0x6DDE92942DbB24F7c9B75765b74a33446980C1e3</code></td></tr><tr><td>Solana</td><td><code>CXGRA5SCc8jxDbaQPZrmmZNu2JV34DP7gFW4m31uC1zs</code></td></tr><tr><td>Aptos</td><td><code>0xc89bf3746dfc70bb3f2de7c35a98f327a40b9d55a443743a5935c5e3de90b7ac</code></td></tr><tr><td>Arbitrum</td><td><code>0x772373214238F09a494828A5323574E3d7e27558</code></td></tr><tr><td>Avalanche</td><td><code>0x58aC806cd205083E7E048E196f36Ff6C4Ae17bE5</code></td></tr><tr><td>Base</td><td><code>0x4D1Cc8921e297155044C01761f581fa52a24C33d</code></td></tr><tr><td>Optimism</td><td><code>0x6826c075973a4393CEf0e131c4B16869426563a7</code></td></tr><tr><td>Polygon</td><td><code>0x7e6Ae241101B355447A4B471D0C6968b132eC4Ab</code></td></tr><tr><td>Sui</td><td><code>N/A*</code></td></tr><tr><td>Unichain</td><td><code>0xa997Ef229E4D2a1fEca249eB41fBf5D4b2217d6E</code></td></tr></tbody></table>

=== "Testnet v1"

    <table data-full-width="true" markdown><thead><th>Chain Name</th><th>Contract Address</th></thead><tbody><tr><td>Ethereum Sepolia</td><td><code>0x2fcc7b2332d924764f17f1cf5eda1cd4b36751a2</code></td></tr><tr><td>Solana</td><td><code>CXGRA5SCc8jxDbaQPZrmmZNu2JV34DP7gFW4m31uC1zs</code></td></tr><tr><td>Aptos</td><td><code>0x14a12d1fd6ef371b70c2113155534ec152ec7f779e281b54866c796c9a4a58d3</code></td></tr><tr><td>Arbitrum Sepolia</td><td><code>0x8158305d331594f3e8d18c33ca4e6d3cdc109b75</code></td></tr><tr><td>Avalanche</td><td><code>0x62819ab61cc7fcc864af7bcfc92e6c1965eb69a6</code></td></tr><tr><td>Base Sepolia</td><td><code>0x96846c31e4f87c0f186a322926c61d4183439f0a</code></td></tr><tr><td>Optimism Sepolia</td><td><code>0xe17de8e29f1f0941b541b053829af74ac81c89a6</code></td></tr><tr><td>Polygon</td><td><code>0xdce63172e9ad15243c97acafd01cc4fdda98bead</code></td></tr><tr><td>Unichain Sepolia</td><td><code>0x2c1354296a11029056e0d7d7abbdd58743dbaf59</code></td></tr></tbody></table>

=== "Mainnet v2"

    <table data-full-width="true" markdown><thead><th>Chain Name</th><th>Contract Address</th></thead><tbody><tr><td>Ethereum</td><td><code>0xDD68aBa3E04CB1a05082402B9325753314803005</code></td></tr><tr><td>Solana</td><td><code>Supported</code></td></tr><tr><td>Arbitrum</td><td><code>0x760feC4425B46E3D8FEf8E2CE49786e5a6f74446</code></td></tr><tr><td>Avalanche</td><td><code>0xE42aE9e352157fcEf74E971F2C5c74A5963a71D7</code></td></tr><tr><td>Base</td><td><code>0x52892976559fB2fc8b7f850440eD9AA5Dc26f7D9</code></td></tr><tr><td>Codex</td><td><code>0x0684286448140F75d4C3D2F2c02BF66f98CdEA51</code></td></tr><tr><td>HyperEVM :material-alert:{ title='⚠️ The HyperEVM integration is experimental, as its node software is not open source. Use Wormhole messaging on HyperEVM with caution.' }</td><td><code>0x001319beBA062d918d7007E4D2D76a0A9cc439Db</code></td></tr><tr><td>Ink</td><td><code>0xef0B43b49315A4aDF11bA2617Be81a304c5D6ecc</code></td></tr><tr><td>Linea</td><td><code>0x257dBB6AD7C7AC19360bEe1A107ebE631D568776</code></td></tr><tr><td>Monad</td><td><code>0x1FdCCf65318b34CFd3F5903fFb747C17e76330ac</code></td></tr><tr><td>Optimism</td><td><code>0x9b51579e67D4ab18D79609105509ad37B2a0D342</code></td></tr><tr><td>Plume</td><td><code>0x9be9C6B420eAfaaC1162D680fd7E61446b38Cf29</code></td></tr><tr><td>Polygon</td><td><code>0x5116F1358ae2445f571AA702dA1feB5e13094E59</code></td></tr><tr><td>SeiEVM</td><td><code>0xe067C0D378C50CDc34bCd973F202736D5A19e5D2</code></td></tr><tr><td>Sonic</td><td><code>0x8A850b2077F1eFccA89eAa9c35b45C4dC9227cdb</code></td></tr><tr><td>Sui</td><td><code>N/A*</code></td></tr><tr><td>Unichain</td><td><code>0xaf7f4FbB6C220baf57ABC7babF81D47Fd628bdb4</code></td></tr><tr><td>World Chain</td><td><code>0xAA4841e5d9652593852403E3ce9e8003f8D579D0</code></td></tr></tbody></table>

=== "Testnet v2"

    <table data-full-width="true" markdown><thead><th>Chain Name</th><th>Contract Address</th></thead><tbody><tr><td>Ethereum Sepolia</td><td><code>0xc58475c97ebde9cf4fefa0d4fb2774df81905d43</code></td></tr><tr><td>Solana</td><td><code>Supported</code></td></tr><tr><td>Arbitrum Sepolia</td><td><code>0xf601f9988d62943cb842baae1e46be9b17d0b2a4</code></td></tr><tr><td>Avalanche</td><td><code>0x10018394905f70daa1d740040d64cbed5a82301e</code></td></tr><tr><td>Base Sepolia</td><td><code>0x1effdcfedc6d45e44b3133257debfb522adb1cae</code></td></tr><tr><td>Ink</td><td><code>0x63993ee08bda32ecb0ba5cdc751b404f5c5c0458</code></td></tr><tr><td>Linea Sepolia</td><td><code>0xe8Ad216e23fc9425E65aB315F0EC13737e75afEF</code></td></tr><tr><td>Monad Testnet</td><td><code>0x358bAd031d7A217ebA2d471cad5fD611AeC2aF17</code></td></tr><tr><td>Optimism Sepolia</td><td><code>0x49f386393c26439b74e62f5794062925dfb7c1db</code></td></tr><tr><td>Polygon</td><td><code>0x05da7c69db265b37b4d3530d476ec4b33bd9dd45</code></td></tr><tr><td>SeiEVM</td><td><code>0xDC735908C3eCF29f40D8CA5f6407F2d94d316a9F</code></td></tr><tr><td>Unichain Sepolia</td><td><code>0xf082af7668f000f60bc519b378f6363708fc302b</code></td></tr></tbody></table>

## NTT With Executor



=== "Mainnet"

    <table data-full-width="true" markdown><thead><th>Chain Name</th><th>Contract Address</th></thead><tbody><tr><td>Ethereum</td><td><code>0xD2D9c936165a85F27a5a7e07aFb974D022B89463</code><br>Multi Ntt: <code>0x03dB430D830601DB368991eE55DAa9A708df7912</code></td></tr><tr><td>Solana</td><td><code>nex1gkSWtRBheEJuQZMqHhbMG5A45qPU76KqnCZNVHR</code></td></tr><tr><td>0G</td><td><code>0xe175a8b838f3cdb2e1aaf4ff74c05cf2f3aea9a8</code></td></tr><tr><td>Arbitrum</td><td><code>0x0Af42A597b0C201D4dcf450DcD0c06d55ddC1C77</code></td></tr><tr><td>Avalanche</td><td><code>0x4e9Af03fbf1aa2b79A2D4babD3e22e09f18Bb8EE</code></td></tr><tr><td>Base</td><td><code>0x83216747fC21b86173D800E2960c0D5395de0F30</code></td></tr><tr><td>Berachain</td><td><code>0x0a2AF374Cc9CCCbB0Acc4E34B20b9d02a0f08c30</code></td></tr><tr><td>BNB Smart Chain</td><td><code>0x39B57Dd9908F8be02CfeE283b67eA1303Bc29fe1</code></td></tr><tr><td>Celo</td><td><code>0x3d69869fcB9e1CD1F4020b637fb8256030BAc8fC</code></td></tr><tr><td>CreditCoin</td><td><code>0x5454b995719626256C96fb57454b044ffb3Da2F9</code></td></tr><tr><td>Fogo</td><td><code>nex1gkSWtRBheEJuQZMqHhbMG5A45qPU76KqnCZNVHR</code></td></tr><tr><td>HyperEVM :material-alert:{ title='⚠️ The HyperEVM integration is experimental, as its node software is not open source. Use Wormhole messaging on HyperEVM with caution.' }</td><td><code>0x431017B1718b86898C7590fFcCC380DEf0456393</code></td></tr><tr><td>Ink</td><td><code>0x420370DC2ECC4D44b47514B7859fd11809BbeFF5</code></td></tr><tr><td>Linea</td><td><code>0xEAa5AddB5b8939Eb73F7faF46e193EefECaF13E9</code></td></tr><tr><td>MegaETH</td><td><code>0x3EFEc0c7Ee79135330DD03e995872f84b1AD49b6</code></td></tr><tr><td>Mezo</td><td><code>0x484b5593BbB90383f94FB299470F09427cf6cfE2</code></td></tr><tr><td>Moca</td><td><code>0xE612837749a0690BA2BCe490D6eFb5F8Fc347df3</code></td></tr><tr><td>Monad</td><td><code>0xc3F3dDa544815a440633176c7598f5B97500793e</code><br>Multi Ntt: <code>0xFEA937F7124E19124671f1685671d3f04a9Af4E4</code></td></tr><tr><td>Moonbeam</td><td><code>0x1365593C8bae71a55e48E105a2Bb76d5928c7DE3</code></td></tr><tr><td>Optimism</td><td><code>0x85C0129bE5226C9F0Cf4e419D2fefc1c3FCa25cF</code></td></tr><tr><td>Plume</td><td><code>0x6Eb53371f646788De6B4D0225a4Ed1d9267188AD</code></td></tr><tr><td>Polygon</td><td><code>0x6762157b73941e36cEd0AEf54614DdE545d0F990</code></td></tr><tr><td>Scroll</td><td><code>0x055625d48968f99409244E8c3e03FbE73B235a62</code></td></tr><tr><td>SeiEVM</td><td><code>0x3F2D6441C7a59Dfe80f8e14142F9E28F6D440445</code></td></tr><tr><td>Sonic</td><td><code>0xaCa00703bb87F31D6F9fCcc963548b48FA46DfeB</code></td></tr><tr><td>Sui</td><td><code>N/A*</code></td></tr><tr><td>Unichain</td><td><code>0x607723D6353Dae3ef62B7B277Cfabd0F4bc6CB4C</code></td></tr><tr><td>World Chain</td><td><code>0x66b1644400D51e104272337226De3EF1A820eC79</code></td></tr><tr><td>XRPL-EVM</td><td><code>0x6bBd1ff3bB303F88835A714EE3241bF45DE26d29</code></td></tr></tbody></table>

=== "Testnet"

    <table data-full-width="true" markdown><thead><th>Chain Name</th><th>Contract Address</th></thead><tbody><tr><td>Ethereum Sepolia</td><td><code>0x54DD7080aE169DD923fE56d0C4f814a0a17B8f41</code></td></tr><tr><td>Solana</td><td><code>nex1gkSWtRBheEJuQZMqHhbMG5A45qPU76KqnCZNVHR</code></td></tr><tr><td>0G Galileo</td><td><code>0xA8CA118f4C8d44Ab651Dad52B5E1a212e5d5c55b</code></td></tr><tr><td>Arbitrum Sepolia</td><td><code>0xd048170F1ECB8D47E499D3459aC379DA023E2C1B</code></td></tr><tr><td>Avalanche</td><td><code>0x4e9Af03fbf1aa2b79A2D4babD3e22e09f18Bb8EE</code></td></tr><tr><td>Base Sepolia</td><td><code>0x5845E08d890E21687F7Ebf7CbAbD360cD91c6245</code></td></tr><tr><td>BNB Smart Chain</td><td><code>0x39B57Dd9908F8be02CfeE283b67eA1303Bc29fe1</code></td></tr><tr><td>Celo</td><td><code>0x3d69869fcB9e1CD1F4020b637fb8256030BAc8fC</code></td></tr><tr><td>Converge</td><td><code>0x3d8c26b67BDf630FBB44F09266aFA735F1129197</code></td></tr><tr><td>Fogo</td><td><code>nex1gkSWtRBheEJuQZMqHhbMG5A45qPU76KqnCZNVHR</code></td></tr><tr><td>Ink</td><td><code>0xF420BFFf922D11c2bBF587C9dF71b83651fAf8Bc</code></td></tr><tr><td>Linea Sepolia</td><td><code>0xaA469cb84C91D5a63bf4B370dE35f0831F2CE4FF</code></td></tr><tr><td>Mezo</td><td><code>0x484b5593BbB90383f94FB299470F09427cf6cfE2</code></td></tr><tr><td>Moca</td><td><code>0x47f26bF9253Eb398fBAf825D7565FE975D839a71</code></td></tr><tr><td>Monad Testnet</td><td><code>0xc8F014FE6a8521259D9ADDc2170bA9e59305D306</code></td></tr><tr><td>Optimism Sepolia</td><td><code>0xaDB1C56D363FF5A75260c3bd27dd7C1fC8421EF5</code></td></tr><tr><td>Plume</td><td><code>0x6Eb53371f646788De6B4D0225a4Ed1d9267188AD</code></td></tr><tr><td>Polygon</td><td><code>0x2982B9566E912458fE711FB1Fd78158264596937</code></td></tr><tr><td>SeiEVM</td><td><code>0x3F2D6441C7a59Dfe80f8e14142F9E28F6D440445</code></td></tr><tr><td>Unichain Sepolia</td><td><code>0x607723D6353Dae3ef62B7B277Cfabd0F4bc6CB4C</code></td></tr><tr><td>XRPL EVM Testnet</td><td><code>0xcDD9d7C759b29680f7a516d0058de8293b2AC7b1</code></td></tr></tbody></table>

## WTT Executor



=== "Mainnet"

    <table data-full-width="true" markdown><thead><th>Chain Name</th><th>Contract Address</th></thead><tbody><tr><td>Ethereum</td><td><code>0xa8969F3f8D97b3Ed89D4e2EC19B6B0CfD504b212</code></td></tr><tr><td>Solana</td><td><code>tbr7Qje6qBzPwfM52csL5KFi8ps5c5vDyiVVBLYVdRf</code></td></tr><tr><td>0G (Zero Gravity)</td><td><code>0x3dBb4dCf25dBA8F0C2417E1c34e527De0E465ecc</code></td></tr><tr><td>Arbitrum</td><td><code>0x04C98824a64d75CD1E9Bc418088b4c9A99048153</code></td></tr><tr><td>Avalanche</td><td><code>0x8849F05675E034b54506caB84450c8C82694a786</code></td></tr><tr><td>Base</td><td><code>0xD8B736EF27Fc997b1d00F22FE37A58145D3BDA07</code></td></tr><tr><td>Berachain</td><td><code>0xFAeFa20CB3759AEd2310E25015F05d62D8567A3F</code></td></tr><tr><td>BNB Smart Chain</td><td><code>0x2513515340fF71DD5AF02fC1BdB9615704d91524</code></td></tr><tr><td>Celo</td><td><code>0xe478DEe705BEae591395B08934FA19F54df316BE</code></td></tr><tr><td>Fantom</td><td><code>0xcafd2f0a35a4459fa40c0517e17e6fa2939441ca</code></td></tr><tr><td>Fogo</td><td><code>tbr7Qje6qBzPwfM52csL5KFi8ps5c5vDyiVVBLYVdRf</code></td></tr><tr><td>Ink</td><td><code>0x4bFB47F4c8A904d2C24e73601D175FE3a38aAb5B</code></td></tr><tr><td>MegaETH</td><td><code>0x4eEC1c908aD6e778664Efb03386C429fE5710D77</code></td></tr><tr><td>Monad</td><td><code>0xf7E051f93948415952a2239582823028DacA948e</code></td></tr><tr><td>Moonbeam</td><td><code>0xF6b9616C63Fa48D07D82c93CE02B5d9111c51a3d</code></td></tr><tr><td>Optimism</td><td><code>0x37aC29617AE74c750a1e4d55990296BAF9b8De73</code></td></tr><tr><td>Polygon</td><td><code>0x1d98CA4221516B9ac4869F5CeA7E6bb9C41609D6</code></td></tr><tr><td>Scroll</td><td><code>0x05129e142e7d5A518D81f19Db342fBF5f7E26A18</code></td></tr><tr><td>SeiEVM</td><td><code>0x7C129bc8F6188d12c0d1BBDE247F134148B97618</code></td></tr><tr><td>Sui</td><td><code>0x9b68b36399a3cd87680878d72253b3e8fdf82edb8ed74f7ec440b8bddd51f85d</code></td></tr><tr><td>Unichain</td><td><code>0x9Bca817F67f01557aeD615130825A28F4C5f3b87</code></td></tr><tr><td>World Chain</td><td><code>0xc0565Bd29b34603C0383598E16843d95Ae9c4f65</code></td></tr><tr><td>XRPL-EVM</td><td><code>0x37bCc9d175124F77Bfce68589d2a8090eF846B85</code></td></tr></tbody></table>

=== "Testnet"

    <table data-full-width="true" markdown><thead><th>Chain Name</th><th>Contract Address</th></thead><tbody><tr><td>Ethereum Sepolia</td><td><code>0xb0b2119067cF04fa959f654250BD49fE1BD6F53c</code></td></tr><tr><td>Solana</td><td><code>tbr7Qje6qBzPwfM52csL5KFi8ps5c5vDyiVVBLYVdRf</code></td></tr><tr><td>0G (Zero Gravity)</td><td><code>0x57188fC61ce92c8E941504562811660Ab883E895</code></td></tr><tr><td>Arbitrum Sepolia</td><td><code>0xaE8dc4a7438801Ec4edC0B035EcCCcF3807F4CC1</code></td></tr><tr><td>Avalanche</td><td><code>0x10Ce9a35883C44640e8B12fea4Cc1e77F77D8c52</code></td></tr><tr><td>Base Sepolia</td><td><code>0x523d25D33B975ad72283f73B1103354352dBCBb8</code></td></tr><tr><td>BNB Smart Chain</td><td><code>0x26e7e3869b781f360A108728EE8391Cee6051E17</code></td></tr><tr><td>Celo</td><td><code>0x9563a59c15842a6f322b10f69d1dd88b41f2e97b</code></td></tr><tr><td>Fantom</td><td><code>0x9563a59c15842a6f322b10f69d1dd88b41f2e97b</code></td></tr><tr><td>Fogo</td><td><code>tbr7Qje6qBzPwfM52csL5KFi8ps5c5vDyiVVBLYVdRf</code></td></tr><tr><td>Linea</td><td><code>0x1C5CC8522b5eE1e528159989A163167bC9264D07</code></td></tr><tr><td>Mezo</td><td><code>0x2002a44b1106DF83671Fb419A2079a75e2a34808</code></td></tr><tr><td>Moca</td><td><code>0x36b91D24BAba19Af3aD1b5D5E2493A571044f14F</code></td></tr><tr><td>Monad Testnet</td><td><code>0x03D9739c91a26d30f4B35f7e55B9FF995ef13dDb</code></td></tr><tr><td>Moonbeam</td><td><code>0x9563a59c15842a6f322b10f69d1dd88b41f2e97b</code></td></tr><tr><td>Optimism Sepolia</td><td><code>0xD9AA4f8Ac271B3149b8C3d1D0f999Ef7cb9af9EC</code></td></tr><tr><td>Polygon Amoy</td><td><code>0xC5c0bF6A8419b3d47150B2a6146b7Ed598C9d736</code></td></tr><tr><td>SeiEVM</td><td><code>0x595712bA7e4882af338d60ae37058082a5d0331A</code></td></tr><tr><td>Sui</td><td><code>0xb4b86c12d4ee0a813d976fb452b7afb325a2b381d00ccb2e54c5342f5ef2e684</code></td></tr><tr><td>Unichain</td><td><code>0x74D37B2bcD2f8CaB6409c5a5f81C8cF5b4156963</code></td></tr><tr><td>XRPL-EVM</td><td><code>0xb00224c60fe6ab134c8544dc29350286545f8dcc</code></td></tr></tbody></table>

## WTT Executor With Referrer



=== "Mainnet"

    <table data-full-width="true" markdown><thead><th>Chain Name</th><th>Contract Address</th></thead><tbody><tr><td>Ethereum</td><td><code>0x412f30e9f8B4a1e99eaE90209A6b00f5C3cc8739</code></td></tr><tr><td>0G (Zero Gravity)</td><td><code>0x412f30e9f8B4a1e99eaE90209A6b00f5C3cc8739</code></td></tr><tr><td>Arbitrum</td><td><code>0x412f30e9f8B4a1e99eaE90209A6b00f5C3cc8739</code></td></tr><tr><td>Avalanche</td><td><code>0x412f30e9f8B4a1e99eaE90209A6b00f5C3cc8739</code></td></tr><tr><td>Base</td><td><code>0x412f30e9f8B4a1e99eaE90209A6b00f5C3cc8739</code></td></tr><tr><td>Berachain</td><td><code>0x412f30e9f8B4a1e99eaE90209A6b00f5C3cc8739</code></td></tr><tr><td>BNB Smart Chain</td><td><code>0x412f30e9f8B4a1e99eaE90209A6b00f5C3cc8739</code></td></tr><tr><td>Celo</td><td><code>0x412f30e9f8B4a1e99eaE90209A6b00f5C3cc8739</code></td></tr><tr><td>Ink</td><td><code>0x412f30e9f8B4a1e99eaE90209A6b00f5C3cc8739</code></td></tr><tr><td>MegaETH</td><td><code>0x412f30e9f8B4a1e99eaE90209A6b00f5C3cc8739</code></td></tr><tr><td>Monad</td><td><code>0x412f30e9f8B4a1e99eaE90209A6b00f5C3cc8739</code></td></tr><tr><td>Moonbeam</td><td><code>0x412f30e9f8B4a1e99eaE90209A6b00f5C3cc8739</code></td></tr><tr><td>Optimism</td><td><code>0x412f30e9f8B4a1e99eaE90209A6b00f5C3cc8739</code></td></tr><tr><td>Polygon</td><td><code>0x412f30e9f8B4a1e99eaE90209A6b00f5C3cc8739</code></td></tr><tr><td>Scroll</td><td><code>0x412f30e9f8B4a1e99eaE90209A6b00f5C3cc8739</code></td></tr><tr><td>SeiEVM</td><td><code>0x412f30e9f8B4a1e99eaE90209A6b00f5C3cc8739</code></td></tr><tr><td>Unichain</td><td><code>0x412f30e9f8B4a1e99eaE90209A6b00f5C3cc8739</code></td></tr><tr><td>World Chain</td><td><code>0x412f30e9f8B4a1e99eaE90209A6b00f5C3cc8739</code></td></tr><tr><td>XRPL-EVM</td><td><code>0x13a35c075D6Acc1Fb9BddFE5FE38e7672789e4db</code></td></tr></tbody></table>

=== "Testnet"

    <table data-full-width="true" markdown><thead><th>Chain Name</th><th>Contract Address</th></thead><tbody><tr><td>Ethereum Sepolia</td><td><code>0x412f30e9f8B4a1e99eaE90209A6b00f5C3cc8739</code></td></tr><tr><td>0G (Zero Gravity)</td><td><code>0x412f30e9f8B4a1e99eaE90209A6b00f5C3cc8739</code></td></tr><tr><td>Avalanche</td><td><code>0x412f30e9f8B4a1e99eaE90209A6b00f5C3cc8739</code></td></tr><tr><td>Base Sepolia</td><td><code>0x412f30e9f8B4a1e99eaE90209A6b00f5C3cc8739</code></td></tr><tr><td>BNB Smart Chain</td><td><code>0x412f30e9f8B4a1e99eaE90209A6b00f5C3cc8739</code></td></tr><tr><td>Linea</td><td><code>0x412f30e9f8B4a1e99eaE90209A6b00f5C3cc8739</code></td></tr><tr><td>Mezo</td><td><code>0x412f30e9f8B4a1e99eaE90209A6b00f5C3cc8739</code></td></tr><tr><td>Moca</td><td><code>0x412f30e9f8B4a1e99eaE90209A6b00f5C3cc8739</code></td></tr><tr><td>Monad Testnet</td><td><code>0x412f30e9f8B4a1e99eaE90209A6b00f5C3cc8739</code></td></tr><tr><td>Optimism Sepolia</td><td><code>0x412f30e9f8B4a1e99eaE90209A6b00f5C3cc8739</code></td></tr><tr><td>Polygon Amoy</td><td><code>0x412f30e9f8B4a1e99eaE90209A6b00f5C3cc8739</code></td></tr><tr><td>SeiEVM</td><td><code>0x412f30e9f8B4a1e99eaE90209A6b00f5C3cc8739</code></td></tr><tr><td>Unichain</td><td><code>0x412f30e9f8B4a1e99eaE90209A6b00f5C3cc8739</code></td></tr><tr><td>XRPL-EVM</td><td><code>0x17CFAAf9e8a5ABb1eee758dB9040F945c9EAC907</code></td></tr></tbody></table>

## On-Chain Quoter

!!! note
    Wormhole Labs’ Quoter uses the following public keys:

    - **Mainnet**: `0xa54008017941EcE968623a0Dd8Ee907E2b133596`.
    - **Testnet**: `0x5241c9276698439fef2780dbab76fec90b633fbd`.
### Wormhole Labs Quoter Implementation



=== "Mainnet"

    <table data-full-width="true" markdown><thead><th>Chain Name</th><th>Contract Address</th></thead><tbody><tr><td>Ethereum</td><td><code>0xA25862D222Eb8343505c12d96e097e4332468D60</code></td></tr><tr><td>Arbitrum</td><td><code>0xA25862D222Eb8343505c12d96e097e4332468D60</code></td></tr><tr><td>Avalanche</td><td><code>0xA25862D222Eb8343505c12d96e097e4332468D60</code></td></tr><tr><td>Base</td><td><code>0xA25862D222Eb8343505c12d96e097e4332468D60</code></td></tr><tr><td>BNB Smart Chain</td><td><code>0xA25862D222Eb8343505c12d96e097e4332468D60</code></td></tr><tr><td>Ink</td><td><code>0xA25862D222Eb8343505c12d96e097e4332468D60</code></td></tr><tr><td>Monad</td><td><code>0xA25862D222Eb8343505c12d96e097e4332468D60</code></td></tr><tr><td>Optimism</td><td><code>0xA25862D222Eb8343505c12d96e097e4332468D60</code></td></tr><tr><td>Plume</td><td><code>0xA25862D222Eb8343505c12d96e097e4332468D60</code></td></tr><tr><td>Polygon</td><td><code>0xA25862D222Eb8343505c12d96e097e4332468D60</code></td></tr><tr><td>Sei</td><td><code>0xA25862D222Eb8343505c12d96e097e4332468D60</code></td></tr></tbody></table>

=== "Testnet"

    <table data-full-width="true" markdown><thead><th>Chain Name</th><th>Contract Address</th></thead><tbody><tr><td>Ethereum Sepolia</td><td><code>0x5a6c5A46082D029FDD7c5cF8265047E0c4BB2089</code></td></tr><tr><td>Solana</td><td><code>qtrxiqVAfVS61utwZLUi7UKugjCgFaNxBGyskmGingz</code></td></tr><tr><td>Arbitrum Sepolia</td><td><code>0x5a6c5A46082D029FDD7c5cF8265047E0c4BB2089</code></td></tr><tr><td>Avalanche</td><td><code>0x5a6c5A46082D029FDD7c5cF8265047E0c4BB2089</code></td></tr><tr><td>Base Sepolia</td><td><code>0x5a6c5A46082D029FDD7c5cF8265047E0c4BB2089</code></td></tr><tr><td>Optimism Sepolia</td><td><code>0x5a6c5A46082D029FDD7c5cF8265047E0c4BB2089</code></td></tr><tr><td>Polygon Amoy</td><td><code>0x5a6c5A46082D029FDD7c5cF8265047E0c4BB2089</code></td></tr><tr><td>Sei</td><td><code>0x5a6c5A46082D029FDD7c5cF8265047E0c4BB2089</code></td></tr></tbody></table>

### Quoter Router



=== "Mainnet"

    <table data-full-width="true" markdown><thead><th>Chain Name</th><th>Contract Address</th></thead><tbody><tr><td>Ethereum</td><td><code>0xF22F1c0A3a8Cb42F695601731974784C499C4EF3</code></td></tr><tr><td>Arbitrum</td><td><code>0x32eec14c963c23176bd8951f192292006756bDcC</code></td></tr><tr><td>Avalanche</td><td><code>0xA3a2A615774d34c6a4dF443C488B084eacaBd2D0</code></td></tr><tr><td>Base</td><td><code>0x265fd0500a430d65d6D79Cd8707F24C048604658</code></td></tr><tr><td>BNB Smart Chain</td><td><code>0xc921F293c27F332D47283174b11C872295624Edb</code></td></tr><tr><td>Ink</td><td><code>0xdEC050E66BEb2f0d5507761A0fE4867839bd88D2</code></td></tr><tr><td>Monad</td><td><code>0x3d9282A8e9a3cdd9b25AE969eff4705a1Fe75F34</code></td></tr><tr><td>Optimism</td><td><code>0xa3B6551cCbB5Fe1dc33b71EE3590B1Df22ae75B3</code></td></tr><tr><td>Plume</td><td><code>0x85BA1B2A2195be51Ab715be458B32B120532d230</code></td></tr><tr><td>Polygon</td><td><code>0x2a856931603930B827B1A4352FB4D66fA029F123</code></td></tr><tr><td>Sei</td><td><code>0x1D6FeA87671F7c5E184F4c59c3BdcEc5CFC3eC1c</code></td></tr></tbody></table>

=== "Testnet"

    <table data-full-width="true" markdown><thead><th>Chain Name</th><th>Contract Address</th></thead><tbody><tr><td>Ethereum Sepolia</td><td><code>0xc0C35D7bfBc4175e0991Ae294f561b433eA4158f</code></td></tr><tr><td>Solana</td><td><code>qtrrrV7W3E1jnX1145wXR6ZpthG19ur5xHC1n6PPhDV</code></td></tr><tr><td>Arbitrum Sepolia</td><td><code>0x5E8c14F436c9ed2ff2E8B042B0542136bf108C6f</code></td></tr><tr><td>Avalanche</td><td><code>0xA3a2A615774d34c6a4dF443C488B084eacaBd2D0</code></td></tr><tr><td>Base Sepolia</td><td><code>0x2507d6899C3D4b93BF46b555d0cB401f44065772</code></td></tr><tr><td>Optimism Sepolia</td><td><code>0x6a829dF7C91f35f9aD72Cd5d05550b95BbC9fd2F</code></td></tr><tr><td>Polygon Amoy</td><td><code>0xE00444636DA924FBAe94471d73D56b5E03cA781c</code></td></tr><tr><td>Sei</td><td><code>0x1D6FeA87671F7c5E184F4c59c3BdcEc5CFC3eC1c</code></td></tr></tbody></table>


---

Page Title: Executor Framework

- Resolved Markdown: https://wormhole.com/docs/ai/pages/protocol-infrastructure-relayers-executor-framework.md
- Canonical (HTML): https://wormhole.com/docs/protocol/infrastructure/relayers/executor-framework/
- Summary: Learn how the Executor framework enables permissionless cross-chain message execution using on-chain contracts and off-chain providers.
- Word Count: 2027; Token Estimate: 3009

# Executor Framework

The Executor is a shared execution framework that delivers Wormhole messages across chains. It standardizes how message execution is requested, quoted, and performed, enabling any service or protocol to execute messages permissionlessly through on-chain contracts.

The Executor framework enables anyone to act as a relayer in a permissionless network that uses a request-and-quote model for message delivery. Instead of relying on a single, centralized relayer service, the Executor framework creates an open marketplace where multiple providers can compete to deliver messages based on signed execution quotes.

At its core, the Executor relies on Wormhole’s existing guarantees: messages are still secured by VAAs and verified by the Guardian network. By decentralizing message execution and supporting both EVM and non-EVM environments, the Executor framework enables developers to integrate Wormhole relaying with broader chain compatibility, without deploying or maintaining their own relayers.

## Architecture and Components

The Executor framework separates responsibilities between three independent participants:

| Actor	            | Responsibility                                                              | 
|-------------------|-----------------------------------------------------------------------------| 
| Integrator        | Creates and submits execution requests using valid quotes.                  | 
| Executor Contract | Publishes requests, transfers payment, and emits observable events.         | 
| Relay Provider	| Monitors events, issues and validates signed quotes, and executes messages. | 

This modular structure enables permissionless, verifiable, and cost-efficient message execution across multiple blockchains — without persistent on-chain state or protocol-specific relayers.

The Executor framework comprises a small set of on-chain and off-chain components that work together to request, quote, and execute cross-chain messages. The following components define the roles, interfaces, and data structures involved in the execution process.

- **Relay Provider**: An off-chain party responsible for performing message execution between chains. 
- **[Executor contract](/docs/products/reference/executor-addresses/){target=\_blank}**: The shared on-chain contract or program used to make execution requests. 
- **Execution quote**: A signed quote defining cost and parameters for execution between a source and destination chain. 
- **Execution request**: A request generated on-chain or off-chain for a given message (e.g., NTT, VAA v1, etc.) to be executed on another chain. 
- **Quoter**: An off-chain service that produces signed quotes. It's Quoter’s EVM public key that identifies each Relay Provider.
- **Payee**: The wallet address designated by the Quoter to receive payment once the execution is completed. 

## Execution Lifecycle

The execution lifecycle defines the sequence of interactions between integrators, the Executor contract, and Relay Providers that result in a cross-chain message being executed on the destination chain.

### Request Flow

Message execution starts on the source chain, where an integrator creates an execution request. The request includes a signed quote from a Quoter, along with message data and delivery instructions.

1. A client requests a quote from a Quoter, specifying source and destination chains.  
2. The Quoter returns a signed quote with pricing and parameters.  
3. The client sends a message through an integrator contract, including the signed quote.  
4. The integrator publishes the message via the [Wormhole Core contract](/docs/protocol/infrastructure/core-contracts/){target=\_blank}.  
5. The integrator then calls the Executor contract to register the execution request.

```mermaid
---
title: v1 VAA Execution Request
---
sequenceDiagram
		participant C as Client
		participant Q as Quoter
		box Source Chain
		participant I as Integrator Contract
		participant W as Wormhole Core
		participant E as Executor Contract
		end
    C->>Q: srcChain, dstChain
    Q-->>C: signedQuote
    C->>I: sendMessage(signedQuote, relayInstructions)
    I->>W: publishMessage
    W-->>I: sequence
    I->>E: requestExecution
```

### Result Flow

Once the request is recorded on-chain, off-chain Relay Providers monitor the Executor contract for events that match their signed quotes. When a valid request is detected, the provider retrieves the message from the Guardians and executes it on the destination chain.

1. The Executor contract emits an event with the request and payment details.
2. A Relay Provider verifies the quote and fetches the associated message (e.g., a VAA).
3. The provider delivers the message to the destination chain’s integrator contract.
4. The integrator verifies the message with the Wormhole Core contract and performs the specified logic.

```mermaid
---
title: v1 VAA Execution Result
---
sequenceDiagram
		box Source Chain
		participant EC as Executor Contract
		end
		participant RP as Relay Provider (Off-Chain)
		box Destination Chain
		participant I as Integrator Contract
		participant W as Wormhole Core
		end
		EC-->>RP: event
    RP->>I: executeVaaV1
    I->>W: parseAndVerifyVM
```

## On-Chain Quote Resolution

While the default execution flow relies on off-chain signed quotes, the Executor framework also supports fully on-chain execution pricing. This mechanism is designed for integrators who cannot modify their off-chain flow or must rely strictly on on-chain state to determine pricing. Instead of passing a signed quote to the Executor contract, the integrator specifies a Quoter public key, and the quote is constructed on-chain through a routing contract.

On-chain quote resolution is appropriate when:

- The integrator must follow a view → payable contract pattern.
- Execution pricing must be deterministically derived from on-chain logic.
- The integration comprises protocols that cannot pass arbitrary off-chain signatures.

For most SDK-based integrations, off-chain signed quotes remain the recommended and more efficient approach.

```mermaid
---
title: On-Chain Quote Resolution (EQ02)
---
sequenceDiagram
    actor Client
    participant I as Integrator
    participant R as ExecutorQuoterRouter
    participant Q as ExecutorQuoter
    participant E as Executor

    Client->>I: quote(...)
    I->>R: quoteExecution(quoterAddr,...)
    R->>Q: requestQuote(...)
    Q-->>R: requiredPayment
    R-->>I: requiredPayment

    Client->>I: execute{value}(...)
    I->>R: requestExecution(quoterAddr,...)
    R->>Q: requestExecutionQuote(...)
    Q-->>R: payee, quoteBody
    R->>E: requestExecution(EQ02)
```

On EVM chains, on-chain quoting introduces two additional contracts:

- `ExecutorQuoter`: Implements the pricing logic for a specific Relay Provider.
- `ExecutorQuoterRouter`: Acts as the canonical entrypoint for integrators requesting on-chain quotes.

The [Quoter public key](/docs/products/reference/executor-addresses/#on-chain-quoter){target=\_blank} identifies a Relay Provider and is used to select which provider’s pricing logic will be applied during execution. This allows multiple providers to register independent pricing logic, permissionless participation, and on-chain formation of execution quotes without requiring signatures.

The Router constructs an unsigned `EQ02` quote on-chain and forwards the execution request to the Executor contract. `EQ02` contains the same pricing fields as the signed `EQ01` quote. Still, it is constructed on-chain, it does not contain a signature, and Relay Providers verify it by checking for an `OnChainQuote` event emitted by the canonical Router. This preserves compatibility with existing Executor tooling and off-chain validation logic.

Most applications do not need to interact directly with `ExecutorQuoter`, `ExecutorQuoterRouter`, or `EQ02` formatting. The Wormhole SDK abstracts quote resolution, relay instruction formatting, execution request construction, and payment handling. Unless building a low-level contract integration, developers should rely on the SDK to manage quote construction and execution flows.

### Quoter Governance

Relay Providers register their `ExecutorQuoter` implementation through a signed governance message submitted to the `ExecutorQuoterRouter`.

The governance message:

- Associates a Quoter public key with a specific implementation contract
- Includes an expiry to prevent replay
- Is validated by the `ExecutorQuoterRouter`

This ensures that providers can update pricing logic, the Router remains immutable and permissionless, and off-chain infrastructure can verify that a quote originated from the canonical Router.

## Executor Contract

Each supported chain hosts a stateless, permissionless [Executor contract](/docs/products/reference/executor-addresses/){target=\_blank}. The contract provides an interface for submitting execution requests and emitting observable events for off-chain providers. It maintains no persistent state; all requests exist as events that off-chain agents can detect.

When called, the Executor contract:

- Accepts execution requests from integrators or clients.
- Verifies basic parameters (source/destination chain IDs, expiry time).
- Transfers payment to the designated [`payeeAddress`](https://github.com/wormholelabs-xyz/example-messaging-executor/blob/main/evm/src/Executor.sol#L59){target=\_blank}.
- Emits events containing request details for off-chain consumption. 

The Executor contract exposes the [`requestExecution`](https://github.com/wormholelabs-xyz/example-messaging-executor/blob/main/evm/src/Executor.sol#L22){target=\_blank} function, used by both on-chain and off-chain integrations to create an execution request. When `requestExecution` is called, the contract checks that:

- The quote’s source chain matches the chain of deployment.
- The destination matches the provided destination chain.
- The quote has not expired.

If all checks pass, payment is transferred to the [`payeeAddress`](https://github.com/wormholelabs-xyz/example-messaging-executor/blob/main/evm/src/Executor.sol#L59){target=\_blank} defined in the quote, and a [`RequestForExecution`](https://github.com/wormholelabs-xyz/example-messaging-executor/blob/main/evm/src/Executor.sol#L61){target=\_blank} event is emitted.

To remain lightweight and chain-agnostic, the Executor contract performs only minimal validation:

- **No signature verification**: The client is responsible for verifying the quote before submission.
- **No message inspection**: The contract does not parse or validate the message payload.
- **No payment enforcement**: The contract does not check that the payment matches the quoted fee; providers enforce this off-chain.

This minimal design keeps the contract generic, inexpensive, and compatible with multiple message formats and future Wormhole protocols.

## Relay Provider

A Relay Provider is an off-chain service that executes messages between chains and operates a Quoter service to issue signed execution quotes. Providers compete in a permissionless marketplace by offering signed execution quotes that define their pricing and delivery terms. This system decentralizes message delivery, allowing integrators to choose providers or run their own, rather than relying on a single relayer service. 

Each provider runs infrastructure that listens for execution requests emitted by the Executor contract on supported chains. When a request matches one of their quotes, the provider retrieves the associated VAA from the Guardians and performs the message execution on the destination chain.  

Each Relay Provider operates a Quoter service that issues signed quotes and defines execution terms. 

Each quote specifies: 

- The source and destination chains
- Pricing
- An expiry time before which the Executor contract can accept the quote

Short expiry windows reduce the risk of stale quotes but must be long enough for users to submit transactions on the source chain. 

Because the network is open, multiple providers may compete to fulfill the same request. Each quote defines the conditions under which a provider is willing to execute, enabling competitive pricing and redundancy across the system. Message validity is enforced through the Wormhole VAA and Guardian verification process, preventing providers from altering or forging the message and ensuring all executions remain trust-minimized.

Relay Providers may operate multiple wallets, each capable of performing execution or receiving payment. They can choose whether payments are collected per-wallet or directed to a central [`payeeAddress`](https://github.com/wormholelabs-xyz/example-messaging-executor/blob/main/evm/src/Executor.sol#L59){target=\_blank} defined by the Quoter.

Providers should provide a public API for integrators to track the status of the request such as: 

- Request creation
- Added gas fees
- Transaction executes
- Any issued refunds

To improve transparency, providers may also publish a Service-Level Agreement (SLA) describing the types of executions they support, their retry and refund policies, and their expected behavior during execution.

!!!warning
    The framework does not prevent repeated execution attempts. Providers should implement their own safeguards to avoid duplicate deliveries.

## Security Considerations

The Executor contract is explicitly designed to be immutable and sit outside an integrator's security stack. Executor is intended to be used as a mechanism to permissionlessly deliver cross-chain data that includes an independent attestation source, such as Wormhole VAAs. The Executor does not change Wormhole’s security model; it changes how delivery requests are initiated and fulfilled.

## Resources

- [demo-hello-executor](https://github.com/wormhole-foundation/demo-hello-executor){target=\_blank} — Minimal end-to-end example demonstrating quote requests and `requestExecution` flows.
- [Executor Addresses Reference](/docs/products/reference/executor-addresses/){target=\_blank} — Deployed Executor contracts, On-chain Quoter contracts, Wormhole Labs’ Quoter implementations, and published Quoter public keys.

## Next Steps

<div class="grid cards" markdown>

-   :octicons-book-16:{ .lg .middle } **Migrate to Executor**

    ---

    Understand the key differences between the Executor framework and the Standard Relayer, and find guidance for migrating existing integrations.

    [:custom-arrow: Migrate to Executor](/docs/protocol/infrastructure/relayers/executor-vs-sr/)

-   :octicons-tools-16:{ .lg .middle } **Executor Demo**

    ---

    Check out a minimal end-to-end Executor demo showing quoting, request calls, and replay protection.

    [:custom-arrow: See the Hello Executor Demo](https://github.com/wormhole-foundation/demo-hello-executor){target=\_blank}

</div>


---

Page Title: Features

- Resolved Markdown: https://wormhole.com/docs/ai/pages/products-connect-reference-support-matrix.md
- Canonical (HTML): https://wormhole.com/docs/products/connect/reference/support-matrix/
- Summary: Explore a comprehensive Feature Support matrix and explain Wormhole's capabilities across networks for WTT, CCTP, ETH Bridge, and more.
- Word Count: 509; Token Estimate: 1081

## Feature Support Matrix {: #feature-support-matrix}

*Scroll down for details about each column.*

| **Network** | **WTT**          | **WTT Relayer**          | **Circle CCTP** | **ETH Bridge** | **Gas Drop Off** |
|:-----------:|:----------------:|:------------------------:|:---------------:|:--------------:|:----------------:|
|   Solana    |        ✅         |            ✅             |        ✅        |       ❌        |        ✅         |
|  Ethereum   |        ✅         |            ✅             |        ✅        |       ✅        |        ✅         |
|     BSC     |        ✅         |            ✅             |        ❌        |       ✅        |        ✅         |
|   Polygon   |        ✅         |            ✅             |        ✅        |       ✅        |        ✅         |
|  Avalanche  |        ✅         |            ✅             |        ✅        |       ✅        |        ✅         |
|   Fantom    |        ✅         |            ✅             |        ❌        |       ❌        |        ✅         |
|    Kaia     |        ✅         |            ❌             |        ❌        |       ❌        |        ❌         |
|    Celo     |        ✅         |            ✅             |        ❌        |       ❌        |        ✅         |
|  Moonbeam   |        ✅         |            ✅             |        ❌        |       ❌        |        ✅         |
|  Injective  |        ✅         |            ❌             |        ❌        |       ❌        |        ❌         |
|     Sui     |        ✅         |            ✅             |        ✅        |       ❌        |        ✅         |
|    Aptos    |        ✅         |            ❌             |        ✅        |       ❌        |        ❌         |
|  Arbitrum   |        ✅         |            ✅             |        ✅        |       ✅        |        ✅         |
|  Optimism   |        ✅         |            ✅             |        ✅        |       ✅        |        ✅         |
|    Base     |        ✅         |            ✅             |        ✅        |       ✅        |        ✅         |
|     Sei     |        ✅         |            ❌             |        ❌        |       ❌        |        ❌         |
|   Scroll    |        ✅         |            ❌             |        ❌        |       ❌        |        ❌         |
|    Blast    |        ✅         |            ❌             |        ❌        |       ❌        |        ❌         |
|   X Layer   |        ✅         |            ❌             |        ❌        |       ❌        |        ❌         |

!!! note "Terminology" 
    The SDK and smart contracts use the name Token Bridge. In documentation, this product is referred to as Wrapped Token Transfers (WTT). Both terms describe the same protocol.

## Feature Explanation {: #feature-explanation}

### Wrapped Token Transfers (WTT) {: #wrapped-token-transfers}

Wormhole is best known for its WTT transfer method. It locks assets on the source chain and mints Wormhole-wrapped "IOU" tokens on the destination chain. To transfer the assets back, the Wormhole-wrapped tokens are burned, unlocking the tokens on their original chain.

This route appears if both of the following conditions are satisfied:

 - Both the origin and destination chains support WTT.
 - No non-WTT routes are available for the selected token.

### WTT Relayer {: #wtt-relayer}

On the [routes](/docs/products/connect/concepts/routes/){target=\_blank} page, this is referred to as the automatic route in the WTT section.

Trustless relayers can execute the second transaction on behalf of the user, so the user only needs to perform one transaction on the origin chain to have the tokens delivered to the destination automatically—for a small fee.

This route appears if all of the following conditions are satisfied:

- Both the origin and destination chains support WTT.
- Both the origin and destination chains support WTT relayer.
- No non-WTT routes are available for the selected token.
- The relayer supports the selected token on the origin chain.

### Circle CCTP {: #circle-cctp}

[Circle](https://www.circle.com/){target=\_blank}, the issuer of USDC, provides a native way for native USDC to be transferred between [CCTP-enabled](https://www.circle.com/cross-chain-transfer-protocol){target=\_blank} chains.

This route appears if all of the following conditions are satisfied:

- Both the origin and destination chains support Circle CCTP.
- The selected token is native Circle-issued USDC.

### ETH Bridge {: #eth-bridge}

[Powered by Uniswap liquidity pools](https://github.com/wormhole-foundation/example-uniswap-liquidity-layer){target=\_blank}, this route can transfer native ETH or wstETH between certain EVMs without going through the native bridges.

This route appears if all of the following conditions are satisfied:

- Both the origin and destination chains support the ETH Bridge.
- The selected token is native ETH, wstETH, or canonical wETH.

### Gas Drop Off {: #gas-drop-off}

A relayer can drop off some gas tokens on the destination chain by swapping some of the assets transferred to the native gas token. This is useful if the user wishes to transfer assets to a chain where they don't already have gas. This way, they don't need to onboard into the ecosystem from a centralized exchange.

This route appears if all of the following conditions are satisfied:

- Both the origin and destination chains support gas drop off.
- An automatic route is selected.
- The relayer accepts the selected token to swap into the gas token.


---

Page Title: Get Started with Connect

- Resolved Markdown: https://wormhole.com/docs/ai/pages/products-connect-get-started.md
- Canonical (HTML): https://wormhole.com/docs/products/connect/get-started/
- Summary: Follow this guide to configure and use the Connect UI widget to easily add an intuitive, multichain asset transfer UI to your web applications.
- Word Count: 616; Token Estimate: 1119

# Get Started with Connect

:simple-github: [Source code on GitHub](https://github.com/wormhole-foundation/demo-basic-connect){target=\_blank}

Connect helps you to easily add an intuitive, multichain asset transfer UI to your web applications. The guide demonstrates how to configure the Connect widget, add it to a React application, and view it locally.

## Install Connect

To install the [Wormhole Connect npm package](https://www.npmjs.com/package/@wormhole-foundation/wormhole-connect){target=\_blank}, run the following command:

```bash
npm i @wormhole-foundation/wormhole-connect
```

## Prerequisites

Before you begin, make sure you have the following:

- [Node.js and npm](https://docs.npmjs.com/downloading-and-installing-node-js-and-npm){target=\_blank}.

- (Optional) To test a transfer from your demo app, you'll need:

    - A wallet with [Sui testnet tokens](https://faucet.sui.io/){target=\_blank}.
    - A wallet with an Avalanche Fuji address (to use as the recipient; no tokens required).

## Install and Set Up Project

1. Clone the demo repository and navigate to the project directory:

    ```bash
    git clone https://github.com/wormhole-foundation/demo-basic-connect.git
    cd demo-basic-connect
    ```

2. Install the dependencies. This example uses the Connect version `5.1.1`:

    ```bash
    npm install
    ```

3. Start the application:

    ```bash
    npm start
    ```

4. Open your browser to `http://localhost:3000` to view the application locally.

    ![Deployed Connect Widget](/docs/images/products/connect/tutorials/react-dapp/get-started/connect-get-started-01.webp)

## Configure Connect

Open the `App.tsx` file in your code editor of choice. You will see code similar to the following:

```typescript title="App.tsx"
import './App.css';
import WormholeConnect, { type config, WormholeConnectTheme } from '@wormhole-foundation/wormhole-connect';

function App() {
  const config: config.WormholeConnectConfig = {
    // Define the network
    network: 'Testnet',

    // Define the chains
    chains: ['Sui', 'Avalanche'],

    // UI configuration
    ui: {
      title: 'SUI Connect TS Demo',
    },
  };

  const theme: WormholeConnectTheme = {
    // Define the theme
    mode: 'dark',
    primary: '#78c4b6',
  };

  return <WormholeConnect config={config} theme={theme} />;
}

export default App;
```

The preceding sample code configures Connect by setting values inside `config` and `theme` as follows:

- **Defines the network**: Options include `Mainnet`, `Testnet`, or `Devnet`.
- **Defines chains to include**: This example uses Sui and Avalanche. See the complete list of [Connect-supported chain names](https://github.com/wormhole-foundation/wormhole-sdk-ts/blob/main/core/base/src/constants/chains.ts){target=\_blank} if you would like to use different chains.
- **Adds a title to UI**: (Optional) If defined, it will render above the widget in the UI.
- **Defines the theme**: This example sets the mode to `dark` and adds a primary color.

## Interact with Connect

Congratulations! You've successfully used Connect to create a simple multichain token transfer application. You can now follow the prompts in the UI to connect your developer wallets and send a test transfer.

## Next Steps

Use the following guides to configure your Connect instance and integrate it into your application.

<div class="grid cards" markdown>

-   :octicons-tools-16:{ .lg .middle } **Data Configuration**

    ---

    Learn how to specify custom networks and RPC endpoints, integrate different bridging protocols, add new tokens, and more.

    [:custom-arrow: View Data Configs](/docs/products/connect/configuration/data/)

-   :octicons-tools-16:{ .lg .middle } **Theme Configuration**

    ---

    Learn how to customize Connect's look and feel to match your application's branding.

    [:custom-arrow: View Theme Configs](/docs/products/connect/configuration/theme/)

-   :octicons-book-16:{ .lg .middle } **Integrate Connect into a React DApp**

    ---

    Learn how to integrate Connect into a React application, including setting up the widget and handling transfers.

    [:custom-arrow: Get Started](/docs/products/connect/tutorials/react-dapp/)

-   :octicons-tools-16:{ .lg .middle } **Wormhole Dev Arena**

    ---

    A structured learning hub with hands-on tutorials across the Wormhole ecosystem.

    [:custom-arrow: Explore the Dev Arena](https://arena.wormhole.com/){target=\_blank}

</div>


---

Page Title: Get Started with Core Contracts

- Resolved Markdown: https://wormhole.com/docs/ai/pages/products-messaging-guides-core-contracts.md
- Canonical (HTML): https://wormhole.com/docs/products/messaging/guides/core-contracts/
- Summary: This guide walks through the key methods of the Core Contracts, providing you with the knowledge needed to integrate them into your cross-chain contracts
- Word Count: 1931; Token Estimate: 3428

# Get Started with Core Contracts

Wormhole's Core Contracts, deployed on each supported blockchain network, enable the fundamental operations of sending and receiving cross-chain messages.

While the implementation details of the Core Contracts varies by network, the core functionality remains consistent across chains. Each version of the Core Contract facilitates secure and reliable cross-chain communication, ensuring that developers can effectively publish and verify messages.

This guide will walk you through the variations and key methods of the Core Contracts, providing you with the knowledge needed to integrate them into your cross-chain contracts. To learn more about Core Contracts' features and how it works, please refer to the [Core Contracts](/docs/protocol/infrastructure/core-contracts/){target=\_blank} page in the Learn section.

## Prerequisites

To interact with the Wormhole Core Contract, you'll need the following:

- The [address of the Core Contract](/docs/products/reference/contract-addresses/#core-contracts){target=\_blank} on the chains you're deploying your contract on.
- The [Wormhole chain ID](/docs/products/reference/chain-ids/){target=\_blank} of the chains you're deploying your contract on.
- The [Wormhole Finality](/docs/products/reference/consistency-levels/){target=\_blank} (consistency) levels (required finality) for the chains you're deploying your contract on.

## How to Interact with Core Contracts

Before writing your own contracts, it's essential to understand the key functions and events of the Wormhole Core Contracts. The primary functionality revolves around:

- **Sending messages**: Submitting messages to the Wormhole network for cross-chain communication.
- **Receiving and verifying messages**: Validating messages received from other chains via the Wormhole network.

While the implementation details of the Core Contracts vary by network, the core functionality remains consistent across chains.

### Sending Messages

To send a message, regardless of the environment or chain, the Core Contract is invoked with a message argument from an [emitter](/docs/products/reference/glossary/#emitter){target=\_blank}. This emitter might be your contract or an existing application such as the [Wrapped Token Transfers (WTT)](/docs/products/token-transfers/wrapped-token-transfers/overview/){target=\_blank}.

=== "EVM"

    The `IWormhole.sol` interface provides the `publishMessage` function, which can be used to publish a message directly to the Core Contract:

    ```solidity
    function publishMessage(
        uint32 nonce,
        bytes memory payload,
        uint8 consistencyLevel
    ) external payable returns (uint64 sequence);
    ```

    ??? interface "Parameters"

        `nonce` ++"uint32"++
        
        A free integer field that can be used however you like. Note that changing the `nonce` will result in a different digest.

        ---

        `payload` ++"bytes memory"++
        
        The content of the emitted message. Due to the constraints of individual blockchains, it may be capped to a certain maximum length.

        ---

        `consistencyLevel` ++"uint8"++
        
        A value that defines the required level of finality that must be reached before the Guardians will observe and attest to emitted events.

    ??? interface "Returns"

        `sequence` ++"uint64"++
        
        A unique number that increments for every message for a given emitter (and implicitly chain). This, combined with the emitter address and emitter chain ID, allows the VAA for this message to be queried from the [Wormholescan API](https://docs.wormholescan.io/){target=\_blank}.
    
    ??? interface "Example"

        ```solidity
        IWormhole wormhole = IWormhole(wormholeAddr);

        // Get the fee for publishing a message
        uint256 wormholeFee = wormhole.messageFee();

        // Check fee and send parameters

        // Create the HelloWorldMessage struct
        HelloWorldMessage memory parsedMessage = HelloWorldMessage({
            payloadID: uint8(1),
            message: helloWorldMessage
        });

        // Encode the HelloWorldMessage struct into bytes
        bytes memory encodedMessage = encodeMessage(parsedMessage);

        // Send the HelloWorld message by calling publishMessage on the
        // wormhole core contract and paying the Wormhole protocol fee.
        messageSequence = wormhole.publishMessage{value: wormholeFee}(
            0, // batchID
            encodedMessage,
            wormholeFinality()
        );
        ```

        View the complete Hello World example in the [Wormhole Scaffolding](https://github.com/wormhole-foundation/wormhole-scaffolding/tree/main/evm/src/01_hello_world){target=\_blank} repository on GitHub.

=== "Solana"

    The `wormhole_anchor_sdk::wormhole` module and the Wormhole program account can be used to pass a message directly to the Core Contract via the `wormhole::post_message` function:

    ```rs
    pub fn post_message<'info>(
        ctx: CpiContext<'_, '_, '_, 'info, PostMessage<'info>>,
        batch_id: u32,
        payload: Vec<u8>,
        finality: Finality
    ) -> Result<()>
    ```

    ??? interface "Parameters"

        `ctx` ++"CpiContext<'_, '_, '_, 'info, PostMessage<'info>>"++ 
        
        Provides the necessary context for executing the function, including the accounts and program information required for the Cross-Program Invocation (CPI).

        ??? child "Type `pub struct CpiContext<'a, 'b, 'c, 'info, T>`"

            ```rs
            pub struct CpiContext<'a, 'b, 'c, 'info, T>
            where
                T: ToAccountMetas + ToAccountInfos<'info>,
            {
                pub accounts: T,
                pub remaining_accounts: Vec<AccountInfo<'info>>,
                pub program: AccountInfo<'info>,
                pub signer_seeds: &'a [&'b [&'c [u8]]],
            }
            ```

            For more information, please refer to the [`wormhole_anchor_sdk` Rust docs](https://docs.rs/anchor-lang/0.29.0/anchor_lang/context/struct.CpiContext.html){target=\_blank}.

        ??? child "Type `PostMessage<'info>`"

            ```rs
            pub struct PostMessage<'info> {
                pub config: AccountInfo<'info>,
                pub message: AccountInfo<'info>,
                pub emitter: AccountInfo<'info>,
                pub sequence: AccountInfo<'info>,
                pub payer: AccountInfo<'info>,
                pub fee_collector: AccountInfo<'info>,
                pub clock: AccountInfo<'info>,
                pub rent: AccountInfo<'info>,
                pub system_program: AccountInfo<'info>,
            }
            ```

            For more information, please refer to the [`wormhole_anchor_sdk` Rust docs](https://docs.rs/wormhole-anchor-sdk/latest/wormhole_anchor_sdk/wormhole/instructions/struct.PostMessage.html){target=\_blank}.

        ---

        `batch_id` ++"u32"++
        
        An identifier for the message batch.

        ---

        `payload` ++"Vec<u8>"++
        
        The data being sent in the message. This is a variable-length byte array that contains the actual content or information being transmitted. To learn about the different types of payloads, check out the [VAAs](/docs/protocol/infrastructure/vaas#payload-types){target=\_blank} page.

        ---

        `finality` ++"Finality"++
        
        Specifies the level of finality or confirmation required for the message.
        
        ??? child "Type `Finality`"

            ```rs
            pub enum Finality {
                Confirmed,
                Finalized,
            }
            ```
    
    ??? interface "Returns"

        ++"Result<()>"++
        
        The result of the function’s execution. If the function completes successfully, it returns `Ok(())`, otherwise it returns `Err(E)`, indicating that an error occurred along with the details about the error
    
    ??? interface "Example"

        ```rust
        let fee = ctx.accounts.wormhole_bridge.fee();
        // ... Check fee and send parameters

        let config = &ctx.accounts.config;
        let payload: Vec<u8> = HelloWorldMessage::Hello { message }.try_to_vec()?;

        // Invoke `wormhole::post_message`.
        wormhole::post_message(
            CpiContext::new_with_signer(
                ctx.accounts.wormhole_program.to_account_info(),
                wormhole::PostMessage {
                    // ... Set fields
                },
                &[
                    // ... Set seeds
                ],
            ),
            config.batch_id,
            payload,
            config.finality.into(),
        )?;
        ```

        View the complete Hello World example in the [Wormhole Scaffolding](https://github.com/wormhole-foundation/wormhole-scaffolding/tree/main/solana/programs/01_hello_world){target=\_blank} repository on GitHub.

Once the message is emitted from the Core Contract, the [Guardian Network](/docs/protocol/infrastructure/guardians/){target=\_blank} will observe the message and sign the digest of an Attestation [VAA](/docs/protocol/infrastructure/vaas/){target=\_blank}. On EVM chains, the body of the VAA is hashed twice with keccak256 to produce the signed digest message. On Solana, the [Solana secp256k1 program](https://solana.com/docs/core/programs#secp256k1-program){target=\_blank} will hash the message passed. In this case, the argument for the message should be a single hash of the body, not the twice-hashed body.

VAAs are [multicast](/docs/protocol/infrastructure/core-contracts/#multicast){target=\_blank} by default. This means there is no default target chain for a given message. The application developer decides on the format of the message and its treatment upon receipt.

### Receiving Messages

The way a message is received and handled depends on the environment.

=== "EVM"

    On EVM chains, the message passed is the raw VAA encoded as binary. The `IWormhole.sol` interface provides the `parseAndVerifyVM` function, which can be used to parse and verify the received message.

    ```solidity
    function parseAndVerifyVM(
        bytes calldata encodedVM
    ) external view returns (VM memory vm, bool valid, string memory reason);
    ```

    ??? interface "Parameters"

        `encodedVM` ++"bytes calldata"++
        
        The encoded message as a Verified Action Approval (VAA), which contains all necessary information for verification and processing.

    ??? interface "Returns"

        `vm` ++"VM memory"++
        
        The valid parsed VAA, which will include the original `emitterAddress`, `sequenceNumber`, and `consistencyLevel`, among other fields outlined on the [VAAs](/docs/protocol/infrastructure/vaas/) page.

        ??? child "Struct `VM`"

            ```solidity
            struct VM {
                uint8 version;
                uint32 timestamp;
                uint32 nonce;
                uint16 emitterChainId;
                bytes32 emitterAddress;
                uint64 sequence;
                uint8 consistencyLevel;
                bytes payload;
                uint32 guardianSetIndex;
                Signature[] signatures;
                bytes32 hash;
            }
            ```

            For more information, refer to the [`IWormhole.sol` interface](https://github.com/wormhole-foundation/wormhole/blob/main/ethereum/contracts/interfaces/IWormhole.sol){target=\_blank}.

        ---
        
        `valid` ++"bool"++
        
        A boolean indicating whether the VAA is valid or not.
        
        ---

        `reason` ++"string"++
        
        If the VAA is not valid, a reason will be provided

    ??? interface "Example"

        ```solidity
        function receiveMessage(bytes memory encodedMessage) public {
            // Call the Wormhole core contract to parse and verify the encodedMessage
            (
                IWormhole.VM memory wormholeMessage,
                bool valid,
                string memory reason
            ) = wormhole().parseAndVerifyVM(encodedMessage);

            // Perform safety checks here

            // Decode the message payload into the HelloWorldMessage struct
            HelloWorldMessage memory parsedMessage = decodeMessage(
                wormholeMessage.payload
            );

            // Your custom application logic here
        }
        ```

        View the complete Hello World example in the [Wormhole Scaffolding](https://github.com/wormhole-foundation/wormhole-scaffolding/tree/main/evm/src/01_hello_world){target=\_blank} repository on GitHub.

=== "Solana"

    On Solana, the VAA is first posted and verified by the Core Contract, after which it can be read by the receiving contract and action taken.

    Retrieve the raw message data:

    ```rs
    let posted_message = &ctx.accounts.posted;
    posted_message.data()
    ```

    ??? interface "Example"

        ```rust
        pub fn receive_message(ctx: Context<ReceiveMessage>, vaa_hash: [u8; 32]) -> Result<()> {
            let posted_message = &ctx.accounts.posted;

            if let HelloWorldMessage::Hello { message } = posted_message.data() {
                // Check message
                // Your custom application logic here
                Ok(())
            } else {
                Err(HelloWorldError::InvalidMessage.into())
            }
        }
        ```

        View the complete Hello World example in the [Wormhole Scaffolding](https://github.com/wormhole-foundation/wormhole-scaffolding/tree/main/solana/programs/01_hello_world){target=\_blank} repository on GitHub.

#### Validating the Emitter

When processing cross-chain messages, it's critical to ensure that the message originates from a trusted sender (emitter). This can be done by verifying the emitter address and chain ID in the parsed VAA.

Typically, contracts should provide a method to register trusted emitters and check incoming messages against this list before processing them. For example, the following check ensures that the emitter is registered and authorized:

```solidity
require(isRegisteredSender(emitterChainId, emitterAddress), "Invalid emitter");
```

This check can be applied after the VAA is parsed, ensuring only authorized senders can interact with the receiving contract. Trusted emitters can be registered using a method like `setRegisteredSender` during contract deployment or initialization.

```typescript
const tx = await receiverContract.setRegisteredSender(
  sourceChain.chainId,
  ethers.zeroPadValue(senderAddress as BytesLike, 32)
);

await tx.wait();
```

#### Additional Checks

In addition to environment-specific checks that should be performed, a contract should take care to check other [fields in the body](/docs/protocol/infrastructure/vaas/){target=\_blank}, including:

- **Sequence**: Is this the expected sequence number? How should out-of-order deliveries be handled?
- **Consistency level**: For the chain this message came from, is the [Wormhole Finality](/docs/products/reference/consistency-levels/){target=\_blank} level enough to guarantee the transaction won't be reverted after taking some action?

The VAA digest is separate from the VAA body but is also relevant. It can be used for replay protection by checking if the digest has already been seen. Since the payload itself is application-specific, there may be other elements to check to ensure safety.

## Source Code References

For a deeper understanding of the Core Contract implementation for a specific blockchain environment and to review the actual source code, please refer to the following links:

- [Algorand Core Contract source code](https://github.com/wormhole-foundation/wormhole/blob/main/algorand/wormhole_core.py){target=\_blank}
- [Aptos Core Contract source code](https://github.com/wormhole-foundation/wormhole/tree/main/aptos/wormhole){target=\_blank}
- [EVM Core Contract source code](https://github.com/wormhole-foundation/wormhole/tree/main/ethereum/contracts){target=\_blank} ([`IWormhole.sol` interface](https://github.com/wormhole-foundation/wormhole/blob/main/ethereum/contracts/interfaces/IWormhole.sol){target=\_blank})
- [NEAR Core Contract source code](https://github.com/wormhole-foundation/wormhole/tree/main/near/contracts/wormhole){target=\_blank}
- [Solana Core Contract source code](https://github.com/wormhole-foundation/wormhole/tree/main/solana/bridge/program){target=\_blank}
- [Sui Core Contract source code](https://github.com/wormhole-foundation/wormhole/tree/main/sui/wormhole){target=\_blank}


---

Page Title: Get Started with Messaging

- Resolved Markdown: https://wormhole.com/docs/ai/pages/products-messaging-get-started.md
- Canonical (HTML): https://wormhole.com/docs/products/messaging/get-started/
- Summary: Follow this guide to use Wormhole's core protocol to publish a multichain message and return transaction information with VAA identifiers.
- Word Count: 1288; Token Estimate: 2574

# Get Started with Messaging

Wormhole's core functionality allows you to send any data packet from one supported chain to another. This guide demonstrates how to publish your first simple, arbitrary data message from an EVM environment source chain using the Wormhole TypeScript SDK's core messaging capabilities. 

## Prerequisites

Before you begin, ensure you have the following:

- [Node.js and npm](https://docs.npmjs.com/downloading-and-installing-node-js-and-npm){target=\_blank} installed.
- [TypeScript](https://www.typescriptlang.org/download/){target=\_blank} installed.
- [Ethers.js](https://docs.ethers.org/v6/getting-started/){target=\_blank} installed (this example uses version 6).
- A small amount of testnet tokens for gas fees. This example uses [Sepolia ETH](https://sepolia-faucet.pk910.de/){target=\_blank} but can be adapted for any supported network.
- A private key for signing blockchain transactions.

## Configure Your Messaging Environment

1. Create a directory and initialize a Node.js project:

    ```bash
    mkdir core-message
    cd core-message
    npm init -y
    ```

2. Install TypeScript, tsx, Node.js type definitions, and Ethers.js:

    ```bash
    npm install --save-dev tsx typescript @types/node ethers
    ```

3. Create a `tsconfig.json` file if you don't have one. You can generate a basic one using the following command:

    ```bash
    npx tsc --init
    ```

    Make sure your `tsconfig.json` includes the following settings:

    ```json 
    {
        "compilerOptions": {
            // es2020 or newer
            "target": "es2020",
            // Use esnext if you configured your package.json with type: "module"
            "module": "commonjs",
            "esModuleInterop": true,
            "forceConsistentCasingInFileNames": true,
            "strict": true,
            "skipLibCheck": true,
            "resolveJsonModule": true
            }
    }
    ```

4. Install the [TypeScript SDK](/docs/tools/typescript-sdk/get-started/){target=\_blank}. This example uses the SDK version `4.14.1`:

    ```bash
    npm install @wormhole-foundation/sdk@4.14.1
    ```

5. Create a new file named `main.ts`:

    ```bash
    touch main.ts
    ```

## Construct and Publish Your Message

1. Open `main.ts` and update the code there as follows:

    ```ts title="main.ts"
    import {
      wormhole,
      signSendWait,
      toNative,
      encoding,
      type Chain,
      type Network,
      type NativeAddress,
      type WormholeMessageId,
      type UnsignedTransaction,
      type TransactionId,
      type WormholeCore,
      type Signer as WormholeSdkSigner,
      type ChainContext,
    } from '@wormhole-foundation/sdk';
    // Platform-specific modules
    import EvmPlatformLoader from '@wormhole-foundation/sdk/evm';
    import { getEvmSigner } from '@wormhole-foundation/sdk-evm';
    import { Wallet, JsonRpcProvider, Signer as EthersSigner } from 'ethers';

    /**
     * The required value (SEPOLIA_PRIVATE_KEY) must
     * be loaded securely beforehand, for example via a keystore, secrets
     * manager, or environment variables (not recommended).
     */

    const SEPOLIA_PRIVATE_KEY = SEPOLIA_PRIVATE_KEY!;
    // Provide a private endpoint RPC URL for Sepolia, defaults to a public node
    // if not set
    const RPC_URL =
      process.env.SEPOLIA_RPC_URL || 'https://ethereum-sepolia-rpc.publicnode.com';

    async function main() {
      // Initialize Wormhole SDK
      const network = 'Testnet';
      const wh = await wormhole(network, [EvmPlatformLoader]);
      console.log('Wormhole SDK Initialized.');

      // Get the EVM signer and provider
      let ethersJsSigner: EthersSigner;
      let ethersJsProvider: JsonRpcProvider;

      try {
        if (!SEPOLIA_PRIVATE_KEY) {
          console.error('Please set the SEPOLIA_PRIVATE_KEY environment variable.');
          process.exit(1);
        }

        ethersJsProvider = new JsonRpcProvider(RPC_URL);
        const wallet = new Wallet(SEPOLIA_PRIVATE_KEY);
        ethersJsSigner = wallet.connect(ethersJsProvider);
        console.log(
          `Ethers.js Signer obtained for address: ${await ethersJsSigner.getAddress()}`
        );
      } catch (error) {
        console.error('Failed to get Ethers.js signer and provider:', error);
        process.exit(1);
      }

      // Define the source chain context
      const sourceChainName: Chain = 'Sepolia';
      const sourceChainContext = wh.getChain(sourceChainName) as ChainContext<
        'Testnet',
        'Sepolia',
        'Evm'
      >;
      console.log(`Source chain context obtained for: ${sourceChainContext.chain}`);

      // Get the Wormhole SDK signer, which is a wrapper around the Ethers.js
      // signer using the Wormhole SDK's signing and transaction handling
      // capabilities
      let sdkSigner: WormholeSdkSigner<Network, Chain>;
      try {
        sdkSigner = await getEvmSigner(ethersJsProvider, ethersJsSigner);
        console.log(
          `Wormhole SDK Signer obtained for address: ${sdkSigner.address()}`
        );
      } catch (error) {
        console.error('Failed to get Wormhole SDK Signer:', error);
        process.exit(1);
      }

      // Construct your message payload
      const messageText = `HelloWormholeSDK-${Date.now()}`;
      const payload: Uint8Array = encoding.bytes.encode(messageText);
      console.log(`Message to send: "${messageText}"`);

      // Define message parameters
      const messageNonce = Math.floor(Math.random() * 1_000_000_000);
      const consistencyLevel = 1;

      try {
        // Get the core protocol client
        const coreProtocolClient: WormholeCore<Network> =
          await sourceChainContext.getWormholeCore();

        // Generate the unsigned transactions
        const whSignerAddress: NativeAddress<Chain> = toNative(
          sdkSigner.chain(),
          sdkSigner.address()
        );
        console.log(
          `Preparing to publish message from ${whSignerAddress.toString()} on ${
            sourceChainContext.chain
          }...`
        );

        const unsignedTxs: AsyncGenerator<UnsignedTransaction<Network, Chain>> =
          coreProtocolClient.publishMessage(
            whSignerAddress,
            payload,
            messageNonce,
            consistencyLevel
          );

        // Sign and send the transactions
        console.log(
          'Signing and sending the message publication transaction(s)...'
        );
        const txIds: TransactionId[] = await signSendWait(
          sourceChainContext,
          unsignedTxs,
          sdkSigner
        );

        if (!txIds || txIds.length === 0) {
          throw new Error('No transaction IDs were returned from signSendWait.');
        }
        const primaryTxIdObject = txIds[txIds.length - 1];
        const primaryTxid = primaryTxIdObject.txid;

        console.log(`Primary transaction ID for parsing: ${primaryTxid}`);
        console.log(
          `View on Sepolia Etherscan: https://sepolia.etherscan.io/tx/${primaryTxid}`
        );

        console.log(
          '\nWaiting a few seconds for transaction to propagate before parsing...'
        );
        await new Promise((resolve) => setTimeout(resolve, 8000));

        // Retrieve VAA identifiers
        console.log(
          `Attempting to parse VAA identifiers from transaction: ${primaryTxid}...`
        );
        const messageIds: WormholeMessageId[] =
          await sourceChainContext.parseTransaction(primaryTxid);

        if (messageIds && messageIds.length > 0) {
          const wormholeMessageId = messageIds[0];
          console.log('--- VAA Identifiers (WormholeMessageId) ---');
          console.log('  Emitter Chain:', wormholeMessageId.chain);
          console.log('  Emitter Address:', wormholeMessageId.emitter.toString());
          console.log('  Sequence:', wormholeMessageId.sequence.toString());
          console.log('-----------------------------------------');
        } else {
          console.error(
            `Could not parse Wormhole message IDs from transaction ${primaryTxid}.`
          );
        }
      } catch (error) {
        console.error(
          'Error during message publishing or VAA identifier retrieval:',
          error
        );
        if (error instanceof Error && error.stack) {
          console.error('Stack Trace:', error.stack);
        }
      }
    }

    main().catch((e) => {
      console.error('Critical error in main function (outer catch):', e);
      if (e instanceof Error && e.stack) {
        console.error('Stack Trace:', e.stack);
      }
      process.exit(1);
    });
    ```

    This script initializes the SDK, defines values for the source chain, creates an EVM signer, constructs the message, uses the core protocol to generate, sign, and send the transaction, and returns the VAA identifiers upon successful publication of the message.

2. Run the script using the following command:

    ```bash
    npx tsx main.ts
    ```

    You will see terminal output similar to the following:

    <div id="termynal" data-termynal>
      <span data-ty="input"><span class="file-path"></span>npx tsx main.ts</span>
      <span data-ty>Wormhole SDK Initialized.</span>
      <span data-ty>Ethers.js Signer obtained for address: 0xCD8Bcd9A793a7381b3C66C763c3f463f70De4e12</span>
      <span data-ty>Source chain context obtained for: Sepolia</span>
      <span data-ty>Wormhole SDK Signer obtained for address: 0xCD8Bcd9A793a7381b3C66C763c3f463f70De4e12</span>
      <span data-ty>Message to send: "HelloWormholeSDK-1748362375390"</span>
      <span data-ty>Preparing to publish message from 0xCD8Bcd9A793a7381b3C66C763c3f463f70De4e12 on Sepolia...</span>
      <span data-ty>Signing and sending the message publication transaction(s)...</span>
      <span data-ty>Primary Transaction ID for parsing: 0xeb34f35f91c72e4e5198509071d24fd25d8a979aa93e2f168de075e3568e1508</span>
      <span data-ty>View on Sepolia Etherscan: https://sepolia.etherscan.io/tx/0xeb34f35f91c72e4e5198509071d24fd25d8a979aa93e2f168de075e3568e1508</span>
      <span data-ty>Waiting a few seconds for transaction to propagate before parsing...</span>
      <span data-ty>Attempting to parse VAA identifiers from transaction:
        0xeb34f35f91c72e4e5198509071d24fd25d8a979aa93e2f168de075e3568e1508...</span>
      <span data-ty>--- VAA Identifiers (WormholeMessageId) ---</span>
      <span data-ty> Emitter Chain: Sepolia</span>
      <span data-ty> Emitter Address: 0x000000000000000000000000cd8bcd9a793a7381b3c66c763c3f463f70de4e12</span>
      <span data-ty> Sequence: 1</span>
      <span data-ty>-----------------------------------------</span>
      <span data-ty="input"><span class="file-path"></span></span>
    </div>
3. Make a note of the transaction ID and VAA identifier values. You can use the transaction ID to [view the transaction on Wormholescan](https://wormholescan.io/#/tx/0xeb34f35f91c72e4e5198509071d24fd25d8a979aa93e2f168de075e3568e1508?network=Testnet){target=\_blank}. The emitter chain, emitter address, and sequence values are used to retrieve and decode signed messages.

Congratulations! You've published your first multichain message using Wormhole's TypeScript SDK and core protocol functionality. Consider the following options to build upon what you've accomplished. 

## Next Steps

<div class="grid cards" markdown>

-   :octicons-tools-16:{ .lg .middle } **Get Started with WTT**

    ---

    Follow this guide to start working with multichain token transfers using Wormhole Wrapped Token Transfers' lock and mint mechanism to send tokens across chains.

    [:custom-arrow: Get Started](/docs/products/token-transfers/wrapped-token-transfers/get-started/)

-   :octicons-tools-16:{ .lg .middle } **Wormhole Dev Arena**

    ---

    A structured learning hub with hands-on tutorials across the Wormhole ecosystem.

    [:custom-arrow: Explore the Dev Arena](https://arena.wormhole.com/){target=\_blank}

</div>


---

Page Title: Glossary

- Resolved Markdown: https://wormhole.com/docs/ai/pages/products-reference-glossary.md
- Canonical (HTML): https://wormhole.com/docs/products/reference/glossary/
- Summary: Explore a comprehensive glossary of technical terms and key concepts used in the Wormhole network, covering Chain ID, Guardian, VAA, and more.
- Word Count: 654; Token Estimate: 844

# Glossary

This glossary is an index of technical term definitions for words commonly used in Wormhole documentation.

## Chain ID

Wormhole assigns a unique `u16` integer chain ID to each supported blockchain. These chain IDs are specific to Wormhole and may differ from those used by blockchains to identify their networks.

You can find each chain ID documented on the [Wormhole Chain IDs](/docs/products/reference/chain-ids/){target=\_blank} page.

## Consistency Level

The level of finality (consistency) a transaction should meet before being signed by a Guardian. See the [Wormhole Finality](/docs/products/reference/consistency-levels/){target=\_blank} reference page for details.

## Delivery Provider

A Delivery Provider monitors for Executor delivery requests and delivers those requests to the intended target chain as instructed.

## Emitter

The emitter contract makes the call to the Wormhole Core Contract. The published message includes the emitter contract address, and a sequence number is tracked to provide a unique ID.

## Finality

The finality of a transaction depends on its blockchain properties. Once a transaction is considered final, you can assume the resulting state changes it caused will not be reverted.

## Guardian

A [Guardian](/docs/protocol/infrastructure/guardians/){target=\_blank} is one of the 19 parties running validators in the Guardian Network contributing to the VAA multisig.

## Guardian Network

Validators operating in a dedicated P2P network that serve as Wormhole's oracle layer. Guardians monitor on-chain activity and generate signed messages (VAAs) attesting to it.

For full Guardian Set chains, all 19 Guardians perform direct on-chain observation. For delegated chains, a delegated subset monitors and broadcasts signed delegate observations to the rest of the network. Canonical Guardians wait for a delegate quorum before signing. Regardless of the observation path, VAAs are always finalized as standard 13-of-19 multisignature attestations.

## Guardian Set

The Guardian Set is the canonical set of 19 Guardians responsible for producing VAAs. A supermajority of 13 signatures is required to generate a valid VAA.

For certain chains, governance may configure a delegated subset of the Guardian Set to perform direct on-chain observation with a smaller per-chain quorum. Canonical Guardians wait for a delegate quorum before signing, ensuring that the effective security threshold for a chain cannot fall below its configured level.

The composition of the Guardian Set may change through governance actions.

## Delegated Guardian

A Guardian configured to perform direct on-chain observation for a delegated chain. Delegated Guardians broadcast `SignedDelegateObservation` messages to the Guardian gossip network.

In contrast, a Canonical Guardian does not observe that chain directly, it waits for enough `DelegateObservation` messages (the delegate quorum) before contributing its signature to the VAA.

The key distinction: on a delegated chain, Delegated Guardians run full nodes and watch the chain themselves, while Canonical Guardians trust the delegate quorum before signing. The final VAA is still a standard 13-of-19 multisig regardless.

## Heartbeat

Each Guardian will issue a `heartbeat` on a 15-second interval to signal that it is still running and convey details about its identity, uptime, version, and the status of the connected nodes.

You can view the heartbeats on the [Wormhole dashboard](https://wormhole-foundation.github.io/wormhole-dashboard/#/?endpoint=Mainnet){target=\_blank}.

## Observation

An Observation is a data structure describing a message emitted by the Core Contract and noticed by the Guardian node.

## Relayer

A relayer is any process that delivers VAAs to a destination.

## Sequence

A nonce, strictly increasing, which is tracked by the Wormhole Core Contract and unique to the emitter chain and address.

## Spy

A Spy is a daemon that eavesdrops on the messages passed between Guardians, typically to track VAAs as they get signed.

## VAA

[Verifiable Action Approvals](/docs/protocol/infrastructure/vaas/){target=\_blank} (VAAs) are the base data structure in the Wormhole ecosystem. They contain emitted messages along with information such as what contract emitted the message.

## Validator

A daemon configured to monitor a blockchain node and observe messages emitted by the Wormhole contracts.


---

Page Title: Guardians

- Resolved Markdown: https://wormhole.com/docs/ai/pages/protocol-infrastructure-guardians.md
- Canonical (HTML): https://wormhole.com/docs/protocol/infrastructure/guardians/
- Summary: Explore Wormhole's Guardian Network, a decentralized system for secure, scalable cross-chain communication across various blockchain ecosystems.
- Word Count: 1598; Token Estimate: 2170

# Guardians

Wormhole relies on a set of 19 distributed nodes called Guardians that monitor the state on several blockchains. The current Guardian set can be seen in the [Dashboard](https://wormhole-foundation.github.io/wormhole-dashboard/#/?endpoint=Mainnet){target=\_blank}. Depending on the chain's operational configuration, messages may be observed directly by all Guardians or by a delegated subset of Guardians. Regardless of how observations are collected, all [Verifiable Action Approvals](/docs/protocol/infrastructure/vaas/){target=\_blank} (VAAs) are ultimately produced as standard 13-of-19 multisignature attestations, preserving full compatibility with existing contracts and integrators.

Guardians fulfill their role in the messaging protocol as follows:

1. Guardians observe messages and sign the corresponding payloads in isolation from the other Guardians.
    - On chains where all Guardians perform direct on-chain observation, each Guardian independently observes events directly.
    - On delegated chains, a subset performs direct observation and broadcasts a `DelegateObservation` to the rest of the network.
2. Once a sufficient delegate quorum is reached or once Guardians independently observe the event, signatures accumulate until the required 13-of-19 quorum is achieved.
3. This multisig represents proof that a majority of the Wormhole network has observed and agreed upon a state.


## Guardian Sets and Delegation

The Guardian network comprises 19 Guardians. However, some chains may utilize delegated subsets. Some chains (such as Ethereum and Solana) are secured by all 19 Guardians. Each Guardian runs a full node and independently observes on-chain events. Other chains may be secured by a delegated subset of Guardians based on chain activity. Chains that are not explicitly delegated, default to full Guardian Set observation, meaning all 19 Guardians observe directly.

For these chains:

- A configured delegated subset of the 19 Guardians performs direct on-chain observation.
- Delegated Guardians broadcast a `SignedDelegateObservation` gossip message.
- Canonical Guardians wait until a delegate quorum is reached before signing.
- A standard 13-of-19 VAA is ultimately produced.

This design provides operational flexibility while maintaining compatibility with the existing Wormhole contract stack.

### Delegated Observation Flow

The following flow shows how a subset of Guardians directly observes events on those chains and broadcasts a `SignedDelegateObservation` message over the Guardian gossip network. Canonical Guardians wait until the configured delegate quorum is reached before proceeding with the normal signing process. The final result is still a standard 13-of-19 VAA, fully compatible with existing smart contracts and integrations.

```mermaid
sequenceDiagram

participant CB as CoreBridge
participant DG as DelegatedGuardian
participant G as Gossip network
participant CG as CanonicalGuardian 1
participant CG2 as CanonicalGuardian 2

CB-->>DG: LogMessagePublished
DG->>DG: Watch & verify

alt DelegatedSet chain
  DG-->>G: Broadcast SignedDelegateObservation
  G-->>CG: Receive SignedDelegateObservation
  G-->>CG2: Receive SignedDelegateObservation
  loop Wait for delegate quorum
    CG->>CG: Mark message valid
    CG2->>CG2: Mark message valid
  end
end

note over CG,CG2: Standard signing flow continues
```

### Delegate Quorum Safeguards

On delegated chains, Canonical Guardians will not sign a message until a delegate quorum has been reached. This prevents a minority of Delegated Guardians from lowering the effective security threshold of a chain. For example, if a chain is configured as 7-of-9 Delegated Guardians, Canonical Guardians will only sign after at least 7 delegate observations agree. Once a delegate quorum is satisfied, Canonical Guardians sign to produce a standard 13-of-19 VAA.

## Guardian Network

The Guardian Network functions as Wormhole's decentralized oracle, ensuring secure, cross-chain interoperability. Learning about this critical element of the Wormhole ecosystem will help you better understand the protocol.

The Guardian Network is designed to help Wormhole deliver on five key principles:

- **Decentralization**: Control of the network is distributed across many parties.
- **Modularity**: Independent components (e.g., oracle, relayer, applications) ensure flexibility and upgradeability.
- **Chain agnosticism**: Supports EVM, Solana, and other blockchains without relying on a single network.
- **Scalability**: Can handle large transaction volumes and high-value transfers.
- **Upgradeable**: Can change the implementation of its existing modules without breaking integrators to adapt to changes in decentralized computing.

The following sections explore each principle in detail.

### Decentralization

Decentralization remains the core concern for interoperability protocols. Earlier solutions were fully centralized, and even newer models often rely on a single entity or just one or two actors, creating low thresholds for collusion or failure.

Two common approaches to decentralization have notable limitations:

- **Proof-of-Stake (PoS)**: While PoS is often seen as a go-to model for decentralization, it is not well-suited for a network that verifies many blockchains and does not run its own smart contracts. Its security in this context is unproven, and it introduces complexities that make other design goals harder to achieve.
- **Zero-Knowledge Proofs (ZKPs)**: ZKPs offer a trustless and decentralized approach, but the technology is still early-stage. On-chain verification is often too computationally expensive—especially on less capable chains—so a multisig-based fallback is still required for practical deployment.

In the current DeFi landscape, most major blockchains are secured by a small group of validator companies. Only a limited number of companies worldwide have the expertise and capital to run high-performance validators.

If a protocol could unite many of these top validator companies into a purpose-built consensus mechanism designed for interoperability, it would likely offer better performance and security than a token-incentivized network. The key question is: how many of them could Wormhole realistically involve?

To answer that, consider these key constraints and design decisions:

- **Threshold signatures allow flexibility, but**: With threshold signatures, in theory, any number of validators could participate. However, threshold signatures are not yet widely supported across blockchains. Verifying them is expensive and complex, especially in a chain-agnostic system.
- **t-Schnorr multisig is more practical**: Wormhole uses [t-Schnorr multisig](https://en.wikipedia.org/wiki/Schnorr_signature){target=\_blank}, which is broadly supported and relatively inexpensive to verify. However, verification costs scale linearly with the number of signers, so the size of the validator set needs to be deliberately specified.
- **19 Guardians form the canonical set**: A set of 19 participants presents ample opportunity for both decentralization and efficiency. A quorum of 13 signatures is required to produce a valid VAA.
- **Per-chain delegated thresholds**: On delegated chains, a delegated subset of Guardians may be configured with an optimized observation threshold. Canonical Guardians wait for delegate quorum before contributing their signatures, ensuring that the effective security threshold for a chain cannot be reduced below its configured level.
- **Security through reputation, not tokens**: Wormhole relies on a network of established validator companies instead of token-based incentives. These 19 Guardians are among the most trusted operators in the industry — real entities with a track record, not anonymous participants.

This forms the foundation for a purpose-built Proof-of-Authority (PoA) consensus model, where each Guardian has an equal stake. As threshold signatures gain broader support, the set can expand. Once ZKPs become widely viable, the network can evolve into a fully trustless system.

### Modularity

Wormhole is designed with simple components that are very good at a single function. Separating security and consensus (Guardians) from message delivery ([Executor](/docs/protocol/infrastructure/relayers/executor-framework/){target=\_blank}) allows for the flexibility to change or upgrade one component without disrupting the others.

### Chain Agnosticism

Today, Wormhole supports a broader range of ecosystems than any other interoperability protocol because it uses simple tech (t-schnorr signatures), an adaptable, heterogeneous relayer model, and a robust validator network. Wormhole can expand to new ecosystems as quickly as a [Core Contract](/docs/protocol/infrastructure/core-contracts/){target=\_blank} can be developed for the smart contract runtime.

### Scalability

Wormhole scales well, as demonstrated by its ability to handle substantial total value locked (TVL) and transaction volume even during tumultuous events.

On chains where all Guardians perform direct on-chain observation, each Guardian runs a full node and independently observes events. This requirement can be computationally heavy to set up; however, once all the full nodes are running, the Guardian Network's actual computation needs become lightweight.

On delegated chains, only the delegated subset of Guardians runs full nodes. Canonical Guardians rely on delegate observations broadcast through the gossip network and wait for delegate quorum before signing.

This reduces operational overhead while preserving the security model of the network. Performance is generally limited by the speed of the underlying blockchains, not the Guardian Network itself.

### Upgradeable

Wormhole is designed to adapt and evolve in the following ways:

- **Per-chain security configuration**: The Delegated Guardian configuration is managed via governance through the `WormholeDelegatedGuardians` contract, allowing per-chain threshold adjustments without requiring upgrades to existing Core contracts.
- **Guardian Set expansion**: Future updates may introduce threshold signatures to allow for more Guardians in the set.
- **ZKP integration**: As Zero-Knowledge Proofs become more widely supported, the network can transition to a fully trustless model.

These principles combine to create a clear pathway towards a fully trustless interoperability layer that spans decentralized computing.

## Next Steps

<div class="grid cards" markdown>

-   :octicons-book-16:{ .lg .middle } **Executor**

    ---

    Learn about the Executor framework - a shared, permissionless system for executing cross-chain messages using standardized contracts and quotes.

    [:custom-arrow: Learn About Executor](/docs/protocol/infrastructure/relayers/executor-framework/)

-   :octicons-tools-16:{ .lg .middle } **Query Guardian Data**

    ---

    Learn how to use Wormhole Queries to add real-time access to Guardian-attested on-chain data via a REST endpoint to your dApp, enabling secure cross-chain interactions and verifications.

    [:custom-arrow: Build with Queries](/docs/products/queries/overview/)

-   :octicons-tools-16:{ .lg .middle } **Wormhole Dev Arena**

    ---

    A structured learning hub with hands-on tutorials across the Wormhole ecosystem.

    [:custom-arrow: Explore the Dev Arena](https://arena.wormhole.com/ecosystem){target=\_blank}


</div>


---

Page Title: Integrate Connect into a React DApp Tutorial

- Resolved Markdown: https://wormhole.com/docs/ai/pages/products-connect-tutorials-react-dapp.md
- Canonical (HTML): https://wormhole.com/docs/products/connect/tutorials/react-dapp/
- Summary: Learn how to use Wormhole Connect to transfers tokens cross-chain seamlessly between Sui and Avalanche Fuji with this step-by-step guide.
- Word Count: 1340; Token Estimate: 2209

# Integrate Connect into a React DApp

:simple-github: [Source code on GitHub](https://github.com/wormhole-foundation/demo-basic-connect){target=\_blank}

In this tutorial, we'll explore how to integrate [Wormhole Connect](/docs/products/connect/overview/){target=\_blank} to enable cross-chain token transfers and interactions. Connect offers a simplified interface for developers to facilitate seamless token transfers between blockchains. Using Connect, you can easily bridge assets across multiple ecosystems without diving into the complex mechanics of cross-chain communication.

While this tutorial will guide you through the process using a specific blockchain as an example, the principles and steps outlined here can be applied to any [blockchain supported by Wormhole](/docs/products/connect/reference/support-matrix/){target=\_blank}. In this example, we'll work with Sui as our source blockchain and Avalanche Fuji as the destination blockchain.

## Prerequisites

To get started with Connect, we'll first need to set up a basic environment that allows for cross-chain token transfers.
Before starting this tutorial, ensure you have the following:

- [Node.js and npm](https://docs.npmjs.com/downloading-and-installing-node-js-and-npm){target=\_blank} installed on your machine.
- A [Sui wallet](https://suiwallet.com/){target=\_blank} set up and ready for use.
- A [compatible wallet](https://support.avax.network/en/articles/5520938-what-are-the-official-avalanche-wallets){target=\_blank} for Avalanche Fuji, such as [MetaMask](https://metamask.io/){target=\_blank}.
- Testnet tokens for [Sui](https://docs.sui.io/guides/developer/getting-started/get-coins){target=\_blank} and [Fuji](https://core.app/tools/testnet-faucet/?subnet=c&token=c){target=\_blank} to cover gas fees. 

## Set Up Connect for Sui Transfers

### Create a React Project

In this tutorial, we'll use [Next.js](https://nextjs.org/docs/app/getting-started){target=\_blank}, a popular framework built on top of React, to set up your app:

1. Open your terminal and run the following command to create a new React app:

    ```bash
    npx create-next-app@latest connect-tutorial
    ```

    We recommend enabling TypeScript and creating a `src/` directory during setup. Other options can be configured based on your preferences.

2. Navigate into the project directory:

    ```bash
    cd connect-tutorial
    ```

### Install Connect

Next, install the Connect package as a dependency by running the following command inside your project directory. This tutorial uses the Connect version `5.1.1`:

```bash
npm install @wormhole-foundation/wormhole-connect@5.1.1
```

### Integrate Connect into the Application

Now, we need to modify the default `page.tsx` file to integrate Connect. We are going to use [version V1.0](/docs/products/connect/guides/upgrade/){target=\_blank} or later, make sure to check which version of Connect you are using. Open `src/app/page.tsx` and replace the content with the following code:

=== "JavaScript"

    ```js
    'use client';

    import WormholeConnect from '@wormhole-foundation/wormhole-connect';

    const config = {
      network: 'Testnet',
      chains: ['Sui', 'Avalanche'],
    };

    const theme = {
      mode: 'light',
      primary: '#78c4b6',
    };

    export default function Home() {
      return <WormholeConnect config={config} theme={theme} />;
    }
    ```

=== "TypeScript"

    ```ts
    'use client';

    import WormholeConnect, {
      type config,
      WormholeConnectTheme,
    } from '@wormhole-foundation/wormhole-connect';

    export default function Home() {
      const config: config.WormholeConnectConfig = {
        network: 'Testnet',
        chains: ['Sui', 'Avalanche'],

        ui: {
          title: 'SUI Connect TS Demo',
        },
      };

      const theme: WormholeConnectTheme = {
        mode: 'light',
        primary: '#78c4b6',
      };
      return <WormholeConnect config={config} theme={theme} />;
    }
    ```

- **Set `network` to `'Testnet'`**: This ensures that Connect uses the testnet environment.
- **Set `chains` to `['Sui', 'Avalanche']`**: Configures the app to allow transfers between Sui and Avalanche Fuji, the testnet for Avalanche.

### Customize Connect

To further customize Connect for your application, such as adjusting the UI, adding custom tokens, enabling Reown (formerly known as WalletConnect), or configuring specific chain settings, you can refer to the [Connect Configuration guide](/docs/products/connect/configuration/data/){target=\_blank}.

### Run the Application

Make sure you're in the root directory of your React app, and run the following command to start the application:

```bash
npm run dev
```

Now your React app should be up and running, and Connect should be visible on `http://localhost:3000/`. You should see the Connect component, which will include a UI for selecting networks and tokens for cross-chain transfers.

## Transfer Tokens from Sui to Fuji

Before transferring token ensure you have enough testnet SUI and Fuji tokens to cover the gas fees for the transfer. 

To transfer tokens from Sui to Fuji in the Connect interface:

1. Select **Sui** as the source network, connect your Sui wallet, and choose **SUI** as the asset you wish to transfer.
2. Choose **Fuji** as the destination network and connect your wallet with the Fuji network.
3. Enter the amount of SUI tokens you wish to transfer.

    ![](/docs/images/products/connect/tutorials/react-dapp/connect-1.webp){.half}

4. Choose to view other routes.
    
    ![](/docs/images/products/connect/tutorials/react-dapp/connect-2.webp){.half}

5. Select the manual bridge option, which will require two transactions: one on the source chain (Sui) and one on the destination chain (Fuji).

    !!! note
        It is recommended to use the manual bridge option for this tutorial. The automatic bridge feature is currently undergoing improvements, while the manual bridge ensures that transfers complete successfully.

    ![](/docs/images/products/connect/tutorials/react-dapp/connect-3.webp){.half}

6. Review and confirm the transfer on Sui. This will lock your tokens on the Sui chain.

    ![](/docs/images/products/connect/tutorials/react-dapp/connect-4.webp){.half}

7. Follow the on-screen prompts to approve the transaction. You will be asked to sign with your Sui wallet.

    ![](/docs/images/products/connect/tutorials/react-dapp/connect-5.webp){.half}

Once the transaction has been submitted, Connect will display the progress of the transfer. Monitor the status until you're prompted to complete the transaction on the destination chain. You can also track your transactions on [Wormholescan](https://wormholescan.io/#/?network=Testnet){target=\_blank}.

## Claim Tokens on Fuji

After the Sui transaction is complete, confirm the final transaction on Fuji by claiming the wrapped tokens. You will be asked to confirm the transaction with your Fuji wallet.

![](/docs/images/products/connect/tutorials/react-dapp/connect-6.webp){.half}

Once confirmed, check your Fuji wallet to verify that the wrapped SUI tokens have been successfully received.

![](/docs/images/products/connect/tutorials/react-dapp/connect-7.webp){.half}

## Resources

If you'd like to explore the complete project or need a reference while following this tutorial, you can find the entire codebase in the [Sui-Connect GitHub repository](https://github.com/wormhole-foundation/demo-basic-connect){target=\_blank}. The repository includes an integration of Connect in a React app for bridging tokens between the Sui and Fuji (Avalanche Testnet) networks.

## Conclusion

In this tutorial, you've gained hands-on experience with integrating Connect to enable cross-chain token transfers. You've learned to configure a React app for seamless interactions between Sui and Avalanche Fuji, providing users with the ability to bridge assets across chains with ease.

By following these steps, you've learned how to:

- Set up a React project tailored for cross-chain transfers.
- Install and configure Connect to support multiple blockchains.
- Implement a streamlined UI for selecting source and destination chains, connecting wallets, and initiating transfers.
- Execute a token transfer from Sui to Avalanche Fuji, monitoring each step and confirming the transaction on both networks.

With these tools and knowledge, you're now equipped to build powerful cross-chain applications using Connect, opening up possibilities for users to move assets across ecosystems securely and efficiently.

## Next Steps

<div class="grid cards" markdown>

-   :octicons-tools-16:{ .lg .middle } **Build a Reimbursement App with Connect**

    ---

    Master the core features of Connect by building a real-world reimbursement application on the Wormhole Dev Arena, a structured learning hub with hands-on tutorials across the Wormhole ecosystem. 

    [:custom-arrow: Explore the Dev Arena](https://arena.wormhole.com/courses/1bee7446-5ed5-814a-8177-e087a5d7a6bc){target=\_blank}

-   :octicons-tools-16:{ .lg .middle } **Demo Tutorials Repository**

    ---

    Looking for more hands-on tutorials? Check out the Wormhole Tutorial Demo repository on GitHub for additional examples.

    [:custom-arrow: Explore the Demo Repository](https://github.com/wormhole-foundation/demo-tutorials){target=\_blank}

</div>


---

Page Title: Integrate Connect via CDN

- Resolved Markdown: https://wormhole.com/docs/ai/pages/products-connect-guides-hosted-version.md
- Canonical (HTML): https://wormhole.com/docs/products/connect/guides/hosted-version/
- Summary: Learn how to use Wormhole Connect via CDN in any JavaScript project using just a script tag with no React or backend setup required.
- Word Count: 342; Token Estimate: 621

# Integrate Connect via CDN

[Wormhole Connect](/docs/products/connect/overview/){target=\_blank} is a prebuilt UI component that makes it easy to transfer tokens across chains. You can integrate it into any website using either React or a hosted version served via [jsDelivr](https://www.jsdelivr.com/){target=\_blank}.

This guide focuses on using the hosted version—ideal for simpler setups or non-React environments. It includes everything you need to get started with just a few lines of code.

If you're using React, refer to the [Get Started with Connect](/docs/products/connect/get-started/){target=\_blank} guide.

## Install Connect

To install the [Connect npm package](https://www.npmjs.com/package/@wormhole-foundation/wormhole-connect){target=\_blank}, run the following command:

```bash
npm i @wormhole-foundation/wormhole-connect
```

## Add Connect to Your Project Using the Hosted Version

The hosted version uses pre-built packages (including React) served via jsDelivr from npm. To integrate it without using React directly, add the following to your JavaScript project:

```js
import { wormholeConnectHosted } from '@wormhole-foundation/wormhole-connect';

// Existing DOM element where you want to mount Connect
const container = document.getElementById('bridge-container');
if (!container) {
  throw new Error("Element with id 'bridge-container' not found");
}

wormholeConnectHosted(container);
```

You can provide config and theme parameters in a second function argument:

```js
import { wormholeConnectHosted } from '@wormhole-foundation/wormhole-connect';

// Existing DOM element where you want to mount Connect
const container = document.getElementById('bridge-container');
if (!container) {
  throw new Error("Element with id 'connect' not found");
}

wormholeConnectHosted(container, {
  config: {
    rpcs: {
      // ...
    },
  },
  theme: {
    background: {
      default: '#004547',
    },
  },
});
```

## Next Steps

Use the following guides to configure your Connect instance.

<div class="grid cards" markdown>

-   :octicons-tools-16:{ .lg .middle } **Data Configuration**

    ---

    Learn how to specify custom networks and RPC endpoints, integrate different bridging protocols, add new tokens, and more.

    [:custom-arrow: View Data Configs](/docs/products/connect/configuration/data/)

-   :octicons-tools-16:{ .lg .middle } **Theme Configuration**

    ---

    Learn how to customize Connect's look and feel to match your application's branding.

    [:custom-arrow: View Theme Configs](/docs/products/connect/configuration/theme/)

</div>


---

Page Title: Introduction to Wormhole

- Resolved Markdown: https://wormhole.com/docs/ai/pages/protocol-introduction.md
- Canonical (HTML): https://wormhole.com/docs/protocol/introduction/
- Summary: Wormhole is a protocol for seamless communication between blockchains, enabling cross-chain applications and integrations.
- Word Count: 885; Token Estimate: 1389

# Introduction to Wormhole

In the rapidly evolving landscape of blockchain technology, interoperability between different blockchains remains a significant challenge. Developers often face hurdles in creating applications that can seamlessly operate across multiple blockchains, limiting innovation and the potential of decentralized ecosystems.

Wormhole addresses this problem by providing a _generic message-passing_ protocol that enables secure and efficient communication between blockchains. By allowing data and asset transfers across various blockchain networks, Wormhole breaks down the walls that traditionally separate these ecosystems.

Wormhole is distinguished by its focus on robust security, scalability, and transparency. The protocol is supported by a decentralized network of validators that ensure the integrity of every cross-chain transaction. This, combined with Wormhole’s proven performance in real-world applications, gives developers a dependable platform to create and scale multichain applications confidently.

![Message-passing process in the Wormhole protocol](/docs/images/protocol/introduction/introduction-1.webp)

!!! note
    The above is an oversimplified illustration of the protocol; details about the architecture and components are available on the [architecture page](/docs/protocol/architecture/){target=\_blank}.

Wormhole allows developers to leverage the strengths of multiple blockchain ecosystems without being confined to one. This means applications can benefit from the unique features of various networks—such as Solana's high throughput, Ethereum's security, and Cosmos's interoperability, while maintaining a unified, efficient user experience.

This page introduces the key concepts and components necessary to understand how Wormhole enables fast, secure, and scalable cross-chain communication.

## What Problems Does Wormhole Solve?

Interoperability is a critical challenge in the rapidly evolving blockchain landscape. Individual blockchains are often isolated, limiting the potential for integrated applications operating across multiple ecosystems. Wormhole solves this problem by enabling seamless communication between blockchains, allowing developers to create multichain applications that can leverage the unique features of each network.

Critical problems Wormhole addresses include:

- **Blockchain isolation**: Wormhole connects disparate blockchains, enabling the transfer of assets, data, and governance actions across networks.
- **Cross-chain complexity**: By abstracting the complexities of cross-chain communication, Wormhole makes it easier for developers to build and deploy cross-chain applications.
- **Security and decentralization**: Wormhole prioritizes security through a decentralized Guardian network that validates and signs messages, ensuring the integrity of cross-chain interactions.

## What Does Wormhole Offer?

Wormhole provides a suite of tools and protocols that support a wide range of use cases:

- **Cross-chain messaging**: Securely transfer arbitrary data between blockchains, enabling the development of cross-chain decentralized applications.
- **Asset transfers**: Facilitate the movement of tokens across supported chains with ease, powered by protocols built on Wormhole like [Portal](https://portalbridge.com/){target=\_blank}.
- **Developer tools**: Leverage Wormhole’s [TypeScript SDK](/docs/tools/typescript-sdk/get-started/){target=\_blank}, [Wormholescan](https://wormholescan.io/){target=\_blank}, and the [Wormholescan API](https://wormholescan.io/#/developers/api-doc){target=\_blank} and documentation to build and deploy cross-chain applications quickly and efficiently.

## What Isn't Wormhole?

- **Wormhole is _not_ a blockchain**: It acts as a communication layer that connects different blockchains, enabling them to interact without being a blockchain itself.
- **Wormhole is _not_ a token bridge**: While it facilitates token transfers, Wormhole also supports a wide range of cross-chain applications, making it much more versatile than a typical bridge.

## Use Cases of Wormhole

Consider the following examples of potential applications enabled by Wormhole:

- **Cross-chain exchange**: Using [Wormhole Connect](/docs/products/connect/overview/){target=\_blank}, developers can build exchanges that allow deposits from any Wormhole-connected chain, significantly increasing liquidity access.
- [**Cross-chain governance**](https://wormhole.com/blog/stake-for-governance-guide){target=\_blank}: Projects with communities spread across multiple blockchains can use Wormhole to relay votes from each chain to a designated governance chain, enabling unified decision-making through combined proposals.
- **Cross-chain game**: Games can be developed on a performant network like Solana, with rewards issued on another network, such as Ethereum.

## Explore

Discover more about the Wormhole ecosystem, components, and protocols:

- **[Architecture](/docs/protocol/architecture/){target=\_blank}**: Explore the components of the protocol.
- **[Protocol Specifications](https://github.com/wormhole-foundation/wormhole/tree/main/whitepapers){target=\_blank}**: Learn about the protocols built on top of Wormhole.

## Demos

Demos offer more realistic implementations than tutorials:

- **[Wormhole Scaffolding](https://github.com/wormhole-foundation/wormhole-scaffolding){target=\_blank}**: Quickly set up a project with the Scaffolding repository.
- **[Demo Tutorials](https://github.com/wormhole-foundation/demo-tutorials){target=\_blank}**: Explore various demos that showcase Wormhole's capabilities across different blockchains.

!!! note
    Wormhole Integration Complete?

    Let us know so we can list your project in our ecosystem directory and introduce you to our global, multichain community!

    **[Reach out now!](https://forms.clickup.com/45049775/f/1aytxf-10244/JKYWRUQ70AUI99F32Q){target=\_blank}**

## Supported Networks by Product

Wormhole supports a growing number of blockchains. Check out the [Supported Networks by Product](/docs/products/reference/supported-networks/){target=\_blank} page to see which networks are supported for each Wormhole product.

## Next Steps

<div class="grid cards" markdown>

-   :octicons-book-16:{ .lg .middle } **Architecture Overview**

    ---

    Get an overview of Wormhole's architecture, detailing key on-chain and off-chain components like the Core Contract, Guardian Network, and relayers.

    [:custom-arrow: Learn More](/docs/protocol/architecture/)

-   :octicons-tools-16:{ .lg .middle } **Wormhole Dev Arena**

    ---

    A structured learning hub with hands-on tutorials across the Wormhole ecosystem.

    [:custom-arrow: Explore the Dev Arena](https://arena.wormhole.com/){target=\_blank}

</div>


---

Page Title: Messaging Overview

- Resolved Markdown: https://wormhole.com/docs/ai/pages/products-messaging-overview.md
- Canonical (HTML): https://wormhole.com/docs/products/messaging/overview/
- Summary: With Wormhole Messaging, you can enable secure, multichain communication, build multichain apps, sync data, and coordinate actions across blockchains.
- Word Count: 615; Token Estimate: 1238

# Messaging Overview 

Wormhole Messaging is the core protocol of the Wormhole ecosystem—a generic, multichain message-passing layer that enables secure, fast communication between blockchains. It solves the critical problem of blockchain isolation by allowing data and assets to move freely across networks, empowering developers to build true multichain applications.

## Key Features

- **Multichain messaging**: Send arbitrary data between blockchains, enabling xDapps, governance actions, or coordination across ecosystems.
- **Decentralized validation**: A network of independent [Guardians](/docs/protocol/infrastructure/guardians/){target=\_blank} observes and signs multichain messages, producing [Verifiable Action Approvals (VAAs)](/docs/protocol/infrastructure/vaas/){target=\_blank} that ensure integrity.
- **Composable architecture**: Works with smart contracts, token bridges, or decentralized applications, providing a flexible foundation for multichain use cases.

## How It Works

The messaging flow consists of several core components:

1. **Source chain (emitter contract)**: A contract emits a message by calling the Wormhole [Core Contract](/docs/protocol/infrastructure/core-contracts/){target=\_blank} on the source chain.
2. **Guardian Network**: [Guardians](/docs/protocol/infrastructure/guardians/){target=\_blank} observe the message, validate it, and generate a signed [VAA](/docs/protocol/infrastructure/vaas/){target=\_blank}.
3. **Relayers (Executor)**: Off-chain or on-chain relayers transport the VAA to the destination chain. In Wormhole’s architecture, this role is fulfilled by the [**Executor**](/docs/products/messaging/concepts/executor-overview/){target=\_blank}, a permissionless, shared framework that standardizes message delivery across all supported chains.
4. **Target chain (recipient contract)**: The [Core Contract](/docs/protocol/infrastructure/core-contracts/){target=\_blank} on the destination chain verifies the VAA and triggers the specified application logic.

![Wormhole architecture detailed diagram: source to target chain communication.](/docs/images/protocol/architecture/architecture-1.webp)

## Use Cases

Wormhole Messaging enables a wide range of multichain applications. Below are common use cases and the Wormhole stack components you can use to build them.

- **Borrowing and Lending Across Chains (e.g., [Folks Finance](https://wormhole.com/case-studies/folks-finance){target=\_blank})**

    - **[Messaging](/docs/products/messaging/get-started/){target=\_blank}**: Coordinate actions across chains.
    - **[Native Token Transfers](/docs/products/token-transfers/native-token-transfers/overview/){target=\_blank}**: Transfer collateral as native assets.

- **Oracle Networks (e.g., [Pyth](https://wormhole.com/case-studies/pyth){target=\_blank})**

    - **[Messaging](/docs/products/messaging/get-started/){target=\_blank}**: Relay verified data.

- **Gas Abstraction**

    - **[Messaging](/docs/products/messaging/get-started/){target=\_blank}**: Coordinate gas logic.
    - **[Native Token Transfers](/docs/products/token-transfers/native-token-transfers/overview/){target=\_blank}**: Handle native token swaps.

- **Bridging Intent Library**

    - **[Messaging](/docs/products/messaging/get-started/){target=\_blank}**: Dispatch and execute intents.
    - **[Settlement](/docs/products/settlement/overview/){target=\_blank}**: Execute user-defined bridging intents.

- **Decentralized Social Platforms (e.g., [Chingari](https://chingari.io/){target=\_blank})**

    - **[Messaging](/docs/products/messaging/get-started/){target=\_blank}**: Facilitate decentralized interactions.
    - **[Wrapped Token Transfers](/docs/products/token-transfers/wrapped-token-transfers/overview/){target=\_blank}**: Enable tokenized rewards.

## Next Steps

Follow these steps to work with Wormhole Messaging:

<div class="grid cards" markdown>

-   :octicons-tools-16:{ .lg .middle } **Get Started with Messaging**

    ---

    Use the core protocol to publish a multichain message and return transaction info with VAA identifiers.

    [:custom-arrow: Get Started](/docs/products/messaging/get-started/)

-   :octicons-book-16:{ .lg .middle } **Executor Overview**

    ---

    Learn how to use Executors to automate message handling and application logic across chains.

    [:custom-arrow: Learn about Executors](/docs/protocol/infrastructure/relayers/executor-framework/)

-   :octicons-tools-16:{ .lg .middle } **Solana Shim Programs**

    ---

    For lower-cost, efficient integration with Core Bridge on Solana, consider using shim programs:

    [:custom-arrow: Learn about Solana Shims](/docs/products/messaging/concepts/solana-shim/)

    [:custom-arrow: Emit Messages with the Emission Shim](/docs/products/messaging/guides/solana-shims/sol-emission/)

    [:custom-arrow: Verify VAAs with the Verification Shim](/docs/products/messaging/guides/solana-shims/sol-verification/)

</div>


---

Page Title: Relayers Overview

- Resolved Markdown: https://wormhole.com/docs/ai/pages/protocol-infrastructure-relayers-relayer.md
- Canonical (HTML): https://wormhole.com/docs/protocol/infrastructure/relayers/relayer/
- Summary: Discover the role of relayers in the Wormhole network, including client-side and automated relaying via the Executor framework, for secure cross-chain communication.
- Word Count: 810; Token Estimate: 1145

# Overview

!!!warning 
    The Wormhole Standard Relayer is being deprecated. Developers are strongly encouraged to [migrate to the Executor framework](/docs/protocol/infrastructure/relayers/executor-vs-sr/){target=\_blank}.

This page introduces relayers in the Wormhole network and explains their role, available approaches, and the trade-offs involved in delivering cross-chain messages.

Relayers are the entities responsible for submitting signed [Verified Action Approvals (VAAs)](/docs/protocol/infrastructure/vaas/){target=\_blank} to destination chains, providing message delivery and automation. At the same time, Guardian signatures and on-chain verification ensure that relayers cannot tamper with message contents and only influence when a VAA is delivered.

Wormhole supports both manual (client-side) and automated relaying. Automated relaying is implemented using the [Executor framework](/docs/protocol/infrastructure/relayers/executor-framework/){target=\_blank}, Wormhole's decentralized relayer infrastructure.

## Fundamentals

Relayers act as delivery mechanisms for cross-chain messages. Their responsibility is to observe signed VAAs and submit them to destination chain contracts for on-chain verification and execution. Guardian signatures and on-chain verification logic define what is executed, while relayers provide availability and automation by ensuring messages reach their destination.

- **Anyone can relay a message**: The Guardian Network broadcasts signed VAAs publicly, allowing any entity to submit them to destination chain contracts. Guardian signatures provide universal verifiability, ensuring relaying is permissionless. If one relayer is unavailable, another party can submit the same VAA to complete delivery.
- **Security is in the VAA**: Guardian signatures authenticate message contents and execution parameters. Contracts should rely only on signed VAAs and on-chain state, not on off-chain data supplied by relayers. As a result, relayers can affect delivery timing, but not message correctness or security, making relaying trustless.
- **User experience vs. infrastructure**: Relayers automate cross-chain delivery to improve user experience, but introduce considerations around fees. Developers can choose between client-side relaying or the Executor framework depending on their needs.

## Manual vs. Automated Relaying

When integrating Wormhole messaging, applications can use either manual (client-side) relaying or automated relaying. The difference lies in who is responsible for delivering the VAA to the destination chain.

- **Manual relaying (client-side)**: The user or client application (e.g., a dApp or wallet) is responsible for carrying out all cross-chain steps. After an action on the source chain produces a VAA, the user must fetch the VAA (e.g., via a Wormhole API or explorer) and submit it in a transaction on the destination chain. No backend infrastructure is required, and costs are limited to destination-chain transaction fees. However, this approach requires multiple user interactions and funds on each chain involved, making it best suited for testing, demos, and MVPs rather than production applications.
- **Automated relaying**: Cross-chain delivery is handled automatically by a relayer service or network instead of the end user. From the user's perspective, the message is delivered to the destination chain without manual intervention, enabling a smoother, one-step experience. With the [Executor framework](/docs/protocol/infrastructure/relayers/executor-framework/){target=\_blank}, applications can leverage Wormhole's decentralized relayer infrastructure to request automated delivery, without running a backend service. This reduces operational complexity at the cost of service fees, while significantly improving user experience.

Choosing between manual and automated relaying depends on the application's requirements. If the integrator prioritizes convenience, automated relaying provides a superior experience.


## Executor

The Executor is a permissionless, next-generation relaying framework that enables anyone to act as a relayer through a request-and-quote model, with support for multichain delivery and flexible pricing.

At a high level, the Executor consists of:

- A lightweight, stateless [Executor contract](/docs/protocol/infrastructure/relayers/executor-framework/#executor-contract){target=\_blank} deployed by Wormhole on supported chains
- A permissionless network of off-chain [relay providers](/docs/protocol/infrastructure/relayers/executor-framework/#relay-provider){target=\_blank} that fulfill delivery requests

Applications request automated delivery by submitting an execution request to the Executor contract, along with a signed fee quote obtained off-chain from a relay provider. Relay providers monitor these requests and deliver the corresponding VAAs to destination chains for on-chain execution, extending relaying functionality beyond EVM-only environments.

The Executor does not change Wormhole’s security model. Guardian signatures and on-chain verification enforce message integrity and execution correctness, while relay providers compete on pricing and availability. This creates a decentralized marketplace for relaying rather than a single relayer service.


## Next Steps

<div class="grid cards" markdown>

-   :octicons-book-16:{ .lg .middle } **Migrate to Executor**

    ---

    Understand the key differences between the Executor framework and the Standard Relayer, and find guidance for migrating existing integrations.

    [:custom-arrow: Migrate to Executor](/docs/protocol/infrastructure/relayers/executor-vs-sr/)

-   :octicons-tools-16:{ .lg .middle } **Wormhole Dev Arena**

    ---

    A structured learning hub with hands-on tutorials across the Wormhole ecosystem.

    [:custom-arrow: Explore the Dev Arena](https://arena.wormhole.com/ecosystem){target=\_blank}

</div>


---

Page Title: Replace Outdated Signatures in VAAs

- Resolved Markdown: https://wormhole.com/docs/ai/pages/products-messaging-tutorials-replace-signatures.md
- Canonical (HTML): https://wormhole.com/docs/products/messaging/tutorials/replace-signatures/
- Summary: Learn how to fetch, validate, and replace outdated signatures in Wormhole VAAs using Wormholescan and the Wormhole SDK to ensure seamless processing.
- Word Count: 4514; Token Estimate: 9168

# Replace Outdated Signatures in VAAs

:simple-github: [Source code on GitHub](https://github.com/wormhole-foundation/demo-vaa-signature-replacement){target=\_blank}

Cross-chain transactions in Wormhole rely on [Verifiable Action Approvals (VAAs)](/docs/protocol/infrastructure/vaas/){target=\_blank}, which contain signatures from a trusted set of validators called [Guardians](/docs/protocol/infrastructure/guardians/){target=\_blank}. These signatures prove that the network approved an action, such as a token transfer.

However, the set of Guardians changes over time. If a user generates a transaction and waits too long before redeeming it, the Guardian set may have already changed. This means the VAA will contain outdated signatures from Guardians, who are no longer part of the network, causing the transaction to fail.

Instead of discarding these VAAs, we can fetch updated signatures and replace the outdated ones to ensure smooth processing.

In this tutorial, you'll build a script from scratch to:

- Fetch a VAA from [Wormholescan](https://wormholescan.io/#/developers/api-doc){target=\_blank}.
- Validate its signatures against the latest Guardian set.
- Replace outdated signatures using the [Wormhole SDK](https://github.com/wormhole-foundation/wormhole-sdk-ts){target=\_blank}.
- Output a valid VAA ready for submission.

By the end, you'll have a script that ensures VAAs remain valid and processable, avoiding transaction failures.

## Prerequisites

Before you begin, ensure you have the following:

 - [Node.js and npm](https://docs.npmjs.com/downloading-and-installing-node-js-and-npm){target=\_blank} installed on your machine.
 - [TypeScript](https://www.typescriptlang.org/download/){target=\_blank} installed globally.

## Project Setup

In this section, you will create the directory, initialize a Node.js project, install dependencies, and configure TypeScript.

1. **Create the project**: Set up the directory and navigate into it.

    ```bash
    mkdir wormhole-scan-api-demo
    cd wormhole-scan-api-demo
    ```

2. **Initialize a Node.js project**: Generate a `package.json` file.

    ```bash
    npm init -y
    ```

3. **Set up TypeScript**: Create a `tsconfig.json` file.

    ```bash
    touch tsconfig.json
    ```

    Then, add the following configuration:

    ```json title="tsconfig.json"
    {
        "compilerOptions": {
            "target": "es2016",
            "module": "commonjs",
            "esModuleInterop": true,
            "forceConsistentCasingInFileNames": true,
            "strict": true,
            "skipLibCheck": true
        }
    }
    ```

4. **Install dependencies**: Add the required packages. This tutorial uses the SDK version `4.14.1`.

    ```bash
    npm install @wormhole-foundation/sdk@4.14.1 axios web3 tsx @types/node
    ```

     - **`@wormhole-foundation/sdk`**: Handles VAAs and cross-chain interactions.  
     - **`axios`**: Makes HTTP requests to the Wormholescan API.  
     - **`web3`**: Interacts with Ethereum transactions and contracts.  
     - **`tsx`**: Executes TypeScript files without compilation.  
     - **`@types/node`**: Provides Node.js type definitions. 

5. **Create the project structure**: Set up the required directories and files.

    ```bash
    mkdir -p src/config && touch src/config/constants.ts src/config/layouts.ts
    mkdir -p src/helpers && touch src/helpers/vaaHelper.ts
    mkdir -p src/scripts && touch scripts/replaceSignatures.ts
    ```

     - **`src/config/*`**: Stores public configuration variables and layouts for serializing and deserializing data structures.
     - **`src/helpers/*`**: Contains utility functions.
     - **`src/scripts/*`**: Contains scripts for fetching and replacing signatures.

6. **Set variables**: Define key constants in `src/config/constants.ts`.

    ```bash title="src/config/constants.ts"
    export const RPC = 'https://ethereum-rpc.publicnode.com';

    export const ETH_CORE =
      '0x98f3c9e6E3fAce36bAAd05FE09d375Ef1464288B'.toLowerCase();

    export const WORMHOLESCAN_API = 'https://api.wormholescan.io/v1';

    export const LOG_MESSAGE_PUBLISHED_TOPIC =
      '0x6eb224fb001ed210e379b335e35efe88672a8ce935d981a6896b27ffdf52a3b2';

    export const TXS = [
      '0x3ad91ec530187bb2ce3b394d587878cd1e9e037a97e51fbc34af89b2e0719367',
      '0x3c989a6bb40dcd4719453fbe7bbac420f23962c900ae75793124fc9cc614368c',
    ];
    ```

     - **`RPC`**: Endpoint for interacting with an Ethereum RPC node.
     - **`ETH_CORE`**: [Wormhole's Core Contract address on Ethereum](/docs/products/reference/contract-addresses/#core-contracts){target=\_blank} responsible for verifying VAAs.
     - **`WORMHOLESCAN_API`**: Base URL for querying the Wormholescan API to fetch VAA data and Guardian sets.
     - **`LOG_MESSAGE_PUBLISHED_TOPIC`**: The event signature hash for `LogMessagePublished`, a Wormhole contract event that signals when a VAA has been emitted. This is used to identify relevant logs in transaction receipts.
     - **`TXS`**: List of example transaction hashes that will be used for testing.

7. **Define data structure for working with VAAs**: Specify the ABI for the Wormhole Core Contract's `parseAndVerifyVM` function, which parses and verifies VAAs. Defining the data structure, also referred to as a [layout](/docs/tools/typescript-sdk/guides/sdk-layout/){target=\_blank}, for this function ensures accurate decoding and validation of VAAs.

    ```typescript title="src/config/layouts.ts"
    export const PARSE_AND_VERIFY_VM_ABI = {
      inputs: [{ internalType: 'bytes', name: 'encodedVM', type: 'bytes' }],
      name: 'parseAndVerifyVM',
      outputs: [
        {
          components: [
            { internalType: 'uint8', name: 'version', type: 'uint8' },
            { internalType: 'uint32', name: 'timestamp', type: 'uint32' },
            { internalType: 'uint32', name: 'nonce', type: 'uint32' },
            { internalType: 'uint16', name: 'emitterChainId', type: 'uint16' },
            { internalType: 'bytes32', name: 'emitterAddress', type: 'bytes32' },
            { internalType: 'uint64', name: 'sequence', type: 'uint64' },
            { internalType: 'uint8', name: 'consistencyLevel', type: 'uint8' },
            { internalType: 'bytes', name: 'payload', type: 'bytes' },
            { internalType: 'uint32', name: 'guardianSetIndex', type: 'uint32' },
            {
              components: [
                { internalType: 'bytes32', name: 'r', type: 'bytes32' },
                { internalType: 'bytes32', name: 's', type: 'bytes32' },
                { internalType: 'uint8', name: 'v', type: 'uint8' },
                { internalType: 'uint8', name: 'guardianIndex', type: 'uint8' },
              ],
              internalType: 'struct Structs.Signature[]',
              name: 'signatures',
              type: 'tuple[]',
            },
            { internalType: 'bytes32', name: 'hash', type: 'bytes32' },
          ],
          internalType: 'struct Structs.VM',
          name: 'vm',
          type: 'tuple',
        },
        { internalType: 'bool', name: 'valid', type: 'bool' },
        { internalType: 'string', name: 'reason', type: 'string' },
      ],
      stateMutability: 'view',
      type: 'function',
    };
    ```

## Create VAA Handling Functions

In this section, we'll create a series of helper functions in the `src/helpers/vaaHelper.ts` file that will retrieve and verify VAAs and fetch and replace outdated Guardian signatures to generate a correctly signed VAA.

To get started, import the necessary dependencies:

```typescript title="src/helpers/vaaHelper.ts"
import axios from 'axios';
import { eth } from 'web3';
import {
  deserialize,
  serialize,
  VAA,
  Signature,
} from '@wormhole-foundation/sdk';
import {
  RPC,
  ETH_CORE,
  LOG_MESSAGE_PUBLISHED_TOPIC,
  WORMHOLESCAN_API,
} from '../config/constants';
import { PARSE_AND_VERIFY_VM_ABI } from '../config/layouts';
```

### Fetch a VAA ID from a Transaction

To retrieve a VAA, we first need to get its VAA ID from a transaction hash. This ID allows us to fetch the full VAA later.
The VAA ID is structured as follows:

```bash
chain/emitter/sequence
```

 - **`chain`**: The [Wormhole chain ID](/docs/products/reference/chain-ids/){target=\_blank} (Ethereum is 2).
 - **`emitter`**: The contract address that emitted the VAA.
 - **`sequence`**: A unique identifier for the event.

We must assemble the ID correctly since this is the format the Wormholescan API expects when querying VAAs.

Follow the below steps to process the transaction logs and construct the VAA ID:

1. **Get the transaction receipt**: Iterate over the array of transaction hashes and fetch the receipt to access its logs.

2. **Find the Wormhole event**: Iterate over the transaction logs and check for events emitted by the Wormhole Core contract. Look specifically for `LogMessagePublished` events, which indicate a VAA was created.

3. **Extract the emitter and sequence number**: If a matching event is found, extract the emitter address from `log.topics[1]` and remove the `0x` prefix. Then, the sequence number from `log.data` is extracted, converting it from hex to an integer.

4. **Construct the VAA ID**: Format the extracted data in `chain/emitter/sequence` format.

```typescript title="src/helpers/vaaHelper.ts"
export async function fetchVaaId(txHashes: string[]): Promise<string[]> {
  const vaaIds: string[] = [];

  for (const tx of txHashes) {
    try {
      const result = (
        await axios.post(RPC, {
          jsonrpc: '2.0',
          id: 1,
          method: 'eth_getTransactionReceipt',
          params: [tx],
        })
      ).data.result;

      if (!result)
        throw new Error(`Unable to fetch transaction receipt for ${tx}`);

      for (const log of result.logs) {
        if (
          log.address === ETH_CORE &&
          log.topics?.[0] === LOG_MESSAGE_PUBLISHED_TOPIC
        ) {
          const emitter = log.topics[1].substring(2);
          const seq = BigInt(log.data.substring(0, 66)).toString();
          vaaIds.push(`2/${emitter}/${seq}`);
        }
      }
    } catch (error) {
      console.error(`Error processing ${tx}:`, error);
    }
  }

  return vaaIds;
}
```

???- code "Try it out: VAA ID retrieval"
    If you want to try out the function before moving forward, create a test file inside the `test` directory: 

    1. Create the directory and file:

        ```bash
        mkdir -p test
        touch test/fetchVaaId.run.ts
        ```  

    2. Add the function call:  

        ```typescript title="test/fetchVaaId.run.ts"
        import { fetchVaaId } from '../src/helpers/vaaHelper';
        import { TXS } from '../src/config/constants';

        const testFetchVaaId = async () => {
          for (const tx of TXS) {
            const vaaIds = await fetchVaaId([tx]);

            if (vaaIds.length > 0) {
              console.log(`Transaction: ${tx}`);
              vaaIds.forEach((vaaId) => console.log(`VAA ID: ${vaaId}`));
            } else {
              console.log(`No VAA ID found for transaction: ${tx}`);
            }
          }
        };

        testFetchVaaId();
        ```  

    3. Run the script:  

        ```bash
        npx tsx test/fetchVaaId.run.ts
        ```  

        If successful, the output will be:

        <div id="termynal" data-termynal>
        	<span data-ty="input"><span class="file-path"></span>npx tsx test/fetchVaaId.run.ts</span>
        	<span data-ty> </span>
        	<span data-ty
        		>Transaction: 0x3ad91ec530187bb2ce3b394d587878cd1e9e037a97e51fbc34af89b2e0719367</span
        	>
        	<span data-ty
        		>VAA ID: 2/0000000000000000000000003ee18b2214aff97000d974cf647e7c347e8fa585/164170</span
        	>
        	<span data-ty="input"><span class="file-path"></span></span>
        </div>
        If no VAA ID is found, the script will log an error message.

### Fetch the Full VAA

Now that you have the VAA ID, we can use it to fetch the full VAA payload from the Wormholescan API. This payload contains the VAA bytes, which will later be used for signature validation.

Open `src/helpers/vaaHelper.ts` and create the `fetchVaa()` function to iterate through VAA IDs and extract the `vaaBytes` payload.

```typescript title="src/helpers/vaaHelper.ts"
export async function fetchVaa(
  vaaIds: string[]
): Promise<{ id: string; vaaBytes: string }[]> {
  const results: { id: string; vaaBytes: string }[] = [];

  for (const id of vaaIds) {
    try {
      const response = await axios.get(`${WORMHOLESCAN_API}/signed_vaa/${id}`);
      const vaaBytes = response.data.vaaBytes;
      results.push({ id, vaaBytes });
    } catch (error) {
      console.error(`Error fetching VAA for ${id}:`, error);
    }
  }
  return results;
}
```

???- code "Try it out: VAA retrieval"
    If you want to try the function before moving forward, create a script inside the `test` directory  

    1. Create the script file:

        ```bash
        touch test/fetchVaa.run.ts
        ```

    2. Add the function call:

        ```typescript title="test/fetchVaa.run.ts"
        import { fetchVaaId, fetchVaa } from '../src/helpers/vaaHelper';
        import { TXS } from '../src/config/constants';

        const testFetchVaa = async () => {
          for (const tx of TXS) {
            const vaaIds = await fetchVaaId([tx]);

            if (vaaIds.length === 0) {
              console.log(`No VAA ID found for transaction: ${tx}`);
              continue;
            }

            for (const vaaId of vaaIds) {
              const vaaBytes = await fetchVaa([vaaId]);

              console.log(
                `Transaction: ${tx}\nVAA ID: ${vaaId}\nVAA Bytes: ${
                  vaaBytes.length > 0 ? vaaBytes[0].vaaBytes : 'Not found'
                }`
              );
            }
          }
        };

        testFetchVaa();
        ```

    3. Run the script:

        ```bash
        npx tsx test/fetchVaa.run.ts
        ```

        If successful, the output will be:

        <div id="termynal" data-termynal>
        	<span data-ty="input"><span class="file-path"></span>npx tsx test/fetchVaa.run.ts</span>
        	<span data-ty> </span>
        	<span data-ty
        		>Transaction: 0x3ad91ec530187bb2ce3b394d587878cd1e9e037a97e51fbc34af89b2e0719367</span
        	>
        	<span data-ty
        		>VAA Bytes: AQAAAAMNANQSwD/HRPcKp7Yxypl1ON8dZeMBzgYJrd2KYz6l9Tq9K9fj72fYJgkMeMaB9h...</span
        	>
        	<span data-ty="input"><span class="file-path"></span></span>
        </div>
        If no VAA is found, the script will log an error message.

### Validate VAA Signatures

Now, we need to verify its validity. A VAA is only considered valid if it contains signatures from currently active Guardians and is correctly verified by the Wormhole Core contract.

Open `src/helpers/vaaHelper.ts` and add the `checkVaaValidity()` function. This function verifies whether a VAA is valid by submitting it to an Ethereum RPC node and checking for outdated signatures.  

Follow these steps to implement the function:  

1. **Prepare the VAA for verification**: Construct the VAA payload in a format that can be sent to the Wormhole Core contract.

2. **Send an `eth_call` request**: Submit the VAA to an Ethereum RPC node, calling the `parseAndVerifyVM` function on the Wormhole Core contract.

3. **Decode the response**: Check whether the VAA is valid. If it contains outdated signatures, further action will be required to replace them.

```typescript title="src/helpers/vaaHelper.ts"
export async function checkVaaValidity(vaaBytes: string) {
  try {
    const vaa = Buffer.from(vaaBytes, 'base64');
    vaa[4] = 4; // Set guardian set index to 4

    const result = (
      await axios.post(RPC, {
        jsonrpc: '2.0',
        id: 1,
        method: 'eth_call',
        params: [
          {
            from: null,
            to: ETH_CORE,
            data: eth.abi.encodeFunctionCall(PARSE_AND_VERIFY_VM_ABI, [
              `0x${vaa.toString('hex')}`,
            ]),
          },
          'latest',
        ],
      })
    ).data.result;

    const decoded = eth.abi.decodeParameters(
      PARSE_AND_VERIFY_VM_ABI.outputs,
      result
    );
    console.log(
      `${decoded.valid ? '✅' : '❌'} VAA Valid: ${decoded.valid}${
        decoded.valid ? '' : `, Reason: ${decoded.reason}`
      }`
    );

    return { valid: decoded.valid, reason: decoded.reason };
  } catch (error) {
    console.error(`Error checking VAA validity:`, error);
    return { valid: false, reason: 'RPC error' };
  }
}
```

???- code "Try it out: VAA Validity"
    If you want to try the function before moving forward, create a script inside the `test` directory

    1. Create the script file:

        ```bash
        touch test/checkVaaValidity.run.ts
        ```

    2. Add the function call:

        ```typescript title="test/checkVaaValidity.run.ts"
        import {
          fetchVaaId,
          fetchVaa,
          checkVaaValidity,
        } from '../src/helpers/vaaHelper';
        import { TXS } from '../src/config/constants';

        const testCheckVaaValidity = async () => {
          for (const tx of TXS) {
            const vaaIds = await fetchVaaId([tx]);

            if (vaaIds.length === 0) {
              console.log(`No VAA ID found for transaction: ${tx}`);
              continue;
            }

            for (const vaaId of vaaIds) {
              const vaaData = await fetchVaa([vaaId]);

              if (vaaData.length === 0 || !vaaData[0].vaaBytes) {
                console.log(`VAA not found for ID: ${vaaId}`);
                continue;
              }

              const result = await checkVaaValidity(vaaData[0].vaaBytes);
              console.log(
                `Transaction: ${tx}\nVAA ID: ${vaaId}\nVAA Validity:`,
                result
              );
            }
          }
        };

        testCheckVaaValidity();
        ```

    3. Run the script:

        ```bash
        npx tsx test/checkVaaValidity.run.ts
        ```

        If the VAA is valid, the output will be:  

        <div id="termynal" data-termynal>
        	<span data-ty="input"><span class="file-path"></span>npx tsx test/checkVaaValidity.run.ts</span>
        	<span data-ty> </span>
        	<span data-ty>✅ VAA Valid: true</span>
        	<span data-ty="input"><span class="file-path"></span></span>
        </div>
        If invalid, the output will include the reason:

        <div id="termynal" data-termynal>
        	<span data-ty="input"><span class="file-path"></span>npx tsx test/checkVaaValidity.run.ts</span>
        	<span data-ty> </span>
        	<span data-ty>❌ VAA Valid: false, Reason: VM signature invalid</span>
        	<span data-ty
        		>Transaction: 0x3ad91ec530187bb2ce3b394d587878cd1e9e037a97e51fbc34af89b2e0719367</span
        	>
        	<span data-ty="input"><span class="file-path"></span></span>
        </div>
### Fetch Observations (VAA Signatures)

Before replacing outdated signatures, we need to fetch the original VAA signatures from Wormholescan. This allows us to compare them with the latest Guardian set and determine which ones need updating.

Inside `src/helpers/vaaHelper.ts`, create the `fetchObservations()` function to query the Wormholescan API for observations related to a given VAA. Format the response by converting Guardian addresses to lowercase for consistency, and return an empty array if an error occurs.

```typescript title="src/helpers/vaaHelper.ts"
export async function fetchObservations(vaaId: string) {
  try {
    console.log(`Fetching observations`);

    const response = await axios.get(
      `https://api.wormholescan.io/api/v1/observations/${vaaId}`
    );

    return response.data.map((obs: any) => ({
      guardianAddr: obs.guardianAddr.toLowerCase(),
      signature: obs.signature,
    }));
  } catch (error) {
    console.error(`Error fetching observations:`, error);
    return [];
  }
}
```

???- code "Try it out: Fetch Observations"
    If you want to try the function before moving forward, create a script inside the `test` directory

    1. Create the script file:

        ```bash
        touch test/fetchObservations.run.ts
        ```

    2. Add the function call:

        ```typescript title="test/fetchObservations.run.ts"
        import { fetchVaaId, fetchObservations } from '../src/helpers/vaaHelper';
        import { TXS } from '../src/config/constants';

        const testFetchObservations = async () => {
          for (const tx of TXS) {
            const vaaIds = await fetchVaaId([tx]);

            if (vaaIds.length === 0) {
              console.log(`No VAA ID found for transaction: ${tx}`);
              continue;
            }

            for (const vaaId of vaaIds) {
              const observations = await fetchObservations(vaaId);

              if (observations.length === 0) {
                console.log(`No observations found for VAA ID: ${vaaId}`);
                continue;
              }

              console.log(
                `Transaction: ${tx}\nVAA ID: ${vaaId}\nObservations:`,
                observations
              );
            }
          }
        };

        testFetchObservations();
        ```

    3. Run the script:

        ```bash
        npx tsx test/fetchObservations.run.ts
        ```

        If successful, the output will be:

        <div id="termynal" data-termynal>
        	<span data-ty="input"><span class="file-path"></span>npx tsx test/fetchObservations.run.ts</span>
        	<span data-ty> </span>
        	<span data-ty>Fetching observations</span>
        	<span data-ty
        		>Transaction: 0x3ad91ec530187bb2ce3b394d587878cd1e9e037a97e51fbc34af89b2e0719367</span
        	>
        	<span data-ty
        		>Observations: [ { guardianAddr: '0xda798f6896a3331f64b48c12d1d57fd9cbe70811', signature:
        		'ZGFlMDYyOGNjZjFjMmE0ZTk5YzE2OThhZjAzMDM4NzZlYTM1OWMxMzczNDA3YzdlMDMxZTkyNzk0ODkwYjRiYjRiOWFmNzM3NjRiMzIyOTE0ZTQwYzNlMjllMWEzNmM2NTc3ZDc5ZTdhNTM2MzA5YjA4YjExZjE3YzE3MDViNWIwMQ=='
        		}, { guardianAddr: '0x74a3bf913953d695260d88bc1aa25a4eee363ef0', signature:
        		'MzAyOTU4OGU4MWU0ODc0OTAwNDU3N2EzMGZlM2UxMDJjOWYwMjM0NWVhY2VmZWQ0ZGJlNTFkNmI3YzRhZmQ5ZTNiODFjNTg3MDNmYzUzNmJiYWFiZjNlODc1YTY3OTQwMGE4MmE3ZjZhNGYzOGY3YmRmNDNhM2VhNGQyNWNlNGMwMA=='
        		},</span
        	>
        	<span data-ty>...]</span>
        	<span data-ty="input"><span class="file-path"></span></span>
        </div>
        If no observations are found, the script will log an error message.

### Fetch the Latest Guardian Set

Now that we have the original VAA signatures, we must fetch the latest Guardian set from Wormholescan. This will allow us to compare the stored signatures with the current Guardians and determine which signatures need replacing.

Create the `fetchGuardianSet()` function inside `src/helpers/vaaHelper.ts` to fetch the latest Guardian set.

```typescript title="src/helpers/vaaHelper.ts"

export async function fetchGuardianSet() {
  try {
    console.log('Fetching current guardian set');

    const response = await axios.get(`${WORMHOLESCAN_API}/guardianset/current`);
    const guardians = response.data.guardianSet.addresses.map((addr: string) =>
      addr.toLowerCase()
    );
    const guardianSet = response.data.guardianSet.index;

    return [guardians, guardianSet];
  } catch (error) {
    console.error('Error fetching guardian set:', error);
    return [];
  }
}
```

???- code "Try it out: Fetch Guardian Set"
    If you want to try the function before moving forward, create a script inside the `test` directory

    1. Create the script file:

        ```bash
        touch test/fetchGuardianSet.run.ts
        ```

    2. Add the function call:

        ```typescript title="test/fetchGuardianSet.run.ts"
        import { fetchGuardianSet } from '../src/helpers/vaaHelper';

        const testFetchGuardianSet = async () => {
          const [guardians, guardianSetIndex] = await fetchGuardianSet();

          console.log('Current Guardian Set Index:', guardianSetIndex);
          console.log('Guardian Addresses:', guardians);
        };

        testFetchGuardianSet();
        ```

    3. Run the script:

        ```bash
        npx tsx test/fetchGuardianSet.run.ts
        ```

        If successful, the output will be:

        <div id="termynal" data-termynal>
        	<span data-ty="input"><span class="file-path"></span>npx tsx test/fetchGuardianSet.run.ts</span>
        	<span data-ty> </span>
        	<span data-ty>Fetching current guardian set</span>
        	<span data-ty>Current Guardian Set Index: 4</span>
            <span data-ty>Guardian Addresses: [
                '0x5893b5a76c3f739645648885bdccc06cd70a3cd3',
                '0xff6cb952589bde862c25ef4392132fb9d4a42157',
                '0x114de8460193bdf3a2fcf81f86a09765f4762fd1',
                '0x107a0086b32d7a0977926a205131d8731d39cbeb',
            </span>
            <span data-ty>...]</span>
        	<span data-ty="input"><span class="file-path"></span></span>
        </div>
        If an error occurs while fetching the Guardian set, a `500` status error will be logged.

### Replace Outdated Signatures

With the full VAA, Guardian signatures, and the latest Guardian set, we can now update outdated signatures while maintaining the required signature count.

1. **Create the `replaceSignatures()` function**: Open `src/helpers/vaaHelper.ts` and add the function header. To catch and handle errors properly, all logic will be wrapped inside a `try` block.

    ```typescript title="src/helpers/vaaHelper.ts"
    export async function replaceSignatures(
      vaa: string | Uint8Array<ArrayBufferLike>,
      observations: { guardianAddr: string; signature: string }[],
      currentGuardians: string[],
      guardianSetIndex: number
    ) {
      console.log('Replacing Signatures...');

      try {
        // Add logic in the following steps here
      } catch (error) {
        console.error('Unexpected error in replaceSignatures:', error);
      }
    }
    ```

     - **`vaa`**: Original VAA bytes.
     - **`observations`**: Observed signatures from the network.
     - **`currentGuardians`**: Latest Guardian set.
     - **`guardianSetIndex`**: Current Guardian set index.

2. **Validate input data**: Ensure all required parameters are present before proceeding. If any required input is missing, the function throws an error to prevent execution with incomplete data. The Guardian set should never be empty; if it is, this likely indicates an error in fetching the Guardian set in a previous step.

    ```typescript
        if (!vaa) throw new Error('VAA is undefined or empty.');
        if (currentGuardians.length === 0)
          throw new Error('Guardian set is empty.');
        if (observations.length === 0) throw new Error('No observations provided.');
    ```

3. **Filter valid signatures**: Remove signatures from inactive Guardians, keeping only valid ones. If there aren't enough valid signatures to replace the outdated ones, execution is halted to prevent an incomplete or invalid VAA.

    ```typescript
        const validSigs = observations.filter((sig) =>
          currentGuardians.includes(sig.guardianAddr)
        );

        if (validSigs.length === 0)
          throw new Error('No valid signatures found. Cannot proceed.');
    ```

4. **Convert valid signatures**: Ensure signatures are correctly formatted for verification. Convert hex-encoded signatures if necessary and extract their components.

    ```typescript
        const formattedSigs = validSigs
          .map((sig) => {
            try {
              const sigBuffer = Buffer.from(sig.signature, 'base64');
              // If it's 130 bytes, it's hex-encoded and needs conversion
              const sigBuffer1 =
                sigBuffer.length === 130
                  ? Buffer.from(sigBuffer.toString(), 'hex')
                  : sigBuffer;

              const r = BigInt('0x' + sigBuffer1.subarray(0, 32).toString('hex'));
              const s = BigInt('0x' + sigBuffer1.subarray(32, 64).toString('hex'));
              const vRaw = sigBuffer1[64];
              const v = vRaw < 27 ? vRaw : vRaw - 27;

              return {
                guardianIndex: currentGuardians.indexOf(sig.guardianAddr),
                signature: new Signature(r, s, v),
              };
            } catch (error) {
              console.error(
                `Failed to process signature for guardian: ${sig.guardianAddr}`,
                error
              );
              return null;
            }
          })
          .filter(
            (sig): sig is { guardianIndex: number; signature: Signature } =>
              sig !== null
          ); // Remove null values
    ```

5. **Deserialize the VAA**: Convert the raw VAA data into a structured format for further processing.

    ```typescript
        let parsedVaa: VAA<'Uint8Array'>;
        try {
          parsedVaa = deserialize('Uint8Array', vaa);
        } catch (error) {
          throw new Error(`Error deserializing VAA: ${error}`);
        }
    ```

6. **Identify outdated signatures**: Compare the current VAA signatures with the newly formatted ones to detect which signatures belong to outdated Guardians. Remove these outdated signatures to ensure only valid ones remain.

    ```typescript
        const outdatedGuardianIndexes = parsedVaa.signatures
          .filter(
            (vaaSig) =>
              !formattedSigs.some(
                (sig) => sig.guardianIndex === vaaSig.guardianIndex
              )
          )
          .map((sig) => sig.guardianIndex);

        console.log('Outdated Guardian Indexes:', outdatedGuardianIndexes);

        let updatedSignatures = parsedVaa.signatures.filter(
          (sig) => !outdatedGuardianIndexes.includes(sig.guardianIndex)
        );
    ```

7. **Replace outdated signatures**: Substitute outdated signatures with valid ones while maintaining the correct number of signatures. If there aren’t enough valid replacements, execution stops.

    ```typescript
        const validReplacements = formattedSigs.filter(
          (sig) =>
            !updatedSignatures.some((s) => s.guardianIndex === sig.guardianIndex)
        );

        // Check if we have enough valid signatures to replace outdated ones**
        if (outdatedGuardianIndexes.length > validReplacements.length) {
          console.warn(
            `Not enough valid replacement signatures! Need ${outdatedGuardianIndexes.length}, but only ${validReplacements.length} available.`
          );
          return;
        }

        updatedSignatures = [
          ...updatedSignatures,
          ...validReplacements.slice(0, outdatedGuardianIndexes.length),
        ];

        updatedSignatures.sort((a, b) => a.guardianIndex - b.guardianIndex);
    ```

8. **Serialize the updated VAA**: Reconstruct the VAA with the updated signatures and convert it into a format suitable for submission.

    ```typescript
        const updatedVaa: VAA<'Uint8Array'> = {
          ...parsedVaa,
          guardianSet: guardianSetIndex,
          signatures: updatedSignatures,
        };

        let patchedVaa: Uint8Array;
        try {
          patchedVaa = serialize(updatedVaa);
        } catch (error) {
          throw new Error(`Error serializing updated VAA: ${error}`);
        }
    ```

9. **Send the updated VAA for verification and handle errors**: Submit the updated VAA to an Ethereum RPC node for validation, ensuring it can be proposed for Guardian approval. If an error occurs during submission or signature replacement, log the issue and prevent further execution.

    ```typescript
        try {
          if (!(patchedVaa instanceof Uint8Array))
            throw new Error('Patched VAA is not a Uint8Array!');

          const vaaHex = `0x${Buffer.from(patchedVaa).toString('hex')}`;

          console.log('Sending updated VAA to RPC...');

          const result = await axios.post(RPC, {
            jsonrpc: '2.0',
            id: 1,
            method: 'eth_call',
            params: [
              {
                from: null,
                to: ETH_CORE,
                data: eth.abi.encodeFunctionCall(PARSE_AND_VERIFY_VM_ABI, [vaaHex]),
              },
              'latest',
            ],
          });

          const verificationResult = result.data.result;
          console.log('Updated VAA (hex):', vaaHex);
          return verificationResult;
        } catch (error) {
          throw new Error(`Error sending updated VAA to RPC: ${error}`);
        }
    ```

???- code "Complete Function"
    ```typescript
    export async function replaceSignatures(
      vaa: string | Uint8Array<ArrayBufferLike>,
      observations: { guardianAddr: string; signature: string }[],
      currentGuardians: string[],
      guardianSetIndex: number
    ) {
      console.log('Replacing Signatures...');

      try {
        if (!vaa) throw new Error('VAA is undefined or empty.');
        if (currentGuardians.length === 0)
          throw new Error('Guardian set is empty.');
        if (observations.length === 0) throw new Error('No observations provided.');

        const validSigs = observations.filter((sig) =>
          currentGuardians.includes(sig.guardianAddr)
        );

        if (validSigs.length === 0)
          throw new Error('No valid signatures found. Cannot proceed.');

        const formattedSigs = validSigs
          .map((sig) => {
            try {
              const sigBuffer = Buffer.from(sig.signature, 'base64');
              // If it's 130 bytes, it's hex-encoded and needs conversion
              const sigBuffer1 =
                sigBuffer.length === 130
                  ? Buffer.from(sigBuffer.toString(), 'hex')
                  : sigBuffer;

              const r = BigInt('0x' + sigBuffer1.subarray(0, 32).toString('hex'));
              const s = BigInt('0x' + sigBuffer1.subarray(32, 64).toString('hex'));
              const vRaw = sigBuffer1[64];
              const v = vRaw < 27 ? vRaw : vRaw - 27;

              return {
                guardianIndex: currentGuardians.indexOf(sig.guardianAddr),
                signature: new Signature(r, s, v),
              };
            } catch (error) {
              console.error(
                `Failed to process signature for guardian: ${sig.guardianAddr}`,
                error
              );
              return null;
            }
          })
          .filter(
            (sig): sig is { guardianIndex: number; signature: Signature } =>
              sig !== null
          ); // Remove null values

        let parsedVaa: VAA<'Uint8Array'>;
        try {
          parsedVaa = deserialize('Uint8Array', vaa);
        } catch (error) {
          throw new Error(`Error deserializing VAA: ${error}`);
        }

        const outdatedGuardianIndexes = parsedVaa.signatures
          .filter(
            (vaaSig) =>
              !formattedSigs.some(
                (sig) => sig.guardianIndex === vaaSig.guardianIndex
              )
          )
          .map((sig) => sig.guardianIndex);

        console.log('Outdated Guardian Indexes:', outdatedGuardianIndexes);

        let updatedSignatures = parsedVaa.signatures.filter(
          (sig) => !outdatedGuardianIndexes.includes(sig.guardianIndex)
        );

        const validReplacements = formattedSigs.filter(
          (sig) =>
            !updatedSignatures.some((s) => s.guardianIndex === sig.guardianIndex)
        );

        // Check if we have enough valid signatures to replace outdated ones**
        if (outdatedGuardianIndexes.length > validReplacements.length) {
          console.warn(
            `Not enough valid replacement signatures! Need ${outdatedGuardianIndexes.length}, but only ${validReplacements.length} available.`
          );
          return;
        }

        updatedSignatures = [
          ...updatedSignatures,
          ...validReplacements.slice(0, outdatedGuardianIndexes.length),
        ];

        updatedSignatures.sort((a, b) => a.guardianIndex - b.guardianIndex);

        const updatedVaa: VAA<'Uint8Array'> = {
          ...parsedVaa,
          guardianSet: guardianSetIndex,
          signatures: updatedSignatures,
        };

        let patchedVaa: Uint8Array;
        try {
          patchedVaa = serialize(updatedVaa);
        } catch (error) {
          throw new Error(`Error serializing updated VAA: ${error}`);
        }

        try {
          if (!(patchedVaa instanceof Uint8Array))
            throw new Error('Patched VAA is not a Uint8Array!');

          const vaaHex = `0x${Buffer.from(patchedVaa).toString('hex')}`;

          console.log('Sending updated VAA to RPC...');

          const result = await axios.post(RPC, {
            jsonrpc: '2.0',
            id: 1,
            method: 'eth_call',
            params: [
              {
                from: null,
                to: ETH_CORE,
                data: eth.abi.encodeFunctionCall(PARSE_AND_VERIFY_VM_ABI, [vaaHex]),
              },
              'latest',
            ],
          });

          const verificationResult = result.data.result;
          console.log('Updated VAA (hex):', vaaHex);
          return verificationResult;
        } catch (error) {
          throw new Error(`Error sending updated VAA to RPC: ${error}`);
        }
      } catch (error) {
        console.error('Unexpected error in replaceSignatures:', error);
      }
    }
    ```

## Create Script to Replace Outdated VAA Signatures

Now that we have all the necessary helper functions, we will create a script to automate replacing outdated VAA signatures. This script will retrieve a transaction’s VAA sequentially, check its validity, fetch the latest Guardian set, and update its signatures. By the end, it will output a correctly signed VAA that can be proposed for Guardian approval.

1. **Open the file**: Inside `src/scripts/replaceSignatures.ts`, import the required helper functions needed to process the VAAs.

    ```typescript title="src/scripts/replaceSignatures.ts"
    import {
      fetchVaaId,
      fetchVaa,
      checkVaaValidity,
      fetchObservations,
      fetchGuardianSet,
      replaceSignatures,
    } from '../helpers/vaaHelper';
    import { TXS } from '../config/constants';
    ```

2. **Define the main execution function**: Add the following function inside `src/scripts/replaceSignatures.ts` to process each transaction in `TXS`, going step by step through the signature replacement process.

    ```typescript
    async function main() {
      try {
        for (const tx of TXS) {
          console.log(`\nProcessing TX: ${tx}\n`);

          // 1. Fetch Transaction VAA IDs:
          const vaaIds = await fetchVaaId([tx]);
          if (!vaaIds.length) continue;

          // 2. Fetch VAA Data:
          const vaaData = await fetchVaa(vaaIds);
          if (!vaaData.length) continue;

          const vaaBytes = vaaData[0].vaaBytes;
          if (!vaaBytes) continue;

          // 3. Check VAA Validity:
          const { valid } = await checkVaaValidity(vaaBytes);
          if (valid) continue;

          // 4. Fetch Observations (VAA signatures):
          const observations = await fetchObservations(vaaIds[0]);

          // 5. Fetch Current Guardian Set:
          const [currentGuardians, guardianSetIndex] = await fetchGuardianSet();

          // 6. Replace Signatures:
          const response = await replaceSignatures(
            Buffer.from(vaaBytes, 'base64'),
            observations,
            currentGuardians,
            guardianSetIndex
          );

          if (!response) continue;
        }
      } catch (error) {
        console.error('❌ Error in execution:', error);
        process.exit(1);
      }
    }
    ```

3. **Make the script executable**: Ensure it runs when executed.

    ```typescript
    main();
    ```

    To run the script, use the following command:

    ```bash
    npx tsx src/scripts/replaceSignatures.ts
    ```

    <div id="termynal" data-termynal>
    	<span data-ty="input"><span class="file-path"></span>npx tsx src/scripts/replaceSignatures.ts</span>
    	<span data-ty> </span>
    	<span data-ty>Processing TX: 0x3ad91ec530187bb2ce3b394d587878cd1e9e037a97e51fbc34af89b2e0719367</span>
        <span data-ty>❌ VAA Valid: false, Reason: VM signature invalid</span>
        <span data-ty>Fetching observations</span>
        <span data-ty>Fetching current guardian set</span>
        <span data-ty>Replacing Signatures...</span>
        <span data-ty>Outdated Guardian Indexes: [ 0 ]</span>
        <span data-ty>Sending updated VAA to RPC...</span>
        <span data-ty>Updated VAA (hex): 0x01000000040d010019447b72d51e33923a3d6b28496ccd3722d5f1e33e2...</span>
    	<span data-ty="input"><span class="file-path"></span></span>
    </div>
The script logs each step, skipping valid VAAs, replacing outdated signatures for invalid VAAs, and logging any errors. It then completes with a valid VAA ready for submission.

## Resources

You can explore the complete project and find all necessary scripts and configurations in Wormhole's [demo GitHub repository](https://github.com/wormhole-foundation/demo-vaa-signature-replacement){target=\_blank}.

The demo repository includes a bonus script to check the VAA redemption status on Ethereum and Solana, allowing you to verify whether a transaction has already been redeemed on the destination chain.

## Conclusion

You've successfully built a script to fetch, validate, and replace outdated signatures in VAAs using Wormholescan and the Wormhole SDK.

It's important to note that this tutorial does not update VAAs in the Wormhole network. Before redeeming the VAA, you must propose it for Guardian approval to finalize the process.

Looking for more? Check out the [Wormhole Tutorial Demo repository](https://github.com/wormhole-foundation/demo-tutorials){target=\_blank} for additional examples.


---

Page Title: Routes

- Resolved Markdown: https://wormhole.com/docs/ai/pages/products-connect-concepts-routes.md
- Canonical (HTML): https://wormhole.com/docs/products/connect/concepts/routes/
- Summary: Explore Wormhole Connect's routing capabilities for asset transfers, featuring WTT, CCTP, NTT, and various blockchain-specific routes for optimal UX.
- Word Count: 1132; Token Estimate: 1602

## Routes Overview {: #routes-overview}

This page explains the concept of routes in Wormhole Connect. To configure routes for your widget, check the [Wormhole Connect Configuration](/docs/products/connect/configuration/data/){target=\_blank}.

Routes are methods by which the widget will transfer the assets. Wormhole Connect supports Wrapped Token Transfers (WTT) for transferring any arbitrary token, and for specific tokens, it also supports more advanced transfer methods that provide superior UX.

When you select the source chain, source token, and destination chain, Wormhole Connect will display the best routes available for that particular combination. In practice, if routes other than WTT are available, only those will be displayed. Check the [feature matrix](/docs/products/connect/reference/support-matrix/){target=\_blank} to see under which exact conditions the routes appear.

!!! note "Terminology" 
    The SDK and smart contracts use the name Token Bridge. In documentation, this product is referred to as Wrapped Token Transfers (WTT). Both terms describe the same protocol.

## WTT Routes {: #wtt-routes}

WTT locks assets on the source chain and mints Wormhole-wrapped "IOU" tokens on the destination chain. To transfer the assets back, the Wormhole-wrapped tokens are burned, unlocking the tokens on their original chain.

#### Manual Route {: #manual-route}

The manual route transfer method requires two transactions: one on the origin chain to lock the tokens (or burn the Wormhole-wrapped tokens) and one on the destination chain to mint the Wormhole-wrapped tokens (or unlock the original tokens). To offer this option, enable the `bridge` route in the configuration.

#### Automatic Route {: #automatic-route}

Trustless relayers can execute the second transaction on the user's behalf, so the user only needs to perform one transaction on the origin chain to have the tokens delivered to the destination automatically - for a small fee. Wormhole Connect automatically detects whether the relayer supports a token and will display the option if the `relay` route is enabled in the configuration.

## CCTP Routes (USDC) {: #cctp-routes-usdc}
 
[Circle](https://www.circle.com/){target=\_blank}, the issuer of USDC, provides a native way for native USDC to be transferred between [CCTP-enabled](https://www.circle.com/cross-chain-transfer-protocol){target=\_blank} chains. Wormhole Connect can facilitate such transfers.

Note that if native USDC is transferred from the CCTP-enabled chains to any other outside of this list, the transfer will be routed through WTT, and the resulting asset will be a Wormhole-wrapped token instead of native USDC.

#### Manual Route {: #manual-route-cctp}

This transfer method requires two transactions: one on the origin chain to burn the USDC and one on the destination chain to mint the USDC. The manual CCTP route relies on CCTP only and doesn't use Wormhole messaging in the background. Enable the `cctpManual` route in the configuration to offer this option.

#### Automatic Route {: #automatic-route-cctp}

Trustless relayers can execute the second transaction on the user's behalf. Therefore, the user only needs to perform one transaction on the origin chain to have the tokens delivered to the destination automatically—for a small fee. To offer this option, enable the `cctpRelay` route in the configuration.

## Native Token Transfers (NTT) Routes {: #native-token-transfers-ntt-routes}

[Wormhole's Native Token Transfer (NTT) framework](https://github.com/wormhole-foundation/native-token-transfers/){target=\_blank} enables token issuers to retain full ownership of their tokens across any number of chains, unlike WTT. The token issuer must deploy NTT contracts, and Wormhole Connect needs to be [configured](/docs/products/connect/configuration/data/){target=\_blank} with the appropriate `nttGroups` before such tokens are recognized as transferrable via NTT. Refer to the [documentation in the NTT repository](https://github.com/wormhole-foundation/native-token-transfers?tab=readme-ov-file#overview){target=\_blank} for more information about the contracts needed and the framework in general.

#### Manual Route {: #manual-route-ntt}

This transfer method requires two transactions: one on the origin chain to burn or lock the tokens and one on the destination chain to mint them. To offer this option, enable the `nttManual` route in the configuration.

#### Automatic Route  {: #automatic-route-ntt}

Trustless relayers can execute the second transaction on the user's behalf, so the user only needs to perform one transaction on the origin chain to have the tokens delivered to the destination automatically—for a small fee. Wormhole Connect automatically detects whether the relayer supports a token and will display the option if the `nttRelay` route is enabled in the configuration.

## ETH Bridge Route for Native ETH and wstETH {: #eth-bridge-route-for-native-eth-and-wsteth}

[Powered by Uniswap liquidity pools](https://github.com/wormhole-foundation/example-uniswap-liquidity-layer){target=\_blank}, this route can transfer native ETH or wstETH between certain EVMs without going through the native bridges. For example, you can transfer native ETH from Arbitrum to Optimism and end up with Optimism ETH all in one go. Supported chains are Ethereum, Arbitrum, Optimism, Base, Polygon (canonical wETH), BSC (canonical wETH), and Avalanche (canonical wETH).

#### Automatic Route {: #automatic-route-eth}

Only the relayed route is available due to the complexity of the transaction that needs to be executed at the destination. To offer this option, enable the `ethBridge` and/or `wstETHBridge` route in the configuration.

## USDT Bridge Route {: #usdt-bridge-route}

Operating on the same technology as the ETH Bridge, this route can transfer USDT between certain EVMs without going through the native bridges. The resulting token will be the canonical USDT token on the destination instead of the Wormhole-wrapped variant. Supported chains are Ethereum, Polygon, Avalanche, Arbitrum, Optimism, BSC, and Base.

#### Automatic Route {: #automatic-route-usdt}

Only the relayed route is available due to the complexity of the transaction that needs to be executed on the destination. Enable the `usdtBridge` route in the configuration to offer this option.

## tBTC Route {: #tbtc-route}

You can bridge [Threshold's Bitcoin](https://www.threshold.network/){target=\_blank} via this hybrid solution that combines WTT and Threshold's contracts. Native tBTC is first locked in the Wormhole WTT, transferred to the destination in the form of Wormhole-wrapped tBTC, which is then immediately locked in Threshold's contract that mints native tBTC for it. The net result is that the user ends up with native tBTC on chains where this Threshold contract is deployed (e.g., Solana, Polygon, Arbitrum, Optimism, or Base).

Note that if native tBTC is transferred out of these chains to any other outside of this list, the transfer will be routed through WTT, and the resulting asset will be a Wormhole-wrapped token instead of native tBTC.

#### Manual Route {: #manual-route-tbtc}

This transfer method requires two transactions: one on the origin chain to burn or lock the tokens and one on the destination chain to mint them. To provide this option, enable the `tbtc` route in the configuration.


---

Page Title: Security

- Resolved Markdown: https://wormhole.com/docs/ai/pages/protocol-security.md
- Canonical (HTML): https://wormhole.com/docs/protocol/security/
- Summary: Explore Wormhole's security features, including the Guardian network, governance, monitoring, open-source development, and bug bounty programs.
- Word Count: 1268; Token Estimate: 1909

# Security

## Core Security Assumptions

At its core, Wormhole is secured by a network of [Guardian](/docs/protocol/infrastructure/guardians/){target=\_blank} nodes that validate and sign messages. If a super majority (e.g., 13 out of 19) of Guardians sign the same message, it can be considered valid. A smart contract on the target chain will verify the signatures and format of the message before approving any transaction.

- Wormhole's core security primitive is its signed messages (signed [VAAs](/docs/protocol/infrastructure/vaas/){target=\_blank}).
- The Guardian network is currently secured by a collection of 19 of the world's top [validator companies](https://wormhole-foundation.github.io/wormhole-dashboard/#/?endpoint=Mainnet){target=\_blank}.
- Guardians produce signed state attestations (signed VAAs) when requested by a Core Contract integrator.
- Every Guardian runs full nodes (rather than light nodes) of every blockchain in the Wormhole network, so if a blockchain suffers a consensus attack or hard fork, the blockchain will disconnect from the network rather than potentially produce invalid signed VAAs.
- Any Signed VAA can be verified as authentic by the Core Contract of any other chain.
- The [Executor](/docs/protocol/infrastructure/relayers/executor-framework/){target=\_blank} is considered untrusted in the Wormhole ecosystem. It can affect message availability (timing of delivery) but cannot alter or forge VAAs, as validity is enforced by Guardian signatures.

In summary:

- **Core integrators are not exposed to risk from chains and contracts they do not integrate with**.
- By default, you only trust Wormhole's signing process and the core contracts of the chains you're on.
- You can expand your contract and chain dependencies as you see fit.

Core assumptions aside, many other factors impact the real-world security of decentralized platforms. Here is more information on additional measures that have been put in place to ensure the security of Wormhole.

## Guardian Network

Wormhole is an evolving platform. While the canonical Guardian set consists of 19 members, not all chains require all 19 Guardians to perform direct on-chain observation. For delegated chains, a delegated subset of Guardians performs direct on-chain observation while the final VAA signature threshold remains 13-of-19.

Delegated Guardian Sets introduces a per-chain trust assumption: the delegate quorum threshold determines how many Delegated Guardians must independently agree before Canonical Guardians sign. This model does not weaken the final 13-of-19 VAA requirement, but it means the observation layer for that chain depends on fewer nodes. The `WormholeDelegatedGuardians` governance contract allows these thresholds to be adjusted as network requirements evolve.

### Governance

Governance is the process through which contract upgrades happen. Guardians manually vote on governance proposals that originate inside the Guardian Network and are then submitted to ecosystem contracts.

This means that governance actions are held to the same security standard as the rest of the system. A two-thirds supermajority of the Guardians is required to pass any governance action.

Governance messages can target any of the various wormhole modules, including the core contracts and all currently deployed Wrapped Token Transfers (WTT) contracts. When a Guardian signs such a message, its signature implies a vote on the action in question. Once more than two-thirds of the Guardians have signed, the message and governance action are considered valid.

All governance actions and contract upgrades have been managed via Wormhole's on-chain governance system.

Via governance, the Guardians can:

- Change the current Guardian set.
- Expand the Guardian set.
- Upgrade ecosystem contract implementations.
- Configure per-chain Delegated Guardian sets and security thresholds via the `WormholeDelegatedGuardians` contract.

The governance system is fully open source in the core repository. See the [Open Source section](#open-source){target=\_blank} for contract source.

## Monitoring

A key element of Wormhole's defense-in-depth strategy is that each Guardian is a highly competent validator company with its own in-house processes for running, monitoring, and securing blockchain operations. This heterogeneous approach to monitoring increases the likelihood that fraudulent activity is detected and reduces the number of single failure points in the system.

For full Guardian Set chains, all Guardians run full nodes and independently monitor block production and contract activity. For delegated chains, Delegated Guardians perform direct on-chain monitoring while Canonical Guardians monitor delegate observations and enforce quorum safeguards.

Guardians monitor:

- **Block production and consensus of each blockchain**: If a blockchain's consensus is violated, it will be disconnected from the network until the Guardians resolve the issue.
- **Smart contract level data**: Via processes like the Governor, Guardians constantly monitor the circulating supply and token movements across all supported blockchains.
- **Guardian level activity**: The Guardian Network functions as an autonomous decentralized computing network, ensuring independent security measures across its validators.

## Asset Layer Protections

One key strength of the Wormhole ecosystem is the Guardians' ability to validate and protect the integrity of assets across multiple blockchains.

To enforce the Wormhole Asset Layer's core protections, the Global Accountant tracks the total circulating supply of all Wormhole assets across all chains, preventing any blockchain from bridging assets that could violate the supply invariant.

For delegated chains, delegate quorum must be reached before Canonical Guardians contribute signatures, ensuring that per-chain delegate thresholds are respected without altering the Global Accountant's 13-of-19 security model.

In addition to the Global Accountant, Guardians may only sign transfers that do not violate the requirements of the Governor. The [Governor](https://github.com/wormhole-foundation/wormhole/blob/main/whitepapers/0007_governor.md){target=\_blank} tracks inflows and outflows of all blockchains and delays suspicious transfers that may indicate an exploit.

## Open Source

Wormhole builds in the open and is always open source.

- **[Wormhole core repository](https://github.com/wormhole-foundation/wormhole){target=\_blank}**
- **[Wormhole Foundation GitHub organization](https://github.com/wormhole-foundation){target=\_blank}**
- **[Wormhole contract deployments](/docs/protocol/infrastructure/core-contracts/){target=\_blank}**

## Audits

Wormhole has been heavily audited, with _29 third-party audits completed_ and more started. Audits have been performed by the following firms:

- [Trail of Bits](https://www.trailofbits.com/){target=\_blank}
- [Neodyme](https://neodyme.io/en/){target=\_blank}
- [Kudelski](https://kudelskisecurity.com/){target=\_blank}
- [OtterSec](https://osec.io/){target=\_blank}
- [Certik](https://www.certik.com/){target=\_blank}
- [Hacken](https://hacken.io/){target=\_blank}
- [Zellic](https://www.zellic.io/){target=\_blank}
- [Coinspect](https://www.coinspect.com/){target=\_blank}
- [Halborn](https://www.halborn.com/){target=\_blank}
- [Cantina](https://cantina.xyz/welcome){target=\_blank}

All audits and final reports can be found in [security page of the GitHub Repo](https://github.com/wormhole-foundation/wormhole/blob/main/SECURITY.md#3rd-party-security-audits){target=\_blank}.

## Bug Bounties

Wormhole has one of the largest bug bounty programs in software development and has repeatedly shown commitment to engaging with the white hat community.

Wormhole runs a bug bounty program through [Immunefi](https://immunefi.com/bug-bounty/wormhole/){target=\_blank} program, with a top payout of **5 million dollars**.

If you are interested in contributing to Wormhole security, please look at this section for [Getting Started as a White Hat](https://github.com/wormhole-foundation/wormhole/blob/main/SECURITY.md#white-hat-hacking){target=\_blank}, and follow the [Wormhole Contributor Guidelines](https://github.com/wormhole-foundation/wormhole/blob/main/CONTRIBUTING.md){target=\_blank}.

For more information about submitting to the bug bounty programs, refer to the [Wormhole Immunefi page](https://immunefi.com/bug-bounty/wormhole/){target=\_blank}.

## Next Steps

<div class="grid cards" markdown>

-   :octicons-book-16:{ .lg .middle } **View Latest Security Policies**

    ---

    The `SECURITY.md` from the official Wormhole repository on GitHub has the latest security policies and updates.

    [:custom-arrow: See SECURITY.md](https://github.com/wormhole-foundation/wormhole/blob/main/SECURITY.md){target=\_blank}

</div>


---

Page Title: Solana Message Emission via Shim

- Resolved Markdown: https://wormhole.com/docs/ai/pages/products-messaging-guides-solana-shims-sol-emission.md
- Canonical (HTML): https://wormhole.com/docs/products/messaging/guides/solana-shims/sol-emission/
- Summary: Learn how to reduce rent costs when emitting Wormhole messages on Solana by using the emission shim instead of post_message.
- Word Count: 1220; Token Estimate: 2148

# Solana Message Emission via Shim

The emission shim is a lightweight Solana program that lets integrators emit Wormhole messages without creating a new rent-exempt account for every message. It passes an empty payload to the core bridge and emits the message data through transaction logs, reducing rent costs and avoiding state bloat while remaining fully compatible with Guardian observation.

Migrating from the legacy path is straightforward: no account resizing is needed, and programs can call the shim directly. The Wormhole fee is still paid through the `fee_collector`, with the same parallelization limits as before. 

Guardians are configured to observe the canonical shim address, reading message data, emitter, and nonce from the transaction logs and CPI events, rather than on-chain accounts. They also ignore the empty core bridge payload to prevent duplicate VAAs. On mainnet, all 19 Guardians support shim emissions, and, as with all Wormhole messages, at least 13 attestations are required for a valid VAA.

!!!note
    For on-chain programs that only call the shim via CPI, consider emitting a dummy/empty message after migration to avoid edge cases with initial CPI depth (Solana limits the depth of cross-program calls).

For more background, see [Emission Shim concept section](/docs/products/messaging/concepts/solana-shim/#emission-shim){target=\_blank}. 

## Prerequisites

To interact with the emission shim, you'll need the following:

- [Rust and Solana CLI](https://solana.com/docs/intro/installation){target=\_blank} installed.  
- [Anchor installed](https://www.anchor-lang.com/docs/installation){target=\_blank}.
- The canonical emission shim program already deployed at [`EtZMZM22ViKMo4r5y4Anovs3wKQ2owUmDpjygnMMcdEX`](https://explorer.solana.com/address/EtZMZM22ViKMo4r5y4Anovs3wKQ2owUmDpjygnMMcdEX){target=\_blank}.
- The shim’s [IDL](https://github.com/wormhole-foundation/wormhole/blob/main/svm/wormhole-core-shims/anchor/idls/wormhole_post_message_shim.json){target=\_blank} for wiring accounts.
- A payer (signer) funded with enough SOL to cover compute and message fees.

## Setup

To start, import the shim crate to call `wormhole_post_message_shim::cpi::post_message`. Then, pull the core bridge addresses needed to be passed along.

```rs
declare_program!(wormhole_post_message_shim);

use anchor_lang::prelude::*;

use wormhole_post_message_shim::{program::WormholePostMessageShim, types::Finality};
use wormhole_solana_consts::{
    CORE_BRIDGE_CONFIG, CORE_BRIDGE_FEE_COLLECTOR, CORE_BRIDGE_PROGRAM_ID,
};
```

## Accounts

When calling the shim’s `post_message` instruction, you need to pass:

- **`bridge`**: Holds the Wormhole core bridge config.
- **`message`**: Represents the PDA derived from the emitter and is reused by the shim instead of generating new accounts.
- **`emitter`**: Serves as the emitter address (signer).
- **`sequence`**: Tracks the emitter's sequence account.
- **`payer`**: Pays compute and any rent needed on first use (signer).
- **`fee_collector`**: Collects the Wormhole message fee.
- **`clock`**: Provides the current Solana time from the sysvar.
- **`system_program`**: Supplies the standard Solana system program for account creation on first use.
- **`wormhole_program`**: Points to the Wormhole core bridge program.
- **`event_authority`**: Acts as the PDA used by the shim to emit log events (Anchor CPI events).
- **`program`**: Specifies the shim program itself.

The struct below defines the accounts required by your instruction and wires the shim to the core bridge, ensuring the emitter PDA can sign the CPI via seeds.

```rs
#[derive(Accounts)]
pub struct PostMessage<'info> {
    #[account(mut)]
    payer: Signer<'info>,

    wormhole_post_message_shim: Program<'info, WormholePostMessageShim>,

    #[account(mut, address = CORE_BRIDGE_CONFIG)]
    /// CHECK: Wormhole bridge config. [`wormhole::post_message`] requires this account be mutable.
    /// Address constraint added for IDL generation / convenience, it will be enforced by the core bridge.
    pub bridge: UncheckedAccount<'info>,

    #[account(mut, seeds = [&emitter.key.to_bytes()], bump, seeds::program = wormhole_post_message_shim::ID)]
    /// CHECK: Wormhole Message. [`wormhole::post_message`] requires this account be signer and mutable.
    /// Seeds constraint added for IDL generation / convenience, it will be enforced by the shim.
    pub message: UncheckedAccount<'info>,

    #[account(seeds = [b"emitter"], bump)]
    /// CHECK: Our emitter
    /// Seeds constraint added for IDL generation / convenience, it will be enforced to match the signer used in the CPI call.
    pub emitter: UncheckedAccount<'info>,

    #[account(mut)]
    /// CHECK: Emitter's sequence account. [`wormhole::post_message`] requires this account be mutable.
    /// Explicitly do not re-derive this account. The core bridge verifies the derivation anyway and
    /// as of Anchor 0.30.1, auto-derivation for other programs' accounts via IDL doesn't work.
    pub sequence: UncheckedAccount<'info>,

    #[account(mut, address = CORE_BRIDGE_FEE_COLLECTOR)]
    /// CHECK: Wormhole fee collector. [`wormhole::post_message`] requires this account be mutable.
    /// Address constraint added for IDL generation / convenience, it will be enforced by the core bridge.
    pub fee_collector: UncheckedAccount<'info>,

    /// Clock sysvar.
    /// Type added for IDL generation / convenience, it will be enforced by the core bridge.
    pub clock: Sysvar<'info, Clock>,

    /// System program.
    /// Type for IDL generation / convenience, it will be enforced by the core bridge.
    pub system_program: Program<'info, System>,

    #[account(address = CORE_BRIDGE_PROGRAM_ID)]
    /// CHECK: Wormhole program.
    /// Address constraint added for IDL generation / convenience, it will be enforced by the shim.
    pub wormhole_program: UncheckedAccount<'info>,

    /// CHECK: Shim event authority
    /// TODO: An address constraint could be included if this address was published to wormhole_solana_consts
    /// Address will be enforced by the shim.
    pub wormhole_post_message_shim_ea: UncheckedAccount<'info>,
}
```

This instruction reuses a single per-emitter message PDA (no per-message rent). When invoked, the shim emits your payload as an Anchor CPI event and, in the same transaction, calls the core bridge with an empty payload, allowing the core bridge to still assign the sequence and enforce fees/finality. Guardians read the Core call (sequence/finality) and the shim event (payload) from the transaction logs, producing a standard VAA without leaving a persistent message account.

## Call post_message

The `post_message` function builds a `CpiContext` and invokes the shim’s `post_message` instruction, forwarding the nonce, finality, and your payload. The Core Bridge enforces fee requirements and assigns the sequence, while the shim emits the payload as an event in the same transaction.

```rs
pub fn post_message(ctx: Context<PostMessage>) -> Result<()> {
    // wormhole::post_message may require that a fee be sent to the fee_collector account of the core bridge.
    // The following code could be used to handle this via CPI call.
    // However, this example handles this complexity on the client side using a `preInstruction`
    //
    // let fee = ctx.accounts.wormhole_bridge.fee();
    // if fee > 0 {
    //     solana_program::program::invoke(
    //         &solana_program::system_instruction::transfer(
    //             &ctx.accounts.payer.key(),
    //             &ctx.accounts.fee_collector.key(),
    //             fee,
    //         ),
    //         &ctx.accounts.to_account_infos(),
    //     )?;
    // }

    wormhole_post_message_shim::cpi::post_message(
        CpiContext::new_with_signer(
            ctx.accounts.wormhole_post_message_shim.to_account_info(),
            wormhole_post_message_shim::cpi::accounts::PostMessage {
                payer: ctx.accounts.payer.to_account_info(),
                bridge: ctx.accounts.bridge.to_account_info(),
                message: ctx.accounts.message.to_account_info(),
                emitter: ctx.accounts.emitter.to_account_info(),
                sequence: ctx.accounts.sequence.to_account_info(),
                fee_collector: ctx.accounts.fee_collector.to_account_info(),
                clock: ctx.accounts.clock.to_account_info(),
                system_program: ctx.accounts.system_program.to_account_info(),
                wormhole_program: ctx.accounts.wormhole_program.to_account_info(),
                program: ctx.accounts.wormhole_post_message_shim.to_account_info(),
                event_authority: ctx.accounts.wormhole_post_message_shim_ea.to_account_info(),
            },
            &[&[b"emitter", &[ctx.bumps.emitter]]],
        ),
        0,
        Finality::Finalized,
        b"your message goes here!".to_vec(),
    )?;

    Ok(())
}
```

## Limitations and Considerations 

- **Rent**: No persistent account rent is paid for every emission; the cost is now dominated by compute and the emission fee.
- **Logs**: Since all observability is log-based, re-observation is only possible while Solana transaction history is available.
- **Parallelization**: Still limited by the `fee_collector` account being mutable.
- **CPI Depth**: The first shim call for an emitter adds one extra stack depth. This is only relevant if you are near the Solana CPI limit (4).

## Conclusion

By using the emission shim, you can dramatically reduce rent costs when emitting Wormhole messages from Solana, while ensuring compatibility with Guardian observation and core bridge sequencing.

For a complete, working reference, see the full example implementation in the Wormhole repo: [`post_message.rs`](https://github.com/wormhole-foundation/wormhole/blob/main/svm/wormhole-core-shims/anchor/programs/wormhole-integrator-example/src/instructions/post_message.rs){target=\_blank}.


---

Page Title: Solana Shims

- Resolved Markdown: https://wormhole.com/docs/ai/pages/products-messaging-concepts-solana-shim.md
- Canonical (HTML): https://wormhole.com/docs/products/messaging/concepts/solana-shim/
- Summary: Understand how Wormhole uses shim programs on Solana to optimize message emission and VAA verification without modifying the Core Bridge.
- Word Count: 1769; Token Estimate: 2648

# Solana Shims

Wormhole shims on Solana are lightweight programs that enable cheaper and more flexible message emission and verification while preserving Guardian observation guarantees. They are designed for integrators who want to reduce Solana rent costs without sacrificing core protocol security or Guardian compatibility.

## The Core Bridge Account Problem

When you emit a message on Solana using the legacy [Wormhole core bridge](/docs/protocol/infrastructure/core-contracts/){target=\_blank}, it creates a new on-chain account, a Program Derived Address (PDA), for every message. Each of these accounts must hold enough SOL to be rent-exempt, locking up lamports that cannot be reclaimed since the core bridge does not allow these accounts to be closed. Over time, this results in two big problems:

- **Permanent On-Chain State**: Every message leaves behind a permanent account, increasing long-term storage needs on Solana.
- **Lost Lamports to Rent**: Integrators lose SOL for every message, as the lamports needed for rent exemption remain locked in the message accounts indefinitely.

Solana’s rent-exemption model isn't the fundamental limitation; the constraint lies in the legacy `post_message` function of the core bridge, which always creates a new, non-reclaimable account every time it’s called. Even after a message is consumed, these accounts can’t be closed or reused, resulting in unrecoverable rent costs.

Although the `post_message_unreliable` function allows account reuse, it comes with significant tradeoffs. Once a message is overwritten, it can no longer be recovered, making it no longer observable by Guardians. It also locks you into the original account size, as the feature predates Solana’s account resizing.

Verification has similar costs. The `post_vaa` instruction creates additional temporary accounts for signatures and VAA data, which, like the original accounts, require rent and aren’t automatically cleaned up. Over time, these add to both storage bloat and unrecoverable SOL.

This design ensures reliability, as message data is always available on-chain for Guardians to observe. However, it comes at a cost in both storage and lost SOL. To address these issues, Wormhole introduces Solana shims that fundamentally change the cost model for emissions and verification.

## What Are the Solana Shims?

To address the limitations of the core bridge, Wormhole deploys two specialized Solana programs called shims:

- **[Post Message Shim (`EtZMZM22ViKMo4r5y4Anovs3wKQ2owUmDpjygnMMcdEX`)](https://explorer.solana.com/address/EtZMZM22ViKMo4r5y4Anovs3wKQ2owUmDpjygnMMcdEX){target=\_blank}**: Emits Wormhole messages efficiently, without creating new message accounts for each emission, reducing rent costs.
- **[Verify VAA Shim (`EFaNWErqAtVWufdNb7yofSHHfWFos843DFpu4JBw24at`)](https://explorer.solana.com/address/EFaNWErqAtVWufdNb7yofSHHfWFos843DFpu4JBw24at){target=\_blank}**: Verifies VAAs on-chain without leaving permanent accounts.

Both act as lightweight wrappers around the existing core bridge. There are two different options, depending on whether you are emitting messages or verifying VAAs:

### Emission Shim

The [Emission Shim](/docs/products/messaging/guides/solana-shims/sol-emission/){target=\_blank} is a Solana program deployed at [`EtZMZM22ViKMo4r5y4Anovs3wKQ2owUmDpjygnMMcdEX`](https://explorer.solana.com/address/EtZMZM22ViKMo4r5y4Anovs3wKQ2owUmDpjygnMMcdEX){target=\_blank} which wraps the core bridge’s `post_message_unreliable` instruction. The Emission Shim emits message data as a log event rather than storing it in a rent-exempt message account, eliminating rent costs and preventing long-term state bloat. Guardians are configured to observe this canonical shim, allowing integrators to send messages through it without additional setup.

This shim works by calling the [`post_message`](https://github.com/wormhole-foundation/wormhole/blob/main/svm/wormhole-core-shims/anchor/idls/wormhole_post_message_shim.json){target=\_blank} instruction on the Post Message Shim program. This instruction emits the Wormhole message as a log event instead of creating a rent-exempt message account.

The shim differs from the standard `post_message` approach in two key ways. First, it utilizes a Program Derived Address (PDA) per emitter for message accounts, eliminating the need to generate a new key pair for each emission. Second, instead of writing the message to a persistent, rent-exempt account, it emits the data via an Anchor CPI event that Guardians can observe directly. This design reduces rent costs and prevents unused accounts from being left behind.

The shim works through a few main components:

- **Shim Program**: Provides a `post_message` instruction modeled on the core bridge’s `post_message_unreliable`.
- **Sequence Handling**: The core bridge continues to manage sequence numbers. It reads the sequence number from the core bridge and emits it in a [CPI event](https://www.anchor-lang.com/docs/basics/cpi){target=\_blank}, along with the timestamp.
- **Message Account**: Calls `post_message_unreliable` on the core bridge, writing an empty payload, so no unique message is stored on-chain.
- **Guardian Role**: Guardians reconstruct the message from instruction data and the emitted event, not from a persistent account.

```mermaid
graph LR
    A[Integrator Program]
    B[Emission Shim]
    C[Core Bridge]
    D[Guardians]

    A -- call post_message --> B
    B -- emits event & calls core --> C
    C -- instruction data & event --> D
```

The emission fee is still paid, and the core bridge continues to manage sequence numbers as before. The difference is that instead of creating a new message account for each emission, the shim emits a CPI event with the message data. All the information Guardians need is captured in the transaction logs, without leaving behind permanent accounts.

### Verification Shim 

The [Verification Shim](/docs/products/messaging/guides/solana-shims/sol-verification/){target=\_blank} is a Solana program deployed at [`EFaNWErqAtVWufdNb7yofSHHfWFos843DFpu4JBw24at`](https://explorer.solana.com/address/EFaNWErqAtVWufdNb7yofSHHfWFos843DFpu4JBw24at){target=\_blank}. It provides a [`verify_hash`](https://github.com/wormhole-foundation/wormhole/blob/4656bd4a72cb99f4e94a771a802856c9451af844/svm/wormhole-core-shims/programs/verify-vaa/src/lib.rs#L195){target=\_blank} instruction that checks Guardian signatures against the active Guardian set for a VAA's digest. It ensures quorum, validates each signature in order, recovers the public keys, and matches them against the Guardian set. If all checks pass, the VAA is verified without creating persistent rent-exempt accounts. This verification method replaces the use of the core bridge’s `post_vaa`. Integrators can call the canonical shim, but existing programs may need to be modified to adopt this approach.

It works by first calling the [`post_signatures`](https://github.com/wormhole-foundation/wormhole/blob/main/svm/wormhole-core-shims/anchor/idls/wormhole_verify_vaa_shim.json#L43){target=\_blank} on the Verification Shim to store Guardian signatures in a temporary account. Then, from within your program, call [`verify_hash`](https://github.com/wormhole-foundation/wormhole/blob/main/svm/wormhole-core-shims/programs/verify-vaa/README.md#verify-hash-technical-details){target=\_blank} to check the VAA’s digest against Guardian signatures. In the same transaction, close the signatures account with [`close_signatures`](https://github.com/wormhole-foundation/wormhole/blob/main/svm/wormhole-core-shims/anchor/idls/wormhole_verify_vaa_shim.json#L11){target=\_blank} to reclaim rent. 

Instead of the core bridge instructions, such as `verify_signatures` and `post_vaa`, the verification shim provides its own flow using `post_signatures`, `verify_hash`, and `close_signatures`. The flow is a simpler sequence that avoids leaving permanent accounts on-chain:


1. **Call `post_signatures`**: Creates (or appends to) a temporary `GuardianSignatures` account that stores the collected Guardian signatures. This account is owned and managed by the verification shim.
2. **Call `verify_hash`**: Verifies the digest of the VAA against the active Guardian set and checks quorum by recovering and validating each Guardian signature. If verification succeeds, your program can continue its logic.
3. **Call `close_signatures`**: Immediately closes the `GuardianSignatures` account to reclaim the lamports paid for its creation.


```mermaid
graph LR
    A[post_signatures] --> B[verify_hash]
    B --> C[Process Logic]
    C --> D[close_signatures]
```

This flow ensures verification is both rent-efficient and secure, no permanent accounts remain, and Guardians still enforce quorum and integrity guarantees.

## Guardian Observation Methods: Legacy vs. Shims

The following table compares how Guardians observe and verify messages on Solana before and after the introduction of the shims program.

| Observation Methods  | Legacy Model           | Shim Model               |
|----------------------|------------------------|--------------------------|
| Message Storage      | On-chain account       | Transaction logs (CPI)   |
| Data Permanence      | Permanent              | Until RPC history pruned |
| Guardian Observation | Reads account data     | Reads transaction logs   |
| Cost                 | High (rent + compute)  | Low (compute only)       |
| Closing Accounts     | Not possible           | Not needed               |

With shims, the message’s existence depends on the transaction log, so cost drops, but indefinite on-chain visibility is no longer guaranteed. Sequence tracking remains the same as the legacy model, so integrators can switch between the two without disrupting sequence numbers.

## Transaction Costs

Solana charges for two primary resources when processing transactions: 

- Compute units for execution.
- Rent for storing data on-chain. 

Understanding how each contributes to the overall cost is key to seeing why shims are cheaper.

- **Compute Units (CU)**: Solana measures CPU resource usage per transaction as “compute units”. Each transaction has a CU limit (usually ~200,000 — which can be increased for a fee).
- **Rent**: One-time cost in SOL to keep an account on-chain. Most of the core bridge’s cost comes from rent, not CUs.

Even though the shim uses slightly more compute (extra logic for logging), it avoids account creation entirely. Since rent is the most significant cost, the total emission cost drops.

## Safety, Tradeoffs & Limitations

Shims preserve the same security guarantees as the core bridge, so that integrators can adopt them without weakening protocol safety. The only difference is where data lives: instead of being stored permanently in message accounts, it is emitted in transaction logs or held temporarily until verification completes. Guardians are explicitly configured to observe shim output, ensuring messages and VAAs remain verifiable across the network.

The main tradeoff is durability. In the legacy model, messages and VAAs were always available on-chain for re-observation. With shims, message data persists only as long as RPC providers retain transaction history. This timeframe is sufficient for Guardian observation, but doesn’t provide indefinite public access to raw message data. Applications that rely on long-term on-chain storage may still prefer the legacy path, while most integrators benefit from the reduced cost and state bloat.

Finally, adopting shims may require some integration changes. For emission, developers should route messages through the Post Message Shim rather than directly through the core bridge. For verification, programs must update their logic to call `verify_hash` and manage temporary accounts in the same transaction. These are lightweight adjustments, but they are necessary to realize the cost savings fully.

## Next Steps

To put these concepts into practice, explore the dedicated guides for emission and verification on Solana.

<div class="grid cards" markdown>

-   :octicons-tools-16:{ .lg .middle } **Emit Messages**

    ---

    Learn how to reduce rent costs when emitting Wormhole messages on Solana by using the emission shim.

    [:custom-arrow: Use the Emission Shim](/docs/products/messaging/guides/solana-shims/sol-emission/)

-   :octicons-tools-16:{ .lg .middle } **Verify VAAs**

    ---

    Efficiently verify Wormhole VAAs on Solana using the verification shim, which avoids persistent rent-exempt accounts while keeping full security guarantees.

    [:custom-arrow: Use the Verification Shim](/docs/products/messaging/guides/solana-shims/sol-verification/)

</div>


---

Page Title: Solana VAA Verification via Shim

- Resolved Markdown: https://wormhole.com/docs/ai/pages/products-messaging-guides-solana-shims-sol-verification.md
- Canonical (HTML): https://wormhole.com/docs/products/messaging/guides/solana-shims/sol-verification/
- Summary: Efficiently verify Wormhole VAAs on Solana using the Verification Shim, which avoids persistent rent-exempt accounts while keeping full security guarantees.
- Word Count: 709; Token Estimate: 1195

# Solana VAA Verification via Shim

Verifying VAAs on Solana with the legacy core bridge requires creating multiple rent-exempt accounts for signatures and posted VAAs. These accounts persist even after verification is complete, which increases costs and bloats the on-chain state.

The verification shim solves this by replacing the core bridge verification flow with its own instructions:

- `post_signatures`: Accumulates Guardian signatures into a temporary account.
- `verify_hash`: Validates the VAA by checking the signatures against the active Guardian set and ensuring quorum.
- `close_signatures`: Closes the temporary account to reclaim lamports.

Because the shim avoids leaving permanent accounts behind, verification becomes much cheaper while keeping the same security guarantees.

This page introduces the Verification Shim, explains how it works, and shows how integrators can adopt it in place of the core bridge’s `verify_signatures` and `post_vaa` functions.

For more background, see the [Verification Shim concept section](/docs/products/messaging/concepts/solana-shim/#verification-shim){target=\_blank}. 

## Prerequisites

To interact with the verification shim, you'll need the following:

- [Rust and Solana CLI installed](https://solana.com/docs/intro/installation){target=\_blank}.  
- [Anchor installed](https://www.anchor-lang.com/docs/installation){target=\_blank}.
- The canonical verification shim program already deployed at [`EFaNWErqAtVWufdNb7yofSHHfWFos843DFpu4JBw24at`](https://explorer.solana.com/address/EFaNWErqAtVWufdNb7yofSHHfWFos843DFpu4JBw24at){target=\_blank}.
- The shim’s [IDL](https://github.com/wormhole-foundation/wormhole/blob/main/svm/wormhole-core-shims/anchor/idls/wormhole_verify_vaa_shim.json){target=\_blank} for wiring accounts.
- A payer (signer) funded for compute and temporary account rent (you’ll close and reclaim).

## Setup

To start, add the verification shim CPI and declare the external program so your instruction can CPI into it. This lets your program verify a VAA digest against the active Guardian set without creating persistent core bridge accounts.

```rs
declare_program!(wormhole_verify_vaa_shim);

use anchor_lang::{
    prelude::*,
    solana_program::{self, keccak},
};
use wormhole_verify_vaa_shim::cpi::accounts::VerifyHash;
use wormhole_verify_vaa_shim::program::WormholeVerifyVaaShim;
```

## Accounts

You’ll wire three accounts for verification:

- `guardian_set`: Core bridge `GuardianSet` PDA for the VAA’s `guardianSetIndex` (shim checks derivation).
- `guardian_signatures`: Temporary account created by `post_signatures` (shim checks ownership & discriminator).
- `wormhole_verify_vaa_shim`: The verification shim program.

```rs
#[derive(Accounts)]
pub struct ConsumeVaa<'info> {
    /// CHECK: Guardian set used for signature verification by shim.
    /// Derivation is checked by the shim.
    guardian_set: UncheckedAccount<'info>,

    /// CHECK: Stored guardian signatures to be verified by shim.
    /// Ownership ownership and discriminator is checked by the shim.
    guardian_signatures: UncheckedAccount<'info>,

    wormhole_verify_vaa_shim: Program<'info, WormholeVerifyVaaShim>,
}
```

Here, `guardian_set` is a core bridge PDA, and `guardian_signatures` is created and owned by the verification shim. Derive `guardian_set = PDA(["GuardianSet", index_be_bytes], CORE_BRIDGE_PROGRAM_ID)` using the `guardianSetIndex` from the VAA header (big-endian), compute its bump, and pass that bump into your instruction.

## Verify the VAA

The `consume_vaa` function computes the digest, calls the shim’s `verify_hash`, and then proceeds with your logic. This step validates Guardian signatures and quorum against the active Guardian set for the VAA’s `guardianSetIndex`, then lets your program proceed without persisting a `PostedVAA`. 

```rs
pub fn consume_vaa(
    ctx: Context<ConsumeVaa>,
    guardian_set_bump: u8,
    vaa_body: Vec<u8>,
) -> Result<()> {
    // Compute the message hash.
    let message_hash = &solana_program::keccak::hashv(&[&vaa_body]).to_bytes();
    let digest = keccak::hash(message_hash.as_slice()).to_bytes();
    // Verify the hash against the signatures.
    wormhole_verify_vaa_shim::cpi::verify_hash(
        CpiContext::new(
            ctx.accounts.wormhole_verify_vaa_shim.to_account_info(),
            VerifyHash {
                guardian_set: ctx.accounts.guardian_set.to_account_info(),
                guardian_signatures: ctx.accounts.guardian_signatures.to_account_info(),
            },
        ),
        guardian_set_bump,
        digest,
    )?;
    // Decode vaa_body, perform security checks, and do your thing.
    Ok(())
}
```

## Limitations and Security Considerations

- You must be the payer and/or account owner to reclaim lamports from the `GuardianSignatures` account.
- The verification proof is not a permanent on-chain record unless you keep the account.
- Compute usage (CU) is higher for the rent-efficient pattern, but the total cost is dramatically lower than keeping permanent accounts.
- All validation guarantees remain as strong as with the legacy method.
- If you do not close accounts you create, rent will be lost as before.
- This approach assumes you do not need to later re-validate the VAA from an on-chain artifact.

## Conclusion

By following this flow, you can efficiently verify VAAs on Solana with minimal rent overhead, leaving no unnecessary state behind on-chain. For a complete, working reference, see the full example implementation in the Wormhole repo: [`consume_vaa.rs`](https://github.com/wormhole-foundation/wormhole/blob/main/svm/wormhole-core-shims/anchor/programs/wormhole-integrator-example/src/instructions/consume_vaa.rs){target=\_blank}.


---

Page Title: Spy

- Resolved Markdown: https://wormhole.com/docs/ai/pages/protocol-infrastructure-spy.md
- Canonical (HTML): https://wormhole.com/docs/protocol/infrastructure/spy/
- Summary: Discover Wormhole's Spy daemon, which subscribes to gossiped messages in the Guardian Network, including VAAs and Observations, with setup instructions.
- Word Count: 747; Token Estimate: 1153

# Spy

In Wormhole's ecosystem, the _Spy_ is a daemon, a continuously running background process that monitors messages within the Guardian Network. Unlike Guardians, a Spy doesn't perform validation; instead, it serves as an interface for observing the network's message traffic, enabling applications and users to access live data transmitted over Wormhole.

The primary purpose of a Spy is to subscribe to the gossiped messages across the Guardian Network, tracking key message types that allow integrators and applications to monitor real-time network activity without directly engaging in consensus operations.

This page provides a comprehensive guide to where the Spy fits within the Wormhole network, describing the key features and role in facilitating multichain processes.

## Key Features

- **Real-time monitoring of Wormhole messages**: The Spy allows users to observe Wormhole messages as they are published across supported chains in near real-time.
- **Filterable and observable message streams**: Users can filter message streams by chain, emitter, and other criteria, making it easier to track specific contracts or categories of interest.
- **Integration-friendly event streaming**: The Spy exposes gRPC and WebSocket interfaces, making it easy to integrate message observation into custom tooling, dashboards, or indexing services.
- **Support for multiple message protocols**: It can observe messages from different Wormhole messaging protocols (WTT, CCTP, NTT, etc.), providing broad coverage of cross-chain activity.
- **Lightweight and infrastructure-ready**: The Spy is designed to run as part of indexing or backend services, not requiring validator-level infrastructure.

## Integrator Use Case

The Spy provides a valuable mechanism for integrators to observe real-time network activity in the Guardian Network without directly engaging in validation or consensus. By running a Spy, integrators can track multichain events and message flows — such as VAAs, observations, and Guardian heartbeats — to monitor network activity essential to their applications.

This monitoring capability is especially beneficial for applications that need immediate insights into multichain data events. Integrators can run a Spy to ensure their applications are promptly informed of message approvals, observations, or Guardian liveness signals, supporting timely and responsive app behavior without additional overhead on network resources.

## Observable Message Categories

A Spy can access the following categories of messages shared over the gossip protocol:

- **[Verifiable Action Approvals (VAAs)](/docs/protocol/infrastructure/vaas/){target=\_blank}**: Packets of multichain data.

    - The Spy can detect whether a VAA has been approved by the Guardian Network, making it a valuable tool for applications needing real-time multichain verification.

- **[Observations](/docs/products/reference/glossary/#observation){target=\_blank}**: Emitted by Wormhole's core contracts, observations are picked up by the Guardians and relayed across the network.

    - A Spy allow users to monitor these messages, adding transparency and insight into blockchain events.

- **[Guardian heartbeats](/docs/products/reference/glossary/#heartbeat){target=\_blank}**: Heartbeat messages represent Guardian node status.

    - By monitoring heartbeats, a Spy can signal the liveness and connectivity of Guardians in the network.

## Additional Resources

<div class="grid cards" markdown>

-   :octicons-code-16:{ .lg .middle } **Spy Source Code**

    ---

    To see the source code for the Go implementation of the Spy, visit the `wormhole` repository on GitHub.

    [:custom-arrow: View the Source Code](https://github.com/wormhole-foundation/wormhole/blob/main/node/cmd/spy/spy.go){target=\_blank}

-   :octicons-code-16:{ .lg .middle } **Alternative Implementation**

    ---

    Visit the `beacon` repository on GitHub to learn more about Beacon, an alternative highly available, reduced-latency version of the Wormhole Spy.

    [:custom-arrow: Get Started with Pyth Beacon](https://github.com/pyth-network/beacon)

-   :octicons-book-16:{ .lg .middle } **Discover Wormhole Queries**

    ---

    For an alternative option to on-demand access to Guardian-attested multichain data, see the Wormhole Queries page. Queries provide a simple, REST endpoint style developer experience. 

    [:custom-arrow: Explore Queries](/docs/products/queries/overview/)

</div>

## Next Steps

<div class="grid cards" markdown>

-   :octicons-code-16:{ .lg .middle } **Run a Spy**

    ---

    Learn how to run the needed infrastructure to spin up a Spy daemon locally and subscribe to a stream of Verifiable Action Approvals (VAAs).

    [:custom-arrow: Spin Up a Spy](/docs/protocol/infrastructure-guides/run-spy/)

-   :octicons-code-16:{ .lg .middle } **Use Queries**

    ---

    For access to real-time network data without infrastructure overhead, follow this guide and use Wormhole Query to construct a query, make a request, and verify the response.

    [:custom-arrow: Get Started with Queries](/docs/products/queries/guides/use-queries/)

-   :octicons-tools-16:{ .lg .middle } **Wormhole Dev Arena**

    ---

    A structured learning hub with hands-on tutorials across the Wormhole ecosystem.

    [:custom-arrow: Explore the Dev Arena](https://arena.wormhole.com/ecosystem){target=\_blank}

</div>


---

Page Title: Supported Networks

- Resolved Markdown: https://wormhole.com/docs/ai/pages/products-reference-supported-networks.md
- Canonical (HTML): https://wormhole.com/docs/products/reference/supported-networks/
- Summary: Learn about the networks each Wormhole product supports, and explore links to documentation, official websites, and block explorers.
- Word Count: 10869; Token Estimate: 29569

# Supported Networks

Wormhole supports many blockchains across mainnet, testnet, and devnets. You can use these tables to verify if your desired chains are supported by the Wormhole products you plan to include in your integration. 

## Supported Networks by Product

### Connect



<div class="full-width" markdown>

<table data-full-width="true" markdown><thead><th>Blockchain</th><th>Environment</th><th>Mainnet</th><th>Testnet</th><th>Devnet</th><th>Quick Links</th></thead><tbody><tr><td>Ethereum</td><td>EVM</td><td>:white_check_mark:</td><td>:white_check_mark:</td><td>:white_check_mark:</td><td>:material-web: <a href="https://ethereum.org/" target="_blank">Website</a><br>:material-file-document: <a href="https://ethereum.org/developers/docs/" target="_blank">Developer Docs</a><br>:octicons-package-16: <a href="https://etherscan.io/" target="_blank">Block Explorer</a></td></tr><tr><td>Solana</td><td>SVM</td><td>:white_check_mark:</td><td>:white_check_mark:</td><td>:x:</td><td>:material-web: <a href="https://solana.com/" target="_blank">Website</a><br>:material-file-document: <a href="https://solana.com/docs" target="_blank">Developer Docs</a><br>:octicons-package-16: <a href="https://explorer.solana.com/" target="_blank">Block Explorer</a></td></tr><tr><td>Aptos</td><td>Move VM</td><td>:white_check_mark:</td><td>:x:</td><td>:x:</td><td>:material-web: <a href="https://aptosnetwork.com/" target="_blank">Website</a><br>:material-file-document: <a href="https://aptos.dev/" target="_blank">Developer Docs</a><br>:octicons-package-16: <a href="https://explorer.aptoslabs.com/" target="_blank">Block Explorer</a></td></tr><tr><td>Arbitrum</td><td>EVM</td><td>:white_check_mark:</td><td>:white_check_mark:</td><td>:x:</td><td>:material-web: <a href="https://arbitrum.io/" target="_blank">Website</a><br>:material-file-document: <a href="https://docs.arbitrum.io/" target="_blank">Developer Docs</a><br>:octicons-package-16: <a href="https://arbiscan.io/" target="_blank">Block Explorer</a></td></tr><tr><td>Avalanche</td><td>EVM</td><td>:white_check_mark:</td><td>:white_check_mark:</td><td>:x:</td><td>:material-web: <a href="https://www.avax.network/" target="_blank">Website</a><br>:material-file-document: <a href="https://build.avax.network/docs/primary-network" target="_blank">Developer Docs</a><br>:octicons-package-16: <a href="https://snowtrace.io/" target="_blank">Block Explorer</a></td></tr><tr><td>Base</td><td>EVM</td><td>:white_check_mark:</td><td>:white_check_mark:</td><td>:x:</td><td>:material-web: <a href="https://base.org/" target="_blank">Website</a><br>:material-file-document: <a href="https://docs.base.org/" target="_blank">Developer Docs</a><br>:octicons-package-16: <a href="https://basescan.org/" target="_blank">Block Explorer</a></td></tr><tr><td>Berachain</td><td>EVM</td><td>:white_check_mark:</td><td>:white_check_mark:</td><td>:x:</td><td>:material-web: <a href="https://www.berachain.com/" target="_blank">Website</a><br>:material-file-document: <a href="https://docs.berachain.com/" target="_blank">Developer Docs</a><br>:octicons-package-16: <a href="https://berascan.com/" target="_blank">Block Explorer</a></td></tr><tr><td>BNB Smart Chain</td><td>EVM</td><td>:white_check_mark:</td><td>:white_check_mark:</td><td>:x:</td><td>:material-web: <a href="https://www.bnbchain.org/en/bnb-smart-chain" target="_blank">Website</a><br>:material-file-document: <a href="https://docs.bnbchain.org/" target="_blank">Developer Docs</a><br>:octicons-package-16: <a href="https://bscscan.com/" target="_blank">Block Explorer</a></td></tr><tr><td>Celo</td><td>EVM</td><td>:white_check_mark:</td><td>:white_check_mark:</td><td>:x:</td><td>:material-web: <a href="https://celo.org/" target="_blank">Website</a><br>:material-file-document: <a href="https://docs.celo.org/" target="_blank">Developer Docs</a><br>:octicons-package-16: <a href="https://celo.blockscout.com/" target="_blank">Block Explorer</a></td></tr><tr><td>CreditCoin</td><td>EVM</td><td>:white_check_mark:</td><td>:x:</td><td>:x:</td><td>:material-web: <a href="https://creditcoin.org/" target="_blank">Website</a><br>:material-file-document: <a href="https://docs.creditcoin.org/" target="_blank">Developer Docs</a><br>:octicons-package-16: <a href="https://creditcoin.subscan.io/" target="_blank">Block Explorer</a></td></tr><tr><td>Fantom</td><td>EVM</td><td>:white_check_mark:</td><td>:white_check_mark:</td><td>:x:</td><td>:material-web: <a href="https://fantom.foundation/" target="_blank">Website</a><br>:material-file-document: <a href="https://docs.fantom.foundation/" target="_blank">Developer Docs</a><br>:octicons-package-16: <a href="https://explorer.fantom.network/" target="_blank">Block Explorer</a></td></tr><tr><td>Fogo</td><td>SVM</td><td>:white_check_mark:</td><td>:white_check_mark:</td><td>:x:</td><td>:material-web: <a href="https://www.fogo.io/" target="_blank">Website</a><br>:octicons-package-16: <a href="https://fogoscan.com/?cluster=testnet" target="_blank">Block Explorer</a></td></tr><tr><td>HyperCore</td><td>EVM</td><td>:white_check_mark:</td><td>:white_check_mark:</td><td>:x:</td><td>:material-web: <a href="https://hyperliquid.gitbook.io/hyperliquid-docs/hypercore" target="_blank">Website</a><br>:material-file-document: <a href="https://hyperliquid.gitbook.io/hyperliquid-docs/hypercore" target="_blank">Developer Docs</a><br></td></tr><tr><td>HyperEVM :material-alert:{ title='⚠️ The HyperEVM integration is experimental, as its node software is not open source. Use Wormhole messaging on HyperEVM with caution.' }</td><td>EVM</td><td>:white_check_mark:</td><td>:white_check_mark:</td><td>:x:</td><td>:material-web: <a href="https://hyperfoundation.org/" target="_blank">Website</a><br>:material-file-document: <a href="https://hyperliquid.gitbook.io/hyperliquid-docs" target="_blank">Developer Docs</a><br></td></tr><tr><td>Ink</td><td>EVM</td><td>:white_check_mark:</td><td>:x:</td><td>:x:</td><td>:material-web: <a href="https://inkonchain.com/" target="_blank">Website</a><br>:material-file-document: <a href="https://docs.inkonchain.com/" target="_blank">Developer Docs</a><br>:octicons-package-16: <a href="https://explorer-sepolia.inkonchain.com/" target="_blank">Block Explorer</a></td></tr><tr><td>Kaia</td><td>EVM</td><td>:white_check_mark:</td><td>:white_check_mark:</td><td>:x:</td><td>:material-web: <a href="https://www.kaia.io/" target="_blank">Website</a><br>:material-file-document: <a href="https://docs.kaia.io/" target="_blank">Developer Docs</a><br>:octicons-package-16: <a href="https://kaiascan.io/" target="_blank">Block Explorer</a></td></tr><tr><td>Linea</td><td>EVM</td><td>:white_check_mark:</td><td>:x:</td><td>:x:</td><td>:material-web: <a href="https://linea.build/" target="_blank">Website</a><br>:material-file-document: <a href="https://docs.linea.build/" target="_blank">Developer Docs</a><br>:octicons-package-16: <a href="https://docs.linea.build/get-started/build/block-explorers" target="_blank">Block Explorer</a></td></tr><tr><td>Mantle</td><td>EVM</td><td>:white_check_mark:</td><td>:white_check_mark:</td><td>:x:</td><td>:material-web: <a href="https://www.mantle.xyz/" target="_blank">Website</a><br>:material-file-document: <a href="https://docs.mantle.xyz/network/" target="_blank">Developer Docs</a><br>:octicons-package-16: <a href="https://mantlescan.xyz/" target="_blank">Block Explorer</a></td></tr><tr><td>MegaETH</td><td>EVM</td><td>:white_check_mark:</td><td>:x:</td><td>:x:</td><td>:material-web: <a href="https://www.megaeth.com/" target="_blank">Website</a><br>:material-file-document: <a href="https://docs.megaeth.com/" target="_blank">Developer Docs</a><br>:octicons-package-16: <a href="https://mega.etherscan.io/" target="_blank">Block Explorer</a></td></tr><tr><td>Mezo</td><td>EVM</td><td>:white_check_mark:</td><td>:white_check_mark:</td><td>:x:</td><td>:material-web: <a href="https://mezo.org/" target="_blank">Website</a><br>:material-file-document: <a href="https://mezo.org/docs/developers/" target="_blank">Developer Docs</a><br>:octicons-package-16: <a href="https://explorer.test.mezo.org/" target="_blank">Block Explorer</a></td></tr><tr><td>Moca</td><td>EVM</td><td>:white_check_mark:</td><td>:x:</td><td>:x:</td><td>:material-web: <a href="https://mocachain.org/en" target="_blank">Website</a><br>:material-file-document: <a href="https://mocacoin.gitbook.io/litepaper" target="_blank">Developer Docs</a><br>:octicons-package-16: <a href="https://devnet-scan.mocachain.org/" target="_blank">Block Explorer</a></td></tr><tr><td>Monad</td><td>EVM</td><td>:white_check_mark:</td><td>:white_check_mark:</td><td>:x:</td><td>:material-web: <a href="https://www.monad.xyz/" target="_blank">Website</a><br>:material-file-document: <a href="https://docs.monad.xyz/" target="_blank">Developer Docs</a><br>:octicons-package-16: <a href="https://testnet.monvision.io/" target="_blank">Block Explorer</a></td></tr><tr><td>Moonbeam</td><td>EVM</td><td>:white_check_mark:</td><td>:white_check_mark:</td><td>:x:</td><td>:material-web: <a href="https://moonbeam.network/" target="_blank">Website</a><br>:material-file-document: <a href="https://docs.moonbeam.network/" target="_blank">Developer Docs</a><br>:octicons-package-16: <a href="https://moonscan.io/" target="_blank">Block Explorer</a></td></tr><tr><td>Optimism</td><td>EVM</td><td>:white_check_mark:</td><td>:white_check_mark:</td><td>:x:</td><td>:material-web: <a href="https://www.optimism.io/" target="_blank">Website</a><br>:material-file-document: <a href="https://docs.optimism.io/" target="_blank">Developer Docs</a><br>:octicons-package-16: <a href="https://optimistic.etherscan.io/" target="_blank">Block Explorer</a></td></tr><tr><td>Plume</td><td>EVM</td><td>:white_check_mark:</td><td>:x:</td><td>:x:</td><td>:material-web: <a href="https://plume.org/" target="_blank">Website</a><br>:material-file-document: <a href="https://docs.plume.org/plume" target="_blank">Developer Docs</a><br>:octicons-package-16: <a href="https://explorer.plume.org/" target="_blank">Block Explorer</a></td></tr><tr><td>Polygon</td><td>EVM</td><td>:white_check_mark:</td><td>:white_check_mark:</td><td>:x:</td><td>:material-web: <a href="https://polygon.technology/" target="_blank">Website</a><br>:material-file-document: <a href="https://docs.polygon.technology/" target="_blank">Developer Docs</a><br>:octicons-package-16: <a href="https://polygonscan.com/" target="_blank">Block Explorer</a></td></tr><tr><td>Scroll</td><td>EVM</td><td>:white_check_mark:</td><td>:white_check_mark:</td><td>:x:</td><td>:material-web: <a href="https://scroll.io/" target="_blank">Website</a><br>:material-file-document: <a href="https://docs.scroll.io/en/home/" target="_blank">Developer Docs</a><br>:octicons-package-16: <a href="https://scrollscan.com/" target="_blank">Block Explorer</a></td></tr><tr><td>SeiEVM</td><td>EVM</td><td>:white_check_mark:</td><td>:x:</td><td>:x:</td><td>:material-web: <a href="https://www.sei.io/" target="_blank">Website</a><br>:material-file-document: <a href="https://docs.sei.io/evm" target="_blank">Developer Docs</a><br>:octicons-package-16: <a href="https://seistream.app/" target="_blank">Block Explorer</a></td></tr><tr><td>Sonic</td><td>EVM</td><td>:white_check_mark:</td><td>:x:</td><td>:x:</td><td>:material-web: <a href="https://www.soniclabs.com/" target="_blank">Website</a><br>:material-file-document: <a href="https://docs.soniclabs.com/" target="_blank">Developer Docs</a><br>:octicons-package-16: <a href="https://sonicscan.org/" target="_blank">Block Explorer</a></td></tr><tr><td>Sui</td><td>Sui Move VM</td><td>:white_check_mark:</td><td>:white_check_mark:</td><td>:x:</td><td>:material-web: <a href="https://www.sui.io/" target="_blank">Website</a><br>:material-file-document: <a href="https://docs.sui.io/" target="_blank">Developer Docs</a><br>:octicons-package-16: <a href="https://suiscan.xyz/" target="_blank">Block Explorer</a></td></tr><tr><td>Unichain</td><td>EVM</td><td>:white_check_mark:</td><td>:white_check_mark:</td><td>:x:</td><td>:material-web: <a href="https://www.unichain.org/" target="_blank">Website</a><br>:material-file-document: <a href="https://docs.unichain.org/docs" target="_blank">Developer Docs</a><br>:octicons-package-16: <a href="https://sepolia.uniscan.xyz/" target="_blank">Block Explorer</a></td></tr><tr><td>World Chain</td><td>EVM</td><td>:white_check_mark:</td><td>:x:</td><td>:x:</td><td>:material-web: <a href="https://world.org/world-chain" target="_blank">Website</a><br>:material-file-document: <a href="https://docs.world.org/" target="_blank">Developer Docs</a><br>:octicons-package-16: <a href="https://docs.world.org/world-chain/providers/explorers" target="_blank">Block Explorer</a></td></tr><tr><td>X Layer</td><td>EVM</td><td>:white_check_mark:</td><td>:x:</td><td>:x:</td><td>:material-web: <a href="https://web3.okx.com/xlayer" target="_blank">Website</a><br>:material-file-document: <a href="https://web3.okx.com/xlayer/docs/developer/build-on-xlayer/about-xlayer" target="_blank">Developer Docs</a><br>:octicons-package-16: <a href="https://web3.okx.com/explorer/x-layer" target="_blank">Block Explorer</a></td></tr><tr><td>XRPL-EVM</td><td>EVM</td><td>:white_check_mark:</td><td>:x:</td><td>:x:</td><td>:material-web: <a href="https://www.xrplevm.org/" target="_blank">Website</a><br>:material-file-document: <a href="https://docs.xrplevm.org/" target="_blank">Developer Docs</a><br>:octicons-package-16: <a href="https://explorer.xrplevm.org/" target="_blank">Block Explorer</a></td></tr></tbody></table>

</div>

### NTT



<div class="full-width" markdown>

<table data-full-width="true" markdown><thead><th>Blockchain</th><th>Environment</th><th>Mainnet</th><th>Testnet</th><th>Devnet</th><th>Quick Links</th></thead><tbody><tr><td>Ethereum</td><td>EVM</td><td>:white_check_mark:</td><td>:white_check_mark:</td><td>:white_check_mark:</td><td>:material-web: <a href="https://ethereum.org/" target="_blank">Website</a><br>:material-file-document: <a href="https://ethereum.org/developers/docs/" target="_blank">Developer Docs</a><br>:octicons-package-16: <a href="https://etherscan.io/" target="_blank">Block Explorer</a></td></tr><tr><td>Solana</td><td>SVM</td><td>:white_check_mark:</td><td>:white_check_mark:</td><td>:white_check_mark:</td><td>:material-web: <a href="https://solana.com/" target="_blank">Website</a><br>:material-file-document: <a href="https://solana.com/docs" target="_blank">Developer Docs</a><br>:octicons-package-16: <a href="https://explorer.solana.com/" target="_blank">Block Explorer</a></td></tr><tr><td>0G (Zero Gravity)</td><td>EVM</td><td>:white_check_mark:</td><td>:white_check_mark:</td><td>:x:</td><td>:material-web: <a href="https://0g.ai/" target="_blank">Website</a><br>:material-file-document: <a href="https://docs.0g.ai/" target="_blank">Developer Docs</a><br>:octicons-package-16: <a href="https://chainscan.0g.ai" target="_blank">Block Explorer</a></td></tr><tr><td>Arbitrum</td><td>EVM</td><td>:white_check_mark:</td><td>:white_check_mark:</td><td>:x:</td><td>:material-web: <a href="https://arbitrum.io/" target="_blank">Website</a><br>:material-file-document: <a href="https://docs.arbitrum.io/" target="_blank">Developer Docs</a><br>:octicons-package-16: <a href="https://arbiscan.io/" target="_blank">Block Explorer</a></td></tr><tr><td>Avalanche</td><td>EVM</td><td>:white_check_mark:</td><td>:white_check_mark:</td><td>:x:</td><td>:material-web: <a href="https://www.avax.network/" target="_blank">Website</a><br>:material-file-document: <a href="https://build.avax.network/docs/primary-network" target="_blank">Developer Docs</a><br>:octicons-package-16: <a href="https://snowtrace.io/" target="_blank">Block Explorer</a></td></tr><tr><td>Base</td><td>EVM</td><td>:white_check_mark:</td><td>:white_check_mark:</td><td>:x:</td><td>:material-web: <a href="https://base.org/" target="_blank">Website</a><br>:material-file-document: <a href="https://docs.base.org/" target="_blank">Developer Docs</a><br>:octicons-package-16: <a href="https://basescan.org/" target="_blank">Block Explorer</a></td></tr><tr><td>Berachain</td><td>EVM</td><td>:white_check_mark:</td><td>:white_check_mark:</td><td>:x:</td><td>:material-web: <a href="https://www.berachain.com/" target="_blank">Website</a><br>:material-file-document: <a href="https://docs.berachain.com/" target="_blank">Developer Docs</a><br>:octicons-package-16: <a href="https://berascan.com/" target="_blank">Block Explorer</a></td></tr><tr><td>BNB Smart Chain</td><td>EVM</td><td>:white_check_mark:</td><td>:white_check_mark:</td><td>:white_check_mark:</td><td>:material-web: <a href="https://www.bnbchain.org/en/bnb-smart-chain" target="_blank">Website</a><br>:material-file-document: <a href="https://docs.bnbchain.org/" target="_blank">Developer Docs</a><br>:octicons-package-16: <a href="https://bscscan.com/" target="_blank">Block Explorer</a></td></tr><tr><td>Celo</td><td>EVM</td><td>:white_check_mark:</td><td>:white_check_mark:</td><td>:x:</td><td>:material-web: <a href="https://celo.org/" target="_blank">Website</a><br>:material-file-document: <a href="https://docs.celo.org/" target="_blank">Developer Docs</a><br>:octicons-package-16: <a href="https://celo.blockscout.com/" target="_blank">Block Explorer</a></td></tr><tr><td>Converge</td><td>EVM</td><td>:x:</td><td>:white_check_mark:</td><td>:x:</td><td>:material-web: <a href="https://www.convergeonchain.xyz/" target="_blank">Website</a><br></td></tr><tr><td>CreditCoin</td><td>EVM</td><td>:white_check_mark:</td><td>:x:</td><td>:x:</td><td>:material-web: <a href="https://creditcoin.org/" target="_blank">Website</a><br>:material-file-document: <a href="https://docs.creditcoin.org/" target="_blank">Developer Docs</a><br>:octicons-package-16: <a href="https://creditcoin.subscan.io/" target="_blank">Block Explorer</a></td></tr><tr><td>Fantom</td><td>EVM</td><td>:white_check_mark:</td><td>:white_check_mark:</td><td>:x:</td><td>:material-web: <a href="https://fantom.foundation/" target="_blank">Website</a><br>:material-file-document: <a href="https://docs.fantom.foundation/" target="_blank">Developer Docs</a><br>:octicons-package-16: <a href="https://explorer.fantom.network/" target="_blank">Block Explorer</a></td></tr><tr><td>Fogo</td><td>SVM</td><td>:white_check_mark:</td><td>:white_check_mark:</td><td>:x:</td><td>:material-web: <a href="https://www.fogo.io/" target="_blank">Website</a><br>:octicons-package-16: <a href="https://fogoscan.com/?cluster=testnet" target="_blank">Block Explorer</a></td></tr><tr><td>HyperEVM :material-alert:{ title='⚠️ The HyperEVM integration is experimental, as its node software is not open source. Use Wormhole messaging on HyperEVM with caution.' }</td><td>EVM</td><td>:white_check_mark:</td><td>:x:</td><td>:x:</td><td>:material-web: <a href="https://hyperfoundation.org/" target="_blank">Website</a><br>:material-file-document: <a href="https://hyperliquid.gitbook.io/hyperliquid-docs" target="_blank">Developer Docs</a><br></td></tr><tr><td>Ink</td><td>EVM</td><td>:white_check_mark:</td><td>:white_check_mark:</td><td>:x:</td><td>:material-web: <a href="https://inkonchain.com/" target="_blank">Website</a><br>:material-file-document: <a href="https://docs.inkonchain.com/" target="_blank">Developer Docs</a><br>:octicons-package-16: <a href="https://explorer-sepolia.inkonchain.com/" target="_blank">Block Explorer</a></td></tr><tr><td>Kaia</td><td>EVM</td><td>:white_check_mark:</td><td>:x:</td><td>:x:</td><td>:material-web: <a href="https://www.kaia.io/" target="_blank">Website</a><br>:material-file-document: <a href="https://docs.kaia.io/" target="_blank">Developer Docs</a><br>:octicons-package-16: <a href="https://kaiascan.io/" target="_blank">Block Explorer</a></td></tr><tr><td>Linea</td><td>EVM</td><td>:white_check_mark:</td><td>:white_check_mark:</td><td>:x:</td><td>:material-web: <a href="https://linea.build/" target="_blank">Website</a><br>:material-file-document: <a href="https://docs.linea.build/" target="_blank">Developer Docs</a><br>:octicons-package-16: <a href="https://docs.linea.build/get-started/build/block-explorers" target="_blank">Block Explorer</a></td></tr><tr><td>Mantle</td><td>EVM</td><td>:white_check_mark:</td><td>:x:</td><td>:x:</td><td>:material-web: <a href="https://www.mantle.xyz/" target="_blank">Website</a><br>:material-file-document: <a href="https://docs.mantle.xyz/network/" target="_blank">Developer Docs</a><br>:octicons-package-16: <a href="https://mantlescan.xyz/" target="_blank">Block Explorer</a></td></tr><tr><td>MegaETH</td><td>EVM</td><td>:white_check_mark:</td><td>:x:</td><td>:x:</td><td>:material-web: <a href="https://www.megaeth.com/" target="_blank">Website</a><br>:material-file-document: <a href="https://docs.megaeth.com/" target="_blank">Developer Docs</a><br>:octicons-package-16: <a href="https://mega.etherscan.io/" target="_blank">Block Explorer</a></td></tr><tr><td>Mezo</td><td>EVM</td><td>:white_check_mark:</td><td>:white_check_mark:</td><td>:x:</td><td>:material-web: <a href="https://mezo.org/" target="_blank">Website</a><br>:material-file-document: <a href="https://mezo.org/docs/developers/" target="_blank">Developer Docs</a><br>:octicons-package-16: <a href="https://explorer.test.mezo.org/" target="_blank">Block Explorer</a></td></tr><tr><td>Moca</td><td>EVM</td><td>:white_check_mark:</td><td>:white_check_mark:</td><td>:x:</td><td>:material-web: <a href="https://mocachain.org/en" target="_blank">Website</a><br>:material-file-document: <a href="https://mocacoin.gitbook.io/litepaper" target="_blank">Developer Docs</a><br>:octicons-package-16: <a href="https://devnet-scan.mocachain.org/" target="_blank">Block Explorer</a></td></tr><tr><td>Monad</td><td>EVM</td><td>:white_check_mark:</td><td>:x:</td><td>:x:</td><td>:material-web: <a href="https://www.monad.xyz/" target="_blank">Website</a><br>:material-file-document: <a href="https://docs.monad.xyz/" target="_blank">Developer Docs</a><br>:octicons-package-16: <a href="https://testnet.monvision.io/" target="_blank">Block Explorer</a></td></tr><tr><td>Moonbeam</td><td>EVM</td><td>:white_check_mark:</td><td>:white_check_mark:</td><td>:x:</td><td>:material-web: <a href="https://moonbeam.network/" target="_blank">Website</a><br>:material-file-document: <a href="https://docs.moonbeam.network/" target="_blank">Developer Docs</a><br>:octicons-package-16: <a href="https://moonscan.io/" target="_blank">Block Explorer</a></td></tr><tr><td>Optimism</td><td>EVM</td><td>:white_check_mark:</td><td>:white_check_mark:</td><td>:x:</td><td>:material-web: <a href="https://www.optimism.io/" target="_blank">Website</a><br>:material-file-document: <a href="https://docs.optimism.io/" target="_blank">Developer Docs</a><br>:octicons-package-16: <a href="https://optimistic.etherscan.io/" target="_blank">Block Explorer</a></td></tr><tr><td>Plume</td><td>EVM</td><td>:white_check_mark:</td><td>:white_check_mark:</td><td>:x:</td><td>:material-web: <a href="https://plume.org/" target="_blank">Website</a><br>:material-file-document: <a href="https://docs.plume.org/plume" target="_blank">Developer Docs</a><br>:octicons-package-16: <a href="https://explorer.plume.org/" target="_blank">Block Explorer</a></td></tr><tr><td>Polygon</td><td>EVM</td><td>:white_check_mark:</td><td>:white_check_mark:</td><td>:x:</td><td>:material-web: <a href="https://polygon.technology/" target="_blank">Website</a><br>:material-file-document: <a href="https://docs.polygon.technology/" target="_blank">Developer Docs</a><br>:octicons-package-16: <a href="https://polygonscan.com/" target="_blank">Block Explorer</a></td></tr><tr><td>Scroll</td><td>EVM</td><td>:white_check_mark:</td><td>:x:</td><td>:x:</td><td>:material-web: <a href="https://scroll.io/" target="_blank">Website</a><br>:material-file-document: <a href="https://docs.scroll.io/en/home/" target="_blank">Developer Docs</a><br>:octicons-package-16: <a href="https://scrollscan.com/" target="_blank">Block Explorer</a></td></tr><tr><td>SeiEVM</td><td>EVM</td><td>:white_check_mark:</td><td>:white_check_mark:</td><td>:x:</td><td>:material-web: <a href="https://www.sei.io/" target="_blank">Website</a><br>:material-file-document: <a href="https://docs.sei.io/evm" target="_blank">Developer Docs</a><br>:octicons-package-16: <a href="https://seistream.app/" target="_blank">Block Explorer</a></td></tr><tr><td>Sui</td><td>Sui Move VM</td><td>:white_check_mark:</td><td>:white_check_mark:</td><td>:x:</td><td>:material-web: <a href="https://www.sui.io/" target="_blank">Website</a><br>:material-file-document: <a href="https://docs.sui.io/" target="_blank">Developer Docs</a><br>:octicons-package-16: <a href="https://suiscan.xyz/" target="_blank">Block Explorer</a></td></tr><tr><td>Unichain</td><td>EVM</td><td>:white_check_mark:</td><td>:white_check_mark:</td><td>:x:</td><td>:material-web: <a href="https://www.unichain.org/" target="_blank">Website</a><br>:material-file-document: <a href="https://docs.unichain.org/docs" target="_blank">Developer Docs</a><br>:octicons-package-16: <a href="https://sepolia.uniscan.xyz/" target="_blank">Block Explorer</a></td></tr><tr><td>World Chain</td><td>EVM</td><td>:white_check_mark:</td><td>:x:</td><td>:x:</td><td>:material-web: <a href="https://world.org/world-chain" target="_blank">Website</a><br>:material-file-document: <a href="https://docs.world.org/" target="_blank">Developer Docs</a><br>:octicons-package-16: <a href="https://docs.world.org/world-chain/providers/explorers" target="_blank">Block Explorer</a></td></tr><tr><td>X Layer</td><td>EVM</td><td>:white_check_mark:</td><td>:x:</td><td>:x:</td><td>:material-web: <a href="https://web3.okx.com/xlayer" target="_blank">Website</a><br>:material-file-document: <a href="https://web3.okx.com/xlayer/docs/developer/build-on-xlayer/about-xlayer" target="_blank">Developer Docs</a><br>:octicons-package-16: <a href="https://web3.okx.com/explorer/x-layer" target="_blank">Block Explorer</a></td></tr><tr><td>XRPL-EVM</td><td>EVM</td><td>:white_check_mark:</td><td>:white_check_mark:</td><td>:x:</td><td>:material-web: <a href="https://www.xrplevm.org/" target="_blank">Website</a><br>:material-file-document: <a href="https://docs.xrplevm.org/" target="_blank">Developer Docs</a><br>:octicons-package-16: <a href="https://explorer.xrplevm.org/" target="_blank">Block Explorer</a></td></tr></tbody></table>

</div>

### WTT



<div class="full-width" markdown>

<table data-full-width="true" markdown><thead><th>Blockchain</th><th>Environment</th><th>Mainnet</th><th>Testnet</th><th>Devnet</th><th>Quick Links</th></thead><tbody><tr><td>Ethereum</td><td>EVM</td><td>:white_check_mark:</td><td>:white_check_mark:</td><td>:white_check_mark:</td><td>:material-web: <a href="https://ethereum.org/" target="_blank">Website</a><br>:material-file-document: <a href="https://ethereum.org/developers/docs/" target="_blank">Developer Docs</a><br>:octicons-package-16: <a href="https://etherscan.io/" target="_blank">Block Explorer</a></td></tr><tr><td>Solana</td><td>SVM</td><td>:white_check_mark:</td><td>:white_check_mark:</td><td>:white_check_mark:</td><td>:material-web: <a href="https://solana.com/" target="_blank">Website</a><br>:material-file-document: <a href="https://solana.com/docs" target="_blank">Developer Docs</a><br>:octicons-package-16: <a href="https://explorer.solana.com/" target="_blank">Block Explorer</a></td></tr><tr><td>0G (Zero Gravity)</td><td>EVM</td><td>:white_check_mark:</td><td>:white_check_mark:</td><td>:x:</td><td>:material-web: <a href="https://0g.ai/" target="_blank">Website</a><br>:material-file-document: <a href="https://docs.0g.ai/" target="_blank">Developer Docs</a><br>:octicons-package-16: <a href="https://chainscan.0g.ai" target="_blank">Block Explorer</a></td></tr><tr><td>Algorand</td><td>AVM</td><td>:white_check_mark:</td><td>:white_check_mark:</td><td>:white_check_mark:</td><td>:material-web: <a href="https://algorandtechnologies.com/" target="_blank">Website</a><br>:material-file-document: <a href="https://dev.algorand.co" target="_blank">Developer Docs</a><br>:octicons-package-16: <a href="https://allo.info/" target="_blank">Block Explorer</a></td></tr><tr><td>Aptos</td><td>Move VM</td><td>:white_check_mark:</td><td>:white_check_mark:</td><td>:white_check_mark:</td><td>:material-web: <a href="https://aptosnetwork.com/" target="_blank">Website</a><br>:material-file-document: <a href="https://aptos.dev/" target="_blank">Developer Docs</a><br>:octicons-package-16: <a href="https://explorer.aptoslabs.com/" target="_blank">Block Explorer</a></td></tr><tr><td>Arbitrum</td><td>EVM</td><td>:white_check_mark:</td><td>:white_check_mark:</td><td>:x:</td><td>:material-web: <a href="https://arbitrum.io/" target="_blank">Website</a><br>:material-file-document: <a href="https://docs.arbitrum.io/" target="_blank">Developer Docs</a><br>:octicons-package-16: <a href="https://arbiscan.io/" target="_blank">Block Explorer</a></td></tr><tr><td>Avalanche</td><td>EVM</td><td>:white_check_mark:</td><td>:white_check_mark:</td><td>:x:</td><td>:material-web: <a href="https://www.avax.network/" target="_blank">Website</a><br>:material-file-document: <a href="https://build.avax.network/docs/primary-network" target="_blank">Developer Docs</a><br>:octicons-package-16: <a href="https://snowtrace.io/" target="_blank">Block Explorer</a></td></tr><tr><td>Base</td><td>EVM</td><td>:white_check_mark:</td><td>:white_check_mark:</td><td>:x:</td><td>:material-web: <a href="https://base.org/" target="_blank">Website</a><br>:material-file-document: <a href="https://docs.base.org/" target="_blank">Developer Docs</a><br>:octicons-package-16: <a href="https://basescan.org/" target="_blank">Block Explorer</a></td></tr><tr><td>Berachain</td><td>EVM</td><td>:white_check_mark:</td><td>:white_check_mark:</td><td>:x:</td><td>:material-web: <a href="https://www.berachain.com/" target="_blank">Website</a><br>:material-file-document: <a href="https://docs.berachain.com/" target="_blank">Developer Docs</a><br>:octicons-package-16: <a href="https://berascan.com/" target="_blank">Block Explorer</a></td></tr><tr><td>BNB Smart Chain</td><td>EVM</td><td>:white_check_mark:</td><td>:white_check_mark:</td><td>:white_check_mark:</td><td>:material-web: <a href="https://www.bnbchain.org/en/bnb-smart-chain" target="_blank">Website</a><br>:material-file-document: <a href="https://docs.bnbchain.org/" target="_blank">Developer Docs</a><br>:octicons-package-16: <a href="https://bscscan.com/" target="_blank">Block Explorer</a></td></tr><tr><td>Celo</td><td>EVM</td><td>:white_check_mark:</td><td>:white_check_mark:</td><td>:x:</td><td>:material-web: <a href="https://celo.org/" target="_blank">Website</a><br>:material-file-document: <a href="https://docs.celo.org/" target="_blank">Developer Docs</a><br>:octicons-package-16: <a href="https://celo.blockscout.com/" target="_blank">Block Explorer</a></td></tr><tr><td>Fantom</td><td>EVM</td><td>:white_check_mark:</td><td>:white_check_mark:</td><td>:x:</td><td>:material-web: <a href="https://fantom.foundation/" target="_blank">Website</a><br>:material-file-document: <a href="https://docs.fantom.foundation/" target="_blank">Developer Docs</a><br>:octicons-package-16: <a href="https://explorer.fantom.network/" target="_blank">Block Explorer</a></td></tr><tr><td>Fogo</td><td>SVM</td><td>:white_check_mark:</td><td>:white_check_mark:</td><td>:x:</td><td>:material-web: <a href="https://www.fogo.io/" target="_blank">Website</a><br>:octicons-package-16: <a href="https://fogoscan.com/?cluster=testnet" target="_blank">Block Explorer</a></td></tr><tr><td>HyperEVM :material-alert:{ title='⚠️ The HyperEVM integration is experimental, as its node software is not open source. Use Wormhole messaging on HyperEVM with caution.' }</td><td>EVM</td><td>:x:</td><td>:white_check_mark:</td><td>:x:</td><td>:material-web: <a href="https://hyperfoundation.org/" target="_blank">Website</a><br>:material-file-document: <a href="https://hyperliquid.gitbook.io/hyperliquid-docs" target="_blank">Developer Docs</a><br></td></tr><tr><td>Injective</td><td>CosmWasm</td><td>:white_check_mark:</td><td>:white_check_mark:</td><td>:x:</td><td>:material-web: <a href="https://injective.com/" target="_blank">Website</a><br>:material-file-document: <a href="https://docs.injective.network/" target="_blank">Developer Docs</a><br>:octicons-package-16: <a href="https://injscan.com/" target="_blank">Block Explorer</a></td></tr><tr><td>Ink</td><td>EVM</td><td>:white_check_mark:</td><td>:white_check_mark:</td><td>:x:</td><td>:material-web: <a href="https://inkonchain.com/" target="_blank">Website</a><br>:material-file-document: <a href="https://docs.inkonchain.com/" target="_blank">Developer Docs</a><br>:octicons-package-16: <a href="https://explorer-sepolia.inkonchain.com/" target="_blank">Block Explorer</a></td></tr><tr><td>Kaia</td><td>EVM</td><td>:white_check_mark:</td><td>:white_check_mark:</td><td>:x:</td><td>:material-web: <a href="https://www.kaia.io/" target="_blank">Website</a><br>:material-file-document: <a href="https://docs.kaia.io/" target="_blank">Developer Docs</a><br>:octicons-package-16: <a href="https://kaiascan.io/" target="_blank">Block Explorer</a></td></tr><tr><td>Linea</td><td>EVM</td><td>:white_check_mark:</td><td>:white_check_mark:</td><td>:x:</td><td>:material-web: <a href="https://linea.build/" target="_blank">Website</a><br>:material-file-document: <a href="https://docs.linea.build/" target="_blank">Developer Docs</a><br>:octicons-package-16: <a href="https://docs.linea.build/get-started/build/block-explorers" target="_blank">Block Explorer</a></td></tr><tr><td>Mantle</td><td>EVM</td><td>:white_check_mark:</td><td>:white_check_mark:</td><td>:x:</td><td>:material-web: <a href="https://www.mantle.xyz/" target="_blank">Website</a><br>:material-file-document: <a href="https://docs.mantle.xyz/network/" target="_blank">Developer Docs</a><br>:octicons-package-16: <a href="https://mantlescan.xyz/" target="_blank">Block Explorer</a></td></tr><tr><td>MegaETH</td><td>EVM</td><td>:white_check_mark:</td><td>:white_check_mark:</td><td>:x:</td><td>:material-web: <a href="https://www.megaeth.com/" target="_blank">Website</a><br>:material-file-document: <a href="https://docs.megaeth.com/" target="_blank">Developer Docs</a><br>:octicons-package-16: <a href="https://mega.etherscan.io/" target="_blank">Block Explorer</a></td></tr><tr><td>Mezo</td><td>EVM</td><td>:x:</td><td>:white_check_mark:</td><td>:x:</td><td>:material-web: <a href="https://mezo.org/" target="_blank">Website</a><br>:material-file-document: <a href="https://mezo.org/docs/developers/" target="_blank">Developer Docs</a><br>:octicons-package-16: <a href="https://explorer.test.mezo.org/" target="_blank">Block Explorer</a></td></tr><tr><td>Moca</td><td>EVM</td><td>:x:</td><td>:white_check_mark:</td><td>:x:</td><td>:material-web: <a href="https://mocachain.org/en" target="_blank">Website</a><br>:material-file-document: <a href="https://mocacoin.gitbook.io/litepaper" target="_blank">Developer Docs</a><br>:octicons-package-16: <a href="https://devnet-scan.mocachain.org/" target="_blank">Block Explorer</a></td></tr><tr><td>Monad</td><td>EVM</td><td>:white_check_mark:</td><td>:white_check_mark:</td><td>:x:</td><td>:material-web: <a href="https://www.monad.xyz/" target="_blank">Website</a><br>:material-file-document: <a href="https://docs.monad.xyz/" target="_blank">Developer Docs</a><br>:octicons-package-16: <a href="https://testnet.monvision.io/" target="_blank">Block Explorer</a></td></tr><tr><td>Moonbeam</td><td>EVM</td><td>:white_check_mark:</td><td>:white_check_mark:</td><td>:x:</td><td>:material-web: <a href="https://moonbeam.network/" target="_blank">Website</a><br>:material-file-document: <a href="https://docs.moonbeam.network/" target="_blank">Developer Docs</a><br>:octicons-package-16: <a href="https://moonscan.io/" target="_blank">Block Explorer</a></td></tr><tr><td>NEAR</td><td>NEAR VM</td><td>:white_check_mark:</td><td>:white_check_mark:</td><td>:white_check_mark:</td><td>:material-web: <a href="https://near.org/" target="_blank">Website</a><br>:material-file-document: <a href="https://docs.near.org/" target="_blank">Developer Docs</a><br>:octicons-package-16: <a href="https://nearblocks.io/" target="_blank">Block Explorer</a></td></tr><tr><td>Optimism</td><td>EVM</td><td>:white_check_mark:</td><td>:white_check_mark:</td><td>:x:</td><td>:material-web: <a href="https://www.optimism.io/" target="_blank">Website</a><br>:material-file-document: <a href="https://docs.optimism.io/" target="_blank">Developer Docs</a><br>:octicons-package-16: <a href="https://optimistic.etherscan.io/" target="_blank">Block Explorer</a></td></tr><tr><td>Polygon</td><td>EVM</td><td>:white_check_mark:</td><td>:white_check_mark:</td><td>:x:</td><td>:material-web: <a href="https://polygon.technology/" target="_blank">Website</a><br>:material-file-document: <a href="https://docs.polygon.technology/" target="_blank">Developer Docs</a><br>:octicons-package-16: <a href="https://polygonscan.com/" target="_blank">Block Explorer</a></td></tr><tr><td>Scroll</td><td>EVM</td><td>:white_check_mark:</td><td>:white_check_mark:</td><td>:x:</td><td>:material-web: <a href="https://scroll.io/" target="_blank">Website</a><br>:material-file-document: <a href="https://docs.scroll.io/en/home/" target="_blank">Developer Docs</a><br>:octicons-package-16: <a href="https://scrollscan.com/" target="_blank">Block Explorer</a></td></tr><tr><td>Sei</td><td>CosmWasm</td><td>:white_check_mark:</td><td>:white_check_mark:</td><td>:x:</td><td>:material-web: <a href="https://www.sei.io/" target="_blank">Website</a><br>:material-file-document: <a href="https://docs.sei.io/" target="_blank">Developer Docs</a><br>:octicons-package-16: <a href="https://docs.sei.io/learn/explorers#sei-explorers" target="_blank">Block Explorer</a></td></tr><tr><td>SeiEVM</td><td>EVM</td><td>:white_check_mark:</td><td>:white_check_mark:</td><td>:x:</td><td>:material-web: <a href="https://www.sei.io/" target="_blank">Website</a><br>:material-file-document: <a href="https://docs.sei.io/evm" target="_blank">Developer Docs</a><br>:octicons-package-16: <a href="https://seistream.app/" target="_blank">Block Explorer</a></td></tr><tr><td>Sui</td><td>Sui Move VM</td><td>:white_check_mark:</td><td>:white_check_mark:</td><td>:white_check_mark:</td><td>:material-web: <a href="https://www.sui.io/" target="_blank">Website</a><br>:material-file-document: <a href="https://docs.sui.io/" target="_blank">Developer Docs</a><br>:octicons-package-16: <a href="https://suiscan.xyz/" target="_blank">Block Explorer</a></td></tr><tr><td>Unichain</td><td>EVM</td><td>:white_check_mark:</td><td>:white_check_mark:</td><td>:x:</td><td>:material-web: <a href="https://www.unichain.org/" target="_blank">Website</a><br>:material-file-document: <a href="https://docs.unichain.org/docs" target="_blank">Developer Docs</a><br>:octicons-package-16: <a href="https://sepolia.uniscan.xyz/" target="_blank">Block Explorer</a></td></tr><tr><td>World Chain</td><td>EVM</td><td>:white_check_mark:</td><td>:white_check_mark:</td><td>:x:</td><td>:material-web: <a href="https://world.org/world-chain" target="_blank">Website</a><br>:material-file-document: <a href="https://docs.world.org/" target="_blank">Developer Docs</a><br>:octicons-package-16: <a href="https://docs.world.org/world-chain/providers/explorers" target="_blank">Block Explorer</a></td></tr><tr><td>X Layer</td><td>EVM</td><td>:white_check_mark:</td><td>:white_check_mark:</td><td>:x:</td><td>:material-web: <a href="https://web3.okx.com/xlayer" target="_blank">Website</a><br>:material-file-document: <a href="https://web3.okx.com/xlayer/docs/developer/build-on-xlayer/about-xlayer" target="_blank">Developer Docs</a><br>:octicons-package-16: <a href="https://web3.okx.com/explorer/x-layer" target="_blank">Block Explorer</a></td></tr><tr><td>XRPL-EVM</td><td>EVM</td><td>:white_check_mark:</td><td>:white_check_mark:</td><td>:x:</td><td>:material-web: <a href="https://www.xrplevm.org/" target="_blank">Website</a><br>:material-file-document: <a href="https://docs.xrplevm.org/" target="_blank">Developer Docs</a><br>:octicons-package-16: <a href="https://explorer.xrplevm.org/" target="_blank">Block Explorer</a></td></tr></tbody></table>

</div>

### CCTP



<div class="full-width" markdown>

=== "CCTP v1"

    <table data-full-width="true" markdown><thead><th>Blockchain</th><th>Environment</th><th>Mainnet</th><th>Testnet</th><th>Devnet</th><th>Quick Links</th></thead><tbody><tr><td>Ethereum</td><td>EVM</td><td>:white_check_mark:</td><td>:white_check_mark:</td><td>:x:</td><td>:material-web: <a href="https://ethereum.org/" target="_blank">Website</a><br>:material-file-document: <a href="https://ethereum.org/developers/docs/" target="_blank">Developer Docs</a><br>:octicons-package-16: <a href="https://etherscan.io/" target="_blank">Block Explorer</a></td></tr><tr><td>Solana</td><td>SVM</td><td>:white_check_mark:</td><td>:white_check_mark:</td><td>:x:</td><td>:material-web: <a href="https://solana.com/" target="_blank">Website</a><br>:material-file-document: <a href="https://solana.com/docs" target="_blank">Developer Docs</a><br>:octicons-package-16: <a href="https://explorer.solana.com/" target="_blank">Block Explorer</a></td></tr><tr><td>Aptos</td><td>Move VM</td><td>:white_check_mark:</td><td>:white_check_mark:</td><td>:x:</td><td>:material-web: <a href="https://aptosnetwork.com/" target="_blank">Website</a><br>:material-file-document: <a href="https://aptos.dev/" target="_blank">Developer Docs</a><br>:octicons-package-16: <a href="https://explorer.aptoslabs.com/" target="_blank">Block Explorer</a></td></tr><tr><td>Arbitrum</td><td>EVM</td><td>:white_check_mark:</td><td>:white_check_mark:</td><td>:x:</td><td>:material-web: <a href="https://arbitrum.io/" target="_blank">Website</a><br>:material-file-document: <a href="https://docs.arbitrum.io/" target="_blank">Developer Docs</a><br>:octicons-package-16: <a href="https://arbiscan.io/" target="_blank">Block Explorer</a></td></tr><tr><td>Avalanche</td><td>EVM</td><td>:white_check_mark:</td><td>:white_check_mark:</td><td>:x:</td><td>:material-web: <a href="https://www.avax.network/" target="_blank">Website</a><br>:material-file-document: <a href="https://build.avax.network/docs/primary-network" target="_blank">Developer Docs</a><br>:octicons-package-16: <a href="https://snowtrace.io/" target="_blank">Block Explorer</a></td></tr><tr><td>Base</td><td>EVM</td><td>:white_check_mark:</td><td>:white_check_mark:</td><td>:x:</td><td>:material-web: <a href="https://base.org/" target="_blank">Website</a><br>:material-file-document: <a href="https://docs.base.org/" target="_blank">Developer Docs</a><br>:octicons-package-16: <a href="https://basescan.org/" target="_blank">Block Explorer</a></td></tr><tr><td>Optimism</td><td>EVM</td><td>:white_check_mark:</td><td>:white_check_mark:</td><td>:x:</td><td>:material-web: <a href="https://www.optimism.io/" target="_blank">Website</a><br>:material-file-document: <a href="https://docs.optimism.io/" target="_blank">Developer Docs</a><br>:octicons-package-16: <a href="https://optimistic.etherscan.io/" target="_blank">Block Explorer</a></td></tr><tr><td>Polygon</td><td>EVM</td><td>:white_check_mark:</td><td>:white_check_mark:</td><td>:x:</td><td>:material-web: <a href="https://polygon.technology/" target="_blank">Website</a><br>:material-file-document: <a href="https://docs.polygon.technology/" target="_blank">Developer Docs</a><br>:octicons-package-16: <a href="https://polygonscan.com/" target="_blank">Block Explorer</a></td></tr><tr><td>Sui</td><td>Sui Move VM</td><td>:white_check_mark:</td><td>:x:</td><td>:x:</td><td>:material-web: <a href="https://www.sui.io/" target="_blank">Website</a><br>:material-file-document: <a href="https://docs.sui.io/" target="_blank">Developer Docs</a><br>:octicons-package-16: <a href="https://suiscan.xyz/" target="_blank">Block Explorer</a></td></tr><tr><td>Unichain</td><td>EVM</td><td>:white_check_mark:</td><td>:white_check_mark:</td><td>:x:</td><td>:material-web: <a href="https://www.unichain.org/" target="_blank">Website</a><br>:material-file-document: <a href="https://docs.unichain.org/docs" target="_blank">Developer Docs</a><br>:octicons-package-16: <a href="https://sepolia.uniscan.xyz/" target="_blank">Block Explorer</a></td></tr></tbody></table>

=== "CCTP v2"

    <table data-full-width="true" markdown><thead><th>Blockchain</th><th>Environment</th><th>Mainnet</th><th>Testnet</th><th>Devnet</th><th>Quick Links</th></thead><tbody><tr><td>Ethereum</td><td>EVM</td><td>:white_check_mark:</td><td>:white_check_mark:</td><td>:x:</td><td>:material-web: <a href="https://ethereum.org/" target="_blank">Website</a><br>:material-file-document: <a href="https://ethereum.org/developers/docs/" target="_blank">Developer Docs</a><br>:octicons-package-16: <a href="https://etherscan.io/" target="_blank">Block Explorer</a></td></tr><tr><td>Solana</td><td>SVM</td><td>:white_check_mark:</td><td>:white_check_mark:</td><td>:x:</td><td>:material-web: <a href="https://solana.com/" target="_blank">Website</a><br>:material-file-document: <a href="https://solana.com/docs" target="_blank">Developer Docs</a><br>:octicons-package-16: <a href="https://explorer.solana.com/" target="_blank">Block Explorer</a></td></tr><tr><td>Arbitrum</td><td>EVM</td><td>:white_check_mark:</td><td>:white_check_mark:</td><td>:x:</td><td>:material-web: <a href="https://arbitrum.io/" target="_blank">Website</a><br>:material-file-document: <a href="https://docs.arbitrum.io/" target="_blank">Developer Docs</a><br>:octicons-package-16: <a href="https://arbiscan.io/" target="_blank">Block Explorer</a></td></tr><tr><td>Avalanche</td><td>EVM</td><td>:white_check_mark:</td><td>:white_check_mark:</td><td>:x:</td><td>:material-web: <a href="https://www.avax.network/" target="_blank">Website</a><br>:material-file-document: <a href="https://build.avax.network/docs/primary-network" target="_blank">Developer Docs</a><br>:octicons-package-16: <a href="https://snowtrace.io/" target="_blank">Block Explorer</a></td></tr><tr><td>Base</td><td>EVM</td><td>:white_check_mark:</td><td>:white_check_mark:</td><td>:x:</td><td>:material-web: <a href="https://base.org/" target="_blank">Website</a><br>:material-file-document: <a href="https://docs.base.org/" target="_blank">Developer Docs</a><br>:octicons-package-16: <a href="https://basescan.org/" target="_blank">Block Explorer</a></td></tr><tr><td>HyperEVM :material-alert:{ title='⚠️ The HyperEVM integration is experimental, as its node software is not open source. Use Wormhole messaging on HyperEVM with caution.' }</td><td>EVM</td><td>:white_check_mark:</td><td>:x:</td><td>:x:</td><td>:material-web: <a href="https://hyperfoundation.org/" target="_blank">Website</a><br>:material-file-document: <a href="https://hyperliquid.gitbook.io/hyperliquid-docs" target="_blank">Developer Docs</a><br></td></tr><tr><td>Ink</td><td>EVM</td><td>:white_check_mark:</td><td>:white_check_mark:</td><td>:x:</td><td>:material-web: <a href="https://inkonchain.com/" target="_blank">Website</a><br>:material-file-document: <a href="https://docs.inkonchain.com/" target="_blank">Developer Docs</a><br>:octicons-package-16: <a href="https://explorer-sepolia.inkonchain.com/" target="_blank">Block Explorer</a></td></tr><tr><td>Linea</td><td>EVM</td><td>:white_check_mark:</td><td>:white_check_mark:</td><td>:x:</td><td>:material-web: <a href="https://linea.build/" target="_blank">Website</a><br>:material-file-document: <a href="https://docs.linea.build/" target="_blank">Developer Docs</a><br>:octicons-package-16: <a href="https://docs.linea.build/get-started/build/block-explorers" target="_blank">Block Explorer</a></td></tr><tr><td>Monad</td><td>EVM</td><td>:white_check_mark:</td><td>:white_check_mark:</td><td>:x:</td><td>:material-web: <a href="https://www.monad.xyz/" target="_blank">Website</a><br>:material-file-document: <a href="https://docs.monad.xyz/" target="_blank">Developer Docs</a><br>:octicons-package-16: <a href="https://testnet.monvision.io/" target="_blank">Block Explorer</a></td></tr><tr><td>Optimism</td><td>EVM</td><td>:white_check_mark:</td><td>:white_check_mark:</td><td>:x:</td><td>:material-web: <a href="https://www.optimism.io/" target="_blank">Website</a><br>:material-file-document: <a href="https://docs.optimism.io/" target="_blank">Developer Docs</a><br>:octicons-package-16: <a href="https://optimistic.etherscan.io/" target="_blank">Block Explorer</a></td></tr><tr><td>Plume</td><td>EVM</td><td>:white_check_mark:</td><td>:x:</td><td>:x:</td><td>:material-web: <a href="https://plume.org/" target="_blank">Website</a><br>:material-file-document: <a href="https://docs.plume.org/plume" target="_blank">Developer Docs</a><br>:octicons-package-16: <a href="https://explorer.plume.org/" target="_blank">Block Explorer</a></td></tr><tr><td>Polygon</td><td>EVM</td><td>:white_check_mark:</td><td>:white_check_mark:</td><td>:x:</td><td>:material-web: <a href="https://polygon.technology/" target="_blank">Website</a><br>:material-file-document: <a href="https://docs.polygon.technology/" target="_blank">Developer Docs</a><br>:octicons-package-16: <a href="https://polygonscan.com/" target="_blank">Block Explorer</a></td></tr><tr><td>SeiEVM</td><td>EVM</td><td>:white_check_mark:</td><td>:white_check_mark:</td><td>:x:</td><td>:material-web: <a href="https://www.sei.io/" target="_blank">Website</a><br>:material-file-document: <a href="https://docs.sei.io/evm" target="_blank">Developer Docs</a><br>:octicons-package-16: <a href="https://seistream.app/" target="_blank">Block Explorer</a></td></tr><tr><td>Sonic</td><td>EVM</td><td>:white_check_mark:</td><td>:x:</td><td>:x:</td><td>:material-web: <a href="https://www.soniclabs.com/" target="_blank">Website</a><br>:material-file-document: <a href="https://docs.soniclabs.com/" target="_blank">Developer Docs</a><br>:octicons-package-16: <a href="https://sonicscan.org/" target="_blank">Block Explorer</a></td></tr><tr><td>Sui</td><td>Sui Move VM</td><td>:white_check_mark:</td><td>:x:</td><td>:x:</td><td>:material-web: <a href="https://www.sui.io/" target="_blank">Website</a><br>:material-file-document: <a href="https://docs.sui.io/" target="_blank">Developer Docs</a><br>:octicons-package-16: <a href="https://suiscan.xyz/" target="_blank">Block Explorer</a></td></tr><tr><td>Unichain</td><td>EVM</td><td>:white_check_mark:</td><td>:white_check_mark:</td><td>:x:</td><td>:material-web: <a href="https://www.unichain.org/" target="_blank">Website</a><br>:material-file-document: <a href="https://docs.unichain.org/docs" target="_blank">Developer Docs</a><br>:octicons-package-16: <a href="https://sepolia.uniscan.xyz/" target="_blank">Block Explorer</a></td></tr><tr><td>World Chain</td><td>EVM</td><td>:white_check_mark:</td><td>:x:</td><td>:x:</td><td>:material-web: <a href="https://world.org/world-chain" target="_blank">Website</a><br>:material-file-document: <a href="https://docs.world.org/" target="_blank">Developer Docs</a><br>:octicons-package-16: <a href="https://docs.world.org/world-chain/providers/explorers" target="_blank">Block Explorer</a></td></tr></tbody></table>

</div>

### Settlement



<div class="full-width" markdown>

<table data-full-width="true" markdown><thead><th>Blockchain</th><th>Environment</th><th>Mainnet</th><th>Testnet</th><th>Devnet</th><th>Quick Links</th></thead><tbody><tr><td>Ethereum</td><td>EVM</td><td>:white_check_mark:</td><td>:x:</td><td>:x:</td><td>:material-web: <a href="https://ethereum.org/" target="_blank">Website</a><br>:material-file-document: <a href="https://ethereum.org/developers/docs/" target="_blank">Developer Docs</a><br>:octicons-package-16: <a href="https://etherscan.io/" target="_blank">Block Explorer</a></td></tr><tr><td>Solana</td><td>SVM</td><td>:white_check_mark:</td><td>:white_check_mark:</td><td>:x:</td><td>:material-web: <a href="https://solana.com/" target="_blank">Website</a><br>:material-file-document: <a href="https://solana.com/docs" target="_blank">Developer Docs</a><br>:octicons-package-16: <a href="https://explorer.solana.com/" target="_blank">Block Explorer</a></td></tr><tr><td>Arbitrum</td><td>EVM</td><td>:white_check_mark:</td><td>:white_check_mark:</td><td>:x:</td><td>:material-web: <a href="https://arbitrum.io/" target="_blank">Website</a><br>:material-file-document: <a href="https://docs.arbitrum.io/" target="_blank">Developer Docs</a><br>:octicons-package-16: <a href="https://arbiscan.io/" target="_blank">Block Explorer</a></td></tr><tr><td>Avalanche</td><td>EVM</td><td>:white_check_mark:</td><td>:x:</td><td>:x:</td><td>:material-web: <a href="https://www.avax.network/" target="_blank">Website</a><br>:material-file-document: <a href="https://build.avax.network/docs/primary-network" target="_blank">Developer Docs</a><br>:octicons-package-16: <a href="https://snowtrace.io/" target="_blank">Block Explorer</a></td></tr><tr><td>Base</td><td>EVM</td><td>:white_check_mark:</td><td>:x:</td><td>:x:</td><td>:material-web: <a href="https://base.org/" target="_blank">Website</a><br>:material-file-document: <a href="https://docs.base.org/" target="_blank">Developer Docs</a><br>:octicons-package-16: <a href="https://basescan.org/" target="_blank">Block Explorer</a></td></tr><tr><td>Optimism</td><td>EVM</td><td>:white_check_mark:</td><td>:white_check_mark:</td><td>:x:</td><td>:material-web: <a href="https://www.optimism.io/" target="_blank">Website</a><br>:material-file-document: <a href="https://docs.optimism.io/" target="_blank">Developer Docs</a><br>:octicons-package-16: <a href="https://optimistic.etherscan.io/" target="_blank">Block Explorer</a></td></tr><tr><td>Polygon</td><td>EVM</td><td>:white_check_mark:</td><td>:x:</td><td>:x:</td><td>:material-web: <a href="https://polygon.technology/" target="_blank">Website</a><br>:material-file-document: <a href="https://docs.polygon.technology/" target="_blank">Developer Docs</a><br>:octicons-package-16: <a href="https://polygonscan.com/" target="_blank">Block Explorer</a></td></tr><tr><td>Sui</td><td>Sui Move VM</td><td>:white_check_mark:</td><td>:x:</td><td>:x:</td><td>:material-web: <a href="https://www.sui.io/" target="_blank">Website</a><br>:material-file-document: <a href="https://docs.sui.io/" target="_blank">Developer Docs</a><br>:octicons-package-16: <a href="https://suiscan.xyz/" target="_blank">Block Explorer</a></td></tr><tr><td>Unichain</td><td>EVM</td><td>:white_check_mark:</td><td>:x:</td><td>:x:</td><td>:material-web: <a href="https://www.unichain.org/" target="_blank">Website</a><br>:material-file-document: <a href="https://docs.unichain.org/docs" target="_blank">Developer Docs</a><br>:octicons-package-16: <a href="https://sepolia.uniscan.xyz/" target="_blank">Block Explorer</a></td></tr></tbody></table>

</div>

### Multigov



<div class="full-width" markdown>

<table data-full-width="true" markdown><thead><th>Blockchain</th><th>Environment</th><th>Mainnet</th><th>Testnet</th><th>Devnet</th><th>Quick Links</th></thead><tbody><tr><td>Ethereum</td><td>EVM</td><td>:white_check_mark:</td><td>:white_check_mark:</td><td>:white_check_mark:</td><td>:material-web: <a href="https://ethereum.org/" target="_blank">Website</a><br>:material-file-document: <a href="https://ethereum.org/developers/docs/" target="_blank">Developer Docs</a><br>:octicons-package-16: <a href="https://etherscan.io/" target="_blank">Block Explorer</a></td></tr><tr><td>Solana</td><td>SVM</td><td>:white_check_mark:</td><td>:white_check_mark:</td><td>:white_check_mark:</td><td>:material-web: <a href="https://solana.com/" target="_blank">Website</a><br>:material-file-document: <a href="https://solana.com/docs" target="_blank">Developer Docs</a><br>:octicons-package-16: <a href="https://explorer.solana.com/" target="_blank">Block Explorer</a></td></tr><tr><td>0G (Zero Gravity)</td><td>EVM</td><td>:white_check_mark:</td><td>:white_check_mark:</td><td>:white_check_mark:</td><td>:material-web: <a href="https://0g.ai/" target="_blank">Website</a><br>:material-file-document: <a href="https://docs.0g.ai/" target="_blank">Developer Docs</a><br>:octicons-package-16: <a href="https://chainscan.0g.ai" target="_blank">Block Explorer</a></td></tr><tr><td>Arbitrum</td><td>EVM</td><td>:white_check_mark:</td><td>:white_check_mark:</td><td>:white_check_mark:</td><td>:material-web: <a href="https://arbitrum.io/" target="_blank">Website</a><br>:material-file-document: <a href="https://docs.arbitrum.io/" target="_blank">Developer Docs</a><br>:octicons-package-16: <a href="https://arbiscan.io/" target="_blank">Block Explorer</a></td></tr><tr><td>Avalanche</td><td>EVM</td><td>:white_check_mark:</td><td>:white_check_mark:</td><td>:white_check_mark:</td><td>:material-web: <a href="https://www.avax.network/" target="_blank">Website</a><br>:material-file-document: <a href="https://build.avax.network/docs/primary-network" target="_blank">Developer Docs</a><br>:octicons-package-16: <a href="https://snowtrace.io/" target="_blank">Block Explorer</a></td></tr><tr><td>Base</td><td>EVM</td><td>:white_check_mark:</td><td>:white_check_mark:</td><td>:white_check_mark:</td><td>:material-web: <a href="https://base.org/" target="_blank">Website</a><br>:material-file-document: <a href="https://docs.base.org/" target="_blank">Developer Docs</a><br>:octicons-package-16: <a href="https://basescan.org/" target="_blank">Block Explorer</a></td></tr><tr><td>Berachain</td><td>EVM</td><td>:white_check_mark:</td><td>:white_check_mark:</td><td>:white_check_mark:</td><td>:material-web: <a href="https://www.berachain.com/" target="_blank">Website</a><br>:material-file-document: <a href="https://docs.berachain.com/" target="_blank">Developer Docs</a><br>:octicons-package-16: <a href="https://berascan.com/" target="_blank">Block Explorer</a></td></tr><tr><td>BNB Smart Chain</td><td>EVM</td><td>:white_check_mark:</td><td>:white_check_mark:</td><td>:white_check_mark:</td><td>:material-web: <a href="https://www.bnbchain.org/en/bnb-smart-chain" target="_blank">Website</a><br>:material-file-document: <a href="https://docs.bnbchain.org/" target="_blank">Developer Docs</a><br>:octicons-package-16: <a href="https://bscscan.com/" target="_blank">Block Explorer</a></td></tr><tr><td>Celo</td><td>EVM</td><td>:white_check_mark:</td><td>:white_check_mark:</td><td>:white_check_mark:</td><td>:material-web: <a href="https://celo.org/" target="_blank">Website</a><br>:material-file-document: <a href="https://docs.celo.org/" target="_blank">Developer Docs</a><br>:octicons-package-16: <a href="https://celo.blockscout.com/" target="_blank">Block Explorer</a></td></tr><tr><td>Converge</td><td>EVM</td><td>:white_check_mark:</td><td>:white_check_mark:</td><td>:white_check_mark:</td><td>:material-web: <a href="https://www.convergeonchain.xyz/" target="_blank">Website</a><br></td></tr><tr><td>CreditCoin</td><td>EVM</td><td>:white_check_mark:</td><td>:white_check_mark:</td><td>:white_check_mark:</td><td>:material-web: <a href="https://creditcoin.org/" target="_blank">Website</a><br>:material-file-document: <a href="https://docs.creditcoin.org/" target="_blank">Developer Docs</a><br>:octicons-package-16: <a href="https://creditcoin.subscan.io/" target="_blank">Block Explorer</a></td></tr><tr><td>Fantom</td><td>EVM</td><td>:white_check_mark:</td><td>:white_check_mark:</td><td>:white_check_mark:</td><td>:material-web: <a href="https://fantom.foundation/" target="_blank">Website</a><br>:material-file-document: <a href="https://docs.fantom.foundation/" target="_blank">Developer Docs</a><br>:octicons-package-16: <a href="https://explorer.fantom.network/" target="_blank">Block Explorer</a></td></tr><tr><td>HyperCore</td><td>EVM</td><td>:white_check_mark:</td><td>:white_check_mark:</td><td>:white_check_mark:</td><td>:material-web: <a href="https://hyperliquid.gitbook.io/hyperliquid-docs/hypercore" target="_blank">Website</a><br>:material-file-document: <a href="https://hyperliquid.gitbook.io/hyperliquid-docs/hypercore" target="_blank">Developer Docs</a><br></td></tr><tr><td>HyperEVM :material-alert:{ title='⚠️ The HyperEVM integration is experimental, as its node software is not open source. Use Wormhole messaging on HyperEVM with caution.' }</td><td>EVM</td><td>:white_check_mark:</td><td>:white_check_mark:</td><td>:white_check_mark:</td><td>:material-web: <a href="https://hyperfoundation.org/" target="_blank">Website</a><br>:material-file-document: <a href="https://hyperliquid.gitbook.io/hyperliquid-docs" target="_blank">Developer Docs</a><br></td></tr><tr><td>Ink</td><td>EVM</td><td>:white_check_mark:</td><td>:white_check_mark:</td><td>:white_check_mark:</td><td>:material-web: <a href="https://inkonchain.com/" target="_blank">Website</a><br>:material-file-document: <a href="https://docs.inkonchain.com/" target="_blank">Developer Docs</a><br>:octicons-package-16: <a href="https://explorer-sepolia.inkonchain.com/" target="_blank">Block Explorer</a></td></tr><tr><td>Kaia</td><td>EVM</td><td>:white_check_mark:</td><td>:white_check_mark:</td><td>:white_check_mark:</td><td>:material-web: <a href="https://www.kaia.io/" target="_blank">Website</a><br>:material-file-document: <a href="https://docs.kaia.io/" target="_blank">Developer Docs</a><br>:octicons-package-16: <a href="https://kaiascan.io/" target="_blank">Block Explorer</a></td></tr><tr><td>Linea</td><td>EVM</td><td>:white_check_mark:</td><td>:white_check_mark:</td><td>:white_check_mark:</td><td>:material-web: <a href="https://linea.build/" target="_blank">Website</a><br>:material-file-document: <a href="https://docs.linea.build/" target="_blank">Developer Docs</a><br>:octicons-package-16: <a href="https://docs.linea.build/get-started/build/block-explorers" target="_blank">Block Explorer</a></td></tr><tr><td>Mantle</td><td>EVM</td><td>:white_check_mark:</td><td>:white_check_mark:</td><td>:white_check_mark:</td><td>:material-web: <a href="https://www.mantle.xyz/" target="_blank">Website</a><br>:material-file-document: <a href="https://docs.mantle.xyz/network/" target="_blank">Developer Docs</a><br>:octicons-package-16: <a href="https://mantlescan.xyz/" target="_blank">Block Explorer</a></td></tr><tr><td>MegaETH</td><td>EVM</td><td>:white_check_mark:</td><td>:white_check_mark:</td><td>:white_check_mark:</td><td>:material-web: <a href="https://www.megaeth.com/" target="_blank">Website</a><br>:material-file-document: <a href="https://docs.megaeth.com/" target="_blank">Developer Docs</a><br>:octicons-package-16: <a href="https://mega.etherscan.io/" target="_blank">Block Explorer</a></td></tr><tr><td>Mezo</td><td>EVM</td><td>:white_check_mark:</td><td>:white_check_mark:</td><td>:white_check_mark:</td><td>:material-web: <a href="https://mezo.org/" target="_blank">Website</a><br>:material-file-document: <a href="https://mezo.org/docs/developers/" target="_blank">Developer Docs</a><br>:octicons-package-16: <a href="https://explorer.test.mezo.org/" target="_blank">Block Explorer</a></td></tr><tr><td>Moca</td><td>EVM</td><td>:white_check_mark:</td><td>:white_check_mark:</td><td>:white_check_mark:</td><td>:material-web: <a href="https://mocachain.org/en" target="_blank">Website</a><br>:material-file-document: <a href="https://mocacoin.gitbook.io/litepaper" target="_blank">Developer Docs</a><br>:octicons-package-16: <a href="https://devnet-scan.mocachain.org/" target="_blank">Block Explorer</a></td></tr><tr><td>Monad</td><td>EVM</td><td>:white_check_mark:</td><td>:white_check_mark:</td><td>:white_check_mark:</td><td>:material-web: <a href="https://www.monad.xyz/" target="_blank">Website</a><br>:material-file-document: <a href="https://docs.monad.xyz/" target="_blank">Developer Docs</a><br>:octicons-package-16: <a href="https://testnet.monvision.io/" target="_blank">Block Explorer</a></td></tr><tr><td>Moonbeam</td><td>EVM</td><td>:white_check_mark:</td><td>:white_check_mark:</td><td>:white_check_mark:</td><td>:material-web: <a href="https://moonbeam.network/" target="_blank">Website</a><br>:material-file-document: <a href="https://docs.moonbeam.network/" target="_blank">Developer Docs</a><br>:octicons-package-16: <a href="https://moonscan.io/" target="_blank">Block Explorer</a></td></tr><tr><td>Optimism</td><td>EVM</td><td>:white_check_mark:</td><td>:white_check_mark:</td><td>:white_check_mark:</td><td>:material-web: <a href="https://www.optimism.io/" target="_blank">Website</a><br>:material-file-document: <a href="https://docs.optimism.io/" target="_blank">Developer Docs</a><br>:octicons-package-16: <a href="https://optimistic.etherscan.io/" target="_blank">Block Explorer</a></td></tr><tr><td>Plasma</td><td>EVM</td><td>:white_check_mark:</td><td>:white_check_mark:</td><td>:white_check_mark:</td><td>:material-web: <a href="https://www.plasma.to/" target="_blank">Website</a><br>:material-file-document: <a href="https://www.plasma.to/docs/get-started/introduction/start-here" target="_blank">Developer Docs</a><br>:octicons-package-16: <a href="https://plasmascan.to/" target="_blank">Block Explorer</a></td></tr><tr><td>Plume</td><td>EVM</td><td>:white_check_mark:</td><td>:white_check_mark:</td><td>:white_check_mark:</td><td>:material-web: <a href="https://plume.org/" target="_blank">Website</a><br>:material-file-document: <a href="https://docs.plume.org/plume" target="_blank">Developer Docs</a><br>:octicons-package-16: <a href="https://explorer.plume.org/" target="_blank">Block Explorer</a></td></tr><tr><td>Polygon</td><td>EVM</td><td>:white_check_mark:</td><td>:white_check_mark:</td><td>:white_check_mark:</td><td>:material-web: <a href="https://polygon.technology/" target="_blank">Website</a><br>:material-file-document: <a href="https://docs.polygon.technology/" target="_blank">Developer Docs</a><br>:octicons-package-16: <a href="https://polygonscan.com/" target="_blank">Block Explorer</a></td></tr><tr><td>Scroll</td><td>EVM</td><td>:white_check_mark:</td><td>:white_check_mark:</td><td>:white_check_mark:</td><td>:material-web: <a href="https://scroll.io/" target="_blank">Website</a><br>:material-file-document: <a href="https://docs.scroll.io/en/home/" target="_blank">Developer Docs</a><br>:octicons-package-16: <a href="https://scrollscan.com/" target="_blank">Block Explorer</a></td></tr><tr><td>Sei</td><td>CosmWasm</td><td>:white_check_mark:</td><td>:white_check_mark:</td><td>:white_check_mark:</td><td>:material-web: <a href="https://www.sei.io/" target="_blank">Website</a><br>:material-file-document: <a href="https://docs.sei.io/" target="_blank">Developer Docs</a><br>:octicons-package-16: <a href="https://docs.sei.io/learn/explorers#sei-explorers" target="_blank">Block Explorer</a></td></tr><tr><td>SeiEVM</td><td>EVM</td><td>:white_check_mark:</td><td>:white_check_mark:</td><td>:white_check_mark:</td><td>:material-web: <a href="https://www.sei.io/" target="_blank">Website</a><br>:material-file-document: <a href="https://docs.sei.io/evm" target="_blank">Developer Docs</a><br>:octicons-package-16: <a href="https://seistream.app/" target="_blank">Block Explorer</a></td></tr><tr><td>Sonic</td><td>EVM</td><td>:white_check_mark:</td><td>:white_check_mark:</td><td>:white_check_mark:</td><td>:material-web: <a href="https://www.soniclabs.com/" target="_blank">Website</a><br>:material-file-document: <a href="https://docs.soniclabs.com/" target="_blank">Developer Docs</a><br>:octicons-package-16: <a href="https://sonicscan.org/" target="_blank">Block Explorer</a></td></tr><tr><td>Unichain</td><td>EVM</td><td>:white_check_mark:</td><td>:white_check_mark:</td><td>:white_check_mark:</td><td>:material-web: <a href="https://www.unichain.org/" target="_blank">Website</a><br>:material-file-document: <a href="https://docs.unichain.org/docs" target="_blank">Developer Docs</a><br>:octicons-package-16: <a href="https://sepolia.uniscan.xyz/" target="_blank">Block Explorer</a></td></tr><tr><td>World Chain</td><td>EVM</td><td>:white_check_mark:</td><td>:white_check_mark:</td><td>:white_check_mark:</td><td>:material-web: <a href="https://world.org/world-chain" target="_blank">Website</a><br>:material-file-document: <a href="https://docs.world.org/" target="_blank">Developer Docs</a><br>:octicons-package-16: <a href="https://docs.world.org/world-chain/providers/explorers" target="_blank">Block Explorer</a></td></tr><tr><td>X Layer</td><td>EVM</td><td>:white_check_mark:</td><td>:white_check_mark:</td><td>:white_check_mark:</td><td>:material-web: <a href="https://web3.okx.com/xlayer" target="_blank">Website</a><br>:material-file-document: <a href="https://web3.okx.com/xlayer/docs/developer/build-on-xlayer/about-xlayer" target="_blank">Developer Docs</a><br>:octicons-package-16: <a href="https://web3.okx.com/explorer/x-layer" target="_blank">Block Explorer</a></td></tr><tr><td>XRPL-EVM</td><td>EVM</td><td>:white_check_mark:</td><td>:white_check_mark:</td><td>:white_check_mark:</td><td>:material-web: <a href="https://www.xrplevm.org/" target="_blank">Website</a><br>:material-file-document: <a href="https://docs.xrplevm.org/" target="_blank">Developer Docs</a><br>:octicons-package-16: <a href="https://explorer.xrplevm.org/" target="_blank">Block Explorer</a></td></tr></tbody></table>

</div>


---

Page Title: Testnet Faucets

- Resolved Markdown: https://wormhole.com/docs/ai/pages/products-reference-testnet-faucets.md
- Canonical (HTML): https://wormhole.com/docs/products/reference/testnet-faucets/
- Summary: This page includes resources to quickly find the Testnet tokens you need to deploy and test applications and contracts on Wormhole's supported networks.
- Word Count: 1395; Token Estimate: 3553

# Testnet Faucets

Don't let the need for testnet tokens get in the way of building your next great idea with Wormhole. Use this guide to quickly locate the testnet token faucets you need to deploy and test applications and contracts on Wormhole's supported networks.




<div class="full-width" markdown>

### EVM

<table data-full-width="true" markdown><thead><th>Testnet</th><th>Environment</th><th>Token</th><th>Faucet</th></thead><tbody><tr><td>Ethereum Holesky</td><td>EVM</td><td>ETH</td><td><a href="https://www.alchemy.com/faucets/ethereum-holesky" target="_blank">Alchemy Faucet</a></td></tr><tr><td>Ethereum Sepolia</td><td>EVM</td><td>ETH</td><td><a href="https://www.alchemy.com/faucets/ethereum-sepolia" target="_blank">Alchemy Faucet</a></td></tr><tr><td>0G (Zero Gravity)</td><td>EVM</td><td>0G</td><td><a href="https://faucet.0g.ai/" target="_blank">0G Official Faucet</a></td></tr><tr><td>Arbitrum Sepolia</td><td>EVM</td><td>ETH</td><td><a href="https://docs.arbitrum.io/for-devs/dev-tools-and-resources/chain-info#faucets" target="_blank">List of Faucets</a></td></tr><tr><td>Avalanche</td><td>EVM</td><td>AVAX</td><td><a href="https://core.app/tools/testnet-faucet/?subnet=c&token=c" target="_blank">Official Avalanche Faucet</a></td></tr><tr><td>Base Sepolia</td><td>EVM</td><td>ETH</td><td><a href="https://docs.base.org/docs/tools/network-faucets/" target="_blank">List of Faucets</a></td></tr><tr><td>Berachain</td><td>EVM</td><td>BERA</td><td><a href="https://bepolia.faucet.berachain.com/" target="_blank">Official Berachain Faucet</a></td></tr><tr><td>BNB Smart Chain</td><td>EVM</td><td>BNB</td><td><a href="https://www.bnbchain.org/en/testnet-faucet" target="_blank">Official BNB Faucet</a></td></tr><tr><td>Sonic</td><td>EVM</td><td>S</td><td><a href="https://testnet.soniclabs.com/account" target="_blank">Official Sonic Faucet</a></td></tr><tr><td>HyperEVM :material-alert:{ title='⚠️ The HyperEVM integration is experimental, as its node software is not open source. Use Wormhole messaging on HyperEVM with caution.' }</td><td>EVM</td><td>mock USDC</td><td><a href="https://app.hyperliquid-testnet.xyz/drip" target="_blank">Official Hyperliquid Faucet</a></td></tr><tr><td>Ink</td><td>EVM</td><td>ETH</td><td><a href="https://inkonchain.com/faucet" target="_blank">Official Ink Faucet</a></td></tr><tr><td>Kaia</td><td>EVM</td><td>KAIA</td><td><a href="https://www.kaia.io/faucet" target="_blank">Official Kaia Faucet</a></td></tr><tr><td>Linea</td><td>EVM</td><td>ETH</td><td><a href="https://docs.linea.build/get-started/how-to/get-testnet-eth" target="_blank">List of Faucets</a></td></tr><tr><td>Mantle</td><td>EVM</td><td>MNT</td><td><a href="https://faucet.sepolia.mantle.xyz/" target="_blank">Official Mantle Faucet</a></td></tr><tr><td>MegaETH</td><td>EVM</td><td>ETH</td><td><a href="https://testnet.megaeth.com/" target="_blank">Official MegaETH Faucet</a></td></tr><tr><td>Moca</td><td>EVM</td><td>MOCA</td><td><a href="https://devnet-scan.mocachain.org/faucet" target="_blank">Official Moca Faucet</a></td></tr><tr><td>Monad Testnet</td><td>EVM</td><td>MON</td><td><a href="https://testnet.monad.xyz/" target="_blank">Official Monad Faucet</a></td></tr><tr><td>Moonbeam</td><td>EVM</td><td>DEV</td><td><a href="https://faucet.moonbeam.network/" target="_blank">Official Moonbeam Faucet</a></td></tr><tr><td>Optimism Sepolia</td><td>EVM</td><td>ETH</td><td><a href="https://console.optimism.io/faucet" target="_blank">Superchain Faucet</a></td></tr><tr><td>Plasma</td><td>EVM</td><td>XPL</td><td><a href="https://faucet.quicknode.com/plasma" target="_blank">QuickNode Faucet</a></td></tr><tr><td>Plume</td><td>EVM</td><td>PLUME</td><td><a href="https://faucet.plume.org/" target="_blank">Official Plume Faucet</a></td></tr><tr><td>Polygon Amoy</td><td>EVM</td><td>POL</td><td><a href="https://faucet.polygon.technology/" target="_blank">Official Polygon Faucet</a></td></tr><tr><td>Scroll</td><td>EVM</td><td>SCR</td><td><a href="https://docs.scroll.io/en/developers/faq/#testnet-eth" target="_blank">List of Faucets</a></td></tr><tr><td>SeiEVM</td><td>EVM</td><td>SEI</td><td><a href="https://docs.sei.io/learn/faucet" target="_blank">Sei Atlantic-2 Faucet</a></td></tr><tr><td>Unichain</td><td>EVM</td><td>ETH</td><td><a href="https://faucet.quicknode.com/unichain/sepolia" target="_blank">QuickNode Faucet</a></td></tr><tr><td>World Chain</td><td>EVM</td><td>ETH</td><td><a href="https://www.alchemy.com/faucets/world-chain-sepolia" target="_blank">Alchemy Faucet</a></td></tr><tr><td>X Layer</td><td>EVM</td><td>OKB</td><td><a href="https://web3.okx.com/xlayer/faucet" target="_blank">X Layer Official Faucet</a></td></tr><tr><td>XRPL-EVM</td><td>EVM</td><td>XRP</td><td><a href="https://faucet.xrplevm.org/" target="_blank">XRPL Official Faucet</a></td></tr></tbody></table>

### SVM

<table data-full-width="true" markdown><thead><th>Testnet</th><th>Environment</th><th>Token</th><th>Faucet</th></thead><tbody><tr><td>Pythnet</td><td>SVM</td><td>ETH</td><td><a href="https://console.optimism.io/faucet" target="_blank">Superchain Faucet</a></td></tr></tbody></table>

### AVM

<table data-full-width="true" markdown><thead><th>Testnet</th><th>Environment</th><th>Token</th><th>Faucet</th></thead><tbody><tr><td>Algorand</td><td>AVM</td><td>ALGO</td><td><a href="https://lora.algokit.io/testnet/fund" target="_blank">Official Algorand Faucet</a></td></tr></tbody></table>

### CosmWasm

<table data-full-width="true" markdown><thead><th>Testnet</th><th>Environment</th><th>Token</th><th>Faucet</th></thead><tbody><tr><td>Celestia</td><td>CosmWasm</td><td>TIA</td><td><a href="https://discord.com/invite/celestiacommunity" target="_blank">Discord Faucet</a></td></tr><tr><td>Cosmos Hub</td><td>CosmWasm</td><td>ATOM</td><td><a href="https://discord.com/invite/cosmosnetwork" target="_blank">Discord Faucet</a></td></tr><tr><td>Injective</td><td>CosmWasm</td><td>INJ</td><td><a href="https://testnet.faucet.injective.network/" target="_blank">Official Injective Faucet</a></td></tr><tr><td>Kujira</td><td>CosmWasm</td><td>KUJI</td><td><a href="https://discord.com/channels/970650215801569330/1009931570263629854" target="_blank">Discord Faucet</a></td></tr><tr><td>Neutron</td><td>CosmWasm</td><td>NTRN</td><td><a href="https://docs.neutron.org/developers/faq#where-is-the-testnet-faucet" target="_blank">List of Faucets</a></td></tr><tr><td>Noble</td><td>CosmWasm</td><td>USDC</td><td><a href="https://faucet.circle.com/" target="_blank">Circle Faucet</a></td></tr><tr><td>Osmosis</td><td>CosmWasm</td><td>OSMO</td><td><a href="https://faucet.testnet.osmosis.zone/" target="_blank">Official Osmosis Faucet</a></td></tr><tr><td>SEDA</td><td>CosmWasm</td><td>SEDA</td><td><a href="https://devnet.explorer.seda.xyz/faucet" target="_blank">Official SEDA Faucet</a></td></tr><tr><td>Sei</td><td>CosmWasm</td><td>SEI</td><td><a href="https://docs.sei.io/learn/faucet" target="_blank">Sei Atlantic-2 Faucet</a></td></tr></tbody></table>

### Move VM

<table data-full-width="true" markdown><thead><th>Testnet</th><th>Environment</th><th>Token</th><th>Faucet</th></thead><tbody><tr><td>Aptos</td><td>Move VM</td><td>APT</td><td><a href="https://www.aptosfaucet.com/" target="_blank">Official Aptos Faucet</a></td></tr></tbody></table>

### NEAR VM

<table data-full-width="true" markdown><thead><th>Testnet</th><th>Environment</th><th>Token</th><th>Faucet</th></thead><tbody><tr><td>NEAR</td><td>NEAR VM</td><td>NEAR</td><td><a href="https://near-faucet.io/" target="_blank">Official NEAR Faucet</a></td></tr></tbody></table>

### Sui Move VM

<table data-full-width="true" markdown><thead><th>Testnet</th><th>Environment</th><th>Token</th><th>Faucet</th></thead><tbody><tr><td>Sui</td><td>Sui Move VM</td><td>SUI</td><td><a href="https://docs.sui.io/guides/developer/getting-started/get-coins" target="_blank">List of Faucets</a></td></tr></tbody></table>

</div>


---

Page Title: VAAs

- Resolved Markdown: https://wormhole.com/docs/ai/pages/protocol-infrastructure-vaas.md
- Canonical (HTML): https://wormhole.com/docs/protocol/infrastructure/vaas/
- Summary: Learn about Verified Action Approvals (VAAs) in Wormhole, their structure, validation, and role in cross-chain communication.
- Word Count: 2154; Token Estimate: 3321

# Verified Action Approvals

Verified Action Approvals (VAAs) are Wormhole's core messaging primitive. They are packets of cross-chain data emitted whenever a cross-chain application contract interacts with the Core Contract.

[Guardians](/docs/protocol/infrastructure/guardians/){target=\_blank} validate messages emitted by contracts before sending them to the target chain. Once a two-thirds supermajority of Guardians agree the message is valid, they sign a keccak256 hash of the message body.

The message is wrapped up in a structure called a VAA, which combines the message with the Guardian signatures to form a proof.

VAAs are uniquely indexed by the (`emitter_chain`, `emitter_address`, `sequence`) tuple. To obtain a VAA, one can query the [Wormholescan API](https://docs.wormholescan.io/){target=\_blank} with this information.

The `sequence` field depends on the final ordering of blocks on the emitter chain. When a lower consistency level is chosen (i.e., not waiting for finality), there is a chance that chain reorganizations could lead to multiple, different VAAs appearing for what looks like the "same" message on the user side.

The tuple (`emitter_chain`, `emitter_address`, `sequence`) can only be considered unique if the chain does not undergo a reorg and the block containing the message has effectively reached finality. However, there is always a small chance of an extended reorg that could invalidate or alter a previously emitted sequence number.

## VAA Format

The basic VAA consists of header and body components described as follows:

- **Header**: Holds metadata about the current VAA, the Guardian set that is currently active, and the list of signatures gathered so far.
    - **`version` ++"byte"++**: The VAA Version.
    - **`guardian_set_index` ++"u32"++**: Indicates which Guardian set is signing.
    - **`len_signatures` ++"u8"++**: The number of signatures stored.
    - **`signatures` ++"[]signature"++**: The collection of Guardian signatures.

    Where each `signature` is:

    - **`index` ++"u8"++**: The index of this Guardian in the Guardian set.
    - **`signature` ++"[65]byte"++**: The ECDSA signature.

- **Body**: _deterministically_ derived from an on-chain message. Any two Guardians processing the same message must derive the same resulting body to maintain a one-to-one relationship between VAAs and messages to avoid double-processing messages.
    - **`timestamp` ++"u32"++**: The timestamp of the block this message was published in.
    - **`nonce` ++"u32"++**: The nonce associated with this message.
    - **`emitter_chain` ++"u16"++**: The id of the chain that emitted the message.
    - **`emitter_address` ++"[32]byte"++**: The contract address (Wormhole formatted) that called the Core Contract.
    - **`sequence` ++"u64"++**: The auto-incrementing integer that represents the number of messages published by this emitter.
    - **`consistency_level` ++"u8"++**: The consistency level (finality) required by this emitter.
    - **`payload` ++"[]byte"++**: Arbitrary bytes containing the data to be acted on.

The deterministic nature of the body is only strictly true once the chain's state is finalized. If a reorg occurs, and a transaction that previously appeared in block X is replaced by block Y, Guardians observing different forks may generate different VAAs for what the emitter contract believes is the same message. This scenario is less likely once a block is sufficiently buried, but it can still happen depending on the consistency level.

The body contains relevant information for entities, such as contracts or other systems, that process or utilize VAAs. When a function like `parseAndVerifyVAA` is called, the body is returned, allowing verification of the `emitterAddress` to determine if the VAA originated from a trusted contract.

Because VAAs have no destination, they are effectively multicast. Any Core Contract on any chain in the network will verify VAAs as authentic. If a VAA has a specific destination, relayers are responsible for appropriately completing that delivery.

## Consistency and Finality

The consistency level determines whether Guardians wait for a chain's final commitment state or issue a VAA sooner under less-final conditions. This choice is especially relevant for blockchains without instant finality, where the risk of reorganization remains until a block is deeply confirmed.

Guardian watchers are specialized processes that monitor each blockchain in real-time. They enforce the selected consistency level by deciding whether enough commitment has been reached before signing and emitting a VAA. Some chains allow only one commitment level (effectively final), while others let integrators pick between near-final or fully finalized states. Choosing a faster option speeds up VAA production but increases reorg risk. A more conservative option takes longer but reduces the likelihood of rollback.

## Signatures

The body of the VAA is hashed twice with `keccak256` to produce the signed digest message.

```js
// hash the bytes of the body twice
digest = keccak256(keccak256(body))
// sign the result 
signature = ecdsa_sign(digest, key)
```

!!!tip "Hash vs. double hash"
    Different implementations of the ECDSA signature validation may apply a keccak256 hash to the message passed, so care must be taken to pass the correct arguments.

    For example, the [Solana secp256k1 program](https://solana.com/docs/core/programs#secp256k1-program){target=\_blank} will hash the message passed. In this case, the argument for the message should be a single hash of the body, not the twice-hashed body.

## Payload Types

Different applications built on Wormhole may specify a format for the payloads attached to a VAA. This payload provides information on the target chain and contract so it can take action (e.g., minting tokens to a receiver address).

### Token Transfer

Many bridges use a lockup/mint and burn/unlock mechanism to transfer tokens between chains. Wormhole's generic message-passing protocol handles the routing of lock and burn events across chains to ensure Wormhole's Wrapped Token Transfer (WTT) is chain-agnostic and can be rapidly integrated into any network with a Wormhole contract.

Transferring tokens from the sending chain to the destination chain requires the following steps:

1. Lock the token on the sending chain.
2. The sending chain emits a message as proof the token lockup is complete.
3. The destination chain receives the message confirming the lockup event on the sending chain.
4. The token is minted on the destination chain.

The message the sending chain emits to verify the lockup is referred to as a transfer message and has the following structure:

- **`payload_id` ++"u8"++**: The ID of the payload. This should be set to `1` for a token transfer.
- **`amount` ++"u256"++**: Amount of tokens being transferred.
- **`token_address` ++"u8[32]"++**: Address on the source chain.
- **`token_chain` ++"u16"++**: Numeric ID for the source chain.
- **`to` ++"u8[32]"++**: Address on the destination chain.
- **`to_chain` ++"u16"++**: Numeric ID for the destination chain.
- **`fee` ++"u256"++**: Portion of amount paid to a relayer.

This structure contains everything the destination chain needs to learn about a lockup event. Once the destination chain receives this payload, it can mint the corresponding asset.

Note that the destination chain is agnostic regarding how the tokens on the sending side were locked. They could have been burned by a mint or locked in a custody account. The protocol relays the event once enough Guardians have attested to its existence.

### Attestation

While the destination chain can trust the message from the sending chain to inform it of token lockup events, it has no way of verifying the correct token is locked up. To solve this, WTT supports token attestation.

To create a token attestation, the sending chain emits a message containing metadata about a token, which the destination chain may use to preserve the name, symbol, and decimal precision of a token address.

The message format for token attestation is as follows:

- **`payload_id` ++"u8"++**: The ID of the payload. This should be set to `2` for an attestation.
- **`token_address` ++"[32]byte"++**: Address of the originating token contract.
- **`token_chain` ++"u16"++**: Chain ID of the originating token.
- **`decimals` ++"u8"++**: Number of decimals this token should have.
- **`symbol` ++"[32]byte"++**: Short name of asset.
- **`name` ++"[32]byte"++**: Full name of asset.

#### Attestation Tips

Be aware of the following considerations when working with attestations:

- Attestations use a fixed-length byte array to encode UTF8 token name and symbol data. Because the byte array is fixed length, the data contained may truncate multibyte Unicode characters.

- When sending an attestation VAA, it is recommended to send the longest UTF8 prefix that doesn't truncate a character and then right-pad it with zero bytes.

- When parsing an attestation VAA, it is recommended to trim all trailing zero bytes and convert the remainder to UTF-8 via any lossy algorithm.

- Be mindful that different on-chain systems may have different VAA parsers, resulting in different names/symbols on different chains if the string is long or contains invalid UTF8.

- Without knowing a token's decimal precision, the destination chain cannot correctly mint the number of tokens when processing a transfer. For this reason, WTT requires an attestation for each token transfer.

### Token Transfer with Message

The Token Transfer with Message data structure is identical to the token-only data structure, except for the following:

- **`fee` field**: Replaced with the `from_address` field.
- **`payload` field**: Is added containing arbitrary bytes. A dApp may include additional data in this arbitrary byte field to inform some application-specific behavior.

This VAA type was previously known as Contract Controlled Transfer and is also sometimes referred to as a `payload3` message. The Token Transfer with Message data structure is as follows:

- **`payload_id` ++"u8"++**: The ID of the payload. This should be set to `3` for a token transfer with message.
- **`amount` ++"u256"++**: Amount of tokens being transferred.
- **`token_address` ++"u8[32]"++**: Address on the source chain.
- **`token_chain` ++"u16"++**: Numeric ID for the source chain.
- **`to` ++"u8[32]"++**: Address on the destination chain.
- **`to_chain` ++"u16"++**: Numeric ID for the destination chain.
- **`from_address` ++"u8[32]"++**: Address that called WTT on the source chain.
- **`payload` ++"[]byte"++**: Message, arbitrary bytes, app-specific.

### Governance

Governance VAAs don't have a `payload_id` field like the preceding formats. Instead, they trigger an action in the deployed contracts (for example, an upgrade).

#### Action Structure

Governance messages contain pre-defined actions, which can target the various Wormhole modules currently deployed on-chain. The structure includes the following fields:

- **`module` ++"u8[32]"++**: Contains a right-aligned module identifier.
- **`action` ++"u8"++**: Predefined governance action to execute.
- **`chain`  ++"u16"++**: Chain the action is targeting. This should be set to `0` for all chains.
- **`args`  ++"any"++**: Arguments to the action.

Below is an example message containing a governance action triggering a code upgrade to the Solana Core Contract. The module field here is a right-aligned encoding of the ASCII Core, represented as a 32-byte hex string.

```js
module:       0x0000000000000000000000000000000000000000000000000000436f7265
action:       1
chain:        1
new_contract: 0x348567293758957162374959376192374884562522281937446234828323
```

#### Actions

The meaning of each numeric action is pre-defined and documented in the Wormhole design documents. For each application, the relevant definitions can be found via these links:

- [Core governance actions](https://github.com/wormhole-foundation/wormhole/blob/main/whitepapers/0002_governance_messaging.md){target=\_blank}
- [WTT governance actions](https://github.com/wormhole-foundation/wormhole/blob/main/whitepapers/0003_token_bridge.md){target=\_blank}

## Lifetime of a Message

Anyone can submit a VAA to the target chain. Guardians typically don't perform this step to avoid transaction fees. Instead, applications built on top of Wormhole can acquire a VAA via the Guardian RPC and submit it in a separate flow.

With the concepts now defined, it is possible to illustrate a full flow for message passing between two chains. The following stages demonstrate each step of processing that the Wormhole network performs to route a message.

1. **A message is emitted by a contract running on Chain A**: Any contract can emit messages, and the Guardian Network observes supported chains for these events. For full Guardian Set chains, all 19 Guardians directly observe on-chain messages. For delegated chains, a delegated subset performs direct observation and broadcasts signed delegate observations to the rest of the network. In the diagram, Guardians are represented as a single entity for simplicity, but observation and signing are performed independently by each participating Guardian.
2. **Signatures are aggregated**: Guardians independently observe and sign the message. For full Guardian Set chains, all Guardians perform on-chain observation. For delegated chains, a delegated subset observes and broadcasts `SignedDelegateObservation` messages to the rest of the network. Canonical Guardians wait for delegate quorum before contributing their signatures. Once a two-thirds majority (13 out of 19) have signed, the signatures are combined with the message and metadata to produce a VAA.
3. **VAA submitted to target chain**: The VAA acts as proof that the Guardians have collectively attested the existence of the message payload. The VAA is submitted (or relayed) to the target chain to be processed by a receiving contract and complete the final step.

![Lifetime of a message diagram](/docs/images/protocol/infrastructure/vaas/lifetime-vaa-diagram.webp)

## Next Steps

<div class="grid cards" markdown>

-   :octicons-book-16:{ .lg .middle } **Guardians**

    ---

    Explore Wormhole's Guardian Network, a decentralized system for secure, scalable cross-chain communication across various blockchain ecosystems.

    [:custom-arrow: Learn About Guardians](/docs/protocol/infrastructure/guardians/)

-   :octicons-tools-16:{ .lg .middle } **Wormhole Dev Arena**

    ---

    A structured learning hub with hands-on tutorials across the Wormhole ecosystem.

    [:custom-arrow: Explore the Dev Arena](https://arena.wormhole.com/ecosystem){target=\_blank}

</div>


---

Page Title: Wormhole Connect

- Resolved Markdown: https://wormhole.com/docs/ai/pages/products-connect-overview.md
- Canonical (HTML): https://wormhole.com/docs/products/connect/overview/
- Summary: With Wormhole Connect, you can seamlessly bridge digital assets and data across a wide range of supported blockchain networks.
- Word Count: 515; Token Estimate: 875

# Connect Overview 

With the Wormhole Connect widget, you can enable users to perform multichain asset transfers directly within your application. Connect simplifies the complexity of bridging, offering a single, intuitive point of interaction for moving assets across diverse blockchains. This empowers you to access liquidity and opportunities across any connected network seamlessly.

## Key Features

Connect's notable features include:

- **In-app multichain transfers**: Bridge assets without leaving your app.
- **Customizable features**: Specify chains and custom RPCs, manage tokens, and select bridging [routes](/docs/products/connect/concepts/routes/){target=\_blank} such as WTT, CCTP, or NTT.
- **Customizable UI**: Style the bridge interface to match your brand.
- **Optional destination gas**: Provide gas for initial transactions on the target chain.
- **Wrapped and native assets support**: Supports both wrapped and native tokens and integrates with Settlement.

Be sure to check the [Feature Support Matrix](/docs/products/connect/reference/support-matrix/#feature-support-matrix){target=\_blank} to find out which routes and features are supported for each chain.

## How It Works

When a user initiates a multichain transfer, Connect walks them through key steps and automates the transfer process behind the scenes, including:

1. **Initiating the transfer**: Connect your chosen wallet to the source chain, select asset and source chain for the transfer.
2. **Finalize transfer setup**: Connect the destination wallet, select the target chain and select a bridging route (manual or automatic).
3. **Transaction submission on source chain**: Confirms the transfer details to trigger the asset lock or deposit on the initial blockchain. Connect will guide you through the transaction process.
4. **VAA or attestation creation**: Wormhole [Guardians](/docs/protocol/infrastructure/guardians/){target=\_blank} observe the source transaction and produce a [Verifiable Action Approval (VAA)](/docs/protocol/infrastructure/vaas/){target=\_blank}.
5. **Relaying to destination**: The VAA or attestation is automatically relayed to the destination chain.
6. **Verification on destination**: Contracts on the target chain receive and verify the incoming VAA.
7. **Asset release/minting**: Upon successful verification, the equivalent assets are either released or minted on the target chain and delivered to your wallet.

!!! tip
    If you want more hands on experience with Connect, checkout [Portal Bridge](https://portalbridge.com/){target=\_blank}.

## Use Cases

Here are some key use cases that highlight the power and versatility of Connect:

- **Cross-Chain Swaps and Liquidity Aggregation**

    - **[Connect](/docs/products/connect/get-started/)**: Handles user-friendly asset transfers.
    - **[Native Token Transfers](/docs/products/token-transfers/native-token-transfers/overview/)**: Moves native assets across chains.
    - **[Queries](/docs/products/queries/overview/)**: Fetches real-time prices for optimal trade execution.

- **Cross-Chain Payment Widgets**

    - **[Connect](/docs/products/connect/get-started/)**: Facilitates seamless payments in various tokens.
    - **[Native Token Transfers](/docs/products/token-transfers/native-token-transfers/overview/)**: Ensures direct, native asset transfers.

- **Web3 Game Asset Transfers**

    - **[Connect](/docs/products/connect/get-started/)**: Provide a user-friendly way to move game tokens across chains.
    - **[Wrapped Token Transfers](/docs/products/token-transfers/wrapped-token-transfers/overview/)**: Handle the underlying lock-and-mint logic securely.

## Next Steps 

Add Connect to your app with these key setup steps:

[timeline(docs/.snippets/text/products/connect/overview/connect-timeline.json)]


---

Page Title: Wormhole Connect Migration Guides

- Resolved Markdown: https://wormhole.com/docs/ai/pages/products-connect-guides-upgrade.md
- Canonical (HTML): https://wormhole.com/docs/products/connect/guides/upgrade/
- Summary: Step-by-step guidance for migrating between major versions of Wormhole Connect, including configuration changes and route updates.
- Word Count: 3270; Token Estimate: 6442

# Wormhole Connect Migration Guides

This page collects step-by-step migration guides for major versions of Wormhole Connect. Choose the section that matches the version you are upgrading from:

- [V5 → V6](#v5-to-v6) - Default automatic routes replaced by [Executor](/docs/products/messaging/guides/executor/)-powered routes.
- [V0/V1/V2 → V3](#v0-v1-v2-to-v3) - Configuration restructure (`networks` → `chains`, capitalized chain names, route plugin system, consolidated `ui` properties).

## V5 to V6 {: #v5-to-v6 }

Wormhole Connect v6 removes the legacy "automatic" routes in favor of [Executor](/docs/products/messaging/guides/executor/)-powered replacements. **Most integrators need no code changes** - default usage and `DEFAULT_ROUTES` are wired to the new routes automatically.

The breaking change was introduced in [PR #4025](https://github.com/wormhole-foundation/wormhole-connect/pull/4025){target=\_blank}. See the full [v6 release notes](https://github.com/wormhole-foundation/wormhole-connect/releases){target=\_blank} for additional context.

### Route Replacements

| Removed | Replacement |
|---|---|
| `AutomaticCCTPRoute` | `cctpV2FastExecutorRoute()`, `cctpV2StandardExecutorRoute()` |
| `AutomaticTokenBridgeRoute`, `TokenBridgeRoute` | `executorTokenBridgeRoute()` |
| `nttAutomaticRoute` | `nttExecutorRoute` |

Route name strings (used in `filterRoutes`, telemetry):

| Old | New |
|---|---|
| `AutomaticCCTP` | `CCTPV2FastExecutorRoute`, `CCTPV2StandardExecutorRoute` |
| `AutomaticTokenBridge` | `TokenBridgeExecutorRoute` |
| `AutomaticNtt` | `NttExecutorRoute` |

**Unchanged**: `CCTPRoute`, `TBTCRoute`, `nttManualRoute`, `nttExecutorRoute`, `nttRoutes`, and all Mayan and LiFi routes.

### When You Need to Change Code

You only need changes if you:

- Import any removed route by name.
- Build a custom `routes: [...]` array using a removed route.
- Compare against old route name strings (in `filterRoutes`, telemetry handlers, etc.).

Default usage (`<WormholeConnect />` with no `routes` config) and `DEFAULT_ROUTES` are wired to the new routes automatically.

!!! tip "Note"
    The new Executor routes are **factory functions** - invoke them with `()` when adding to a `routes` array. The legacy automatic routes were class constructors passed directly.

### Update the Connect Package

Install the v6 release:

```bash
npm install @wormhole-foundation/wormhole-connect@^6.0
```

### `DEFAULT_ROUTES` Has Been Updated

The default route set used when integrators don't specify a `routes` array now uses Executor-based routes:

=== "v5.x"

    ```typescript
    DEFAULT_ROUTES = [
      AutomaticCCTPRoute,
      CCTPRoute,
      AutomaticTokenBridgeRoute,
      TokenBridgeRoute,
      TBTCRoute,
    ];
    ```

=== "v6.x"

    ```typescript
    DEFAULT_ROUTES = [
      cctpV2FastExecutorRoute(),
      cctpV2StandardExecutorRoute(),
      CCTPRoute,
      executorTokenBridgeRoute(),
      TBTCRoute,
    ];
    ```

If you rely on `DEFAULT_ROUTES` without overriding it, no code changes are required.

### Update Custom `routes` Arrays

If you pass a custom `routes` array, replace removed routes with their Executor equivalents and remember to invoke the new factory functions with `()`:

=== "v5.x"

    ```typescript
    import {
      AutomaticCCTPRoute,
      CCTPRoute,
      AutomaticTokenBridgeRoute,
    } from '@wormhole-foundation/wormhole-connect';

    const config = {
      routes: [AutomaticCCTPRoute, CCTPRoute, AutomaticTokenBridgeRoute],
    };
    ```

=== "v6.x"

    ```typescript
    import {
      cctpV2FastExecutorRoute,
      cctpV2StandardExecutorRoute,
      CCTPRoute,
      executorTokenBridgeRoute,
    } from '@wormhole-foundation/wormhole-connect';

    const config = {
      routes: [
        cctpV2FastExecutorRoute(),
        cctpV2StandardExecutorRoute(),
        CCTPRoute,
        executorTokenBridgeRoute(),
      ],
    };
    ```

### Update NTT Routes

If you use the `nttRoutes(...)` helper, no changes are needed. Otherwise, swap `nttAutomaticRoute` for `nttExecutorRoute`:

=== "v5.x"

    ```typescript
    import { nttAutomaticRoute } from '@wormhole-foundation/wormhole-connect/ntt';

    const config = {
      routes: [nttAutomaticRoute(myNttConfig)],
    };
    ```

=== "v6.x"

    ```typescript
    import { nttExecutorRoute } from '@wormhole-foundation/wormhole-connect/ntt';

    const config = {
      routes: [nttExecutorRoute({ ntt: myNttConfig })],
    };
    ```

## V0/V1/V2 to V3 {: #v0-v1-v2-to-v3 }

The Wormhole Connect feature has been updated to **version 3.0**, introducing a modernized design and improved routing for faster native-to-native token transfers. This stable release comes with several breaking changes in how to configure the application, requiring minor updates to your integration.

This guide will help you migrate to the new version in just a few simple steps. By following this migration guide, you'll learn how to:

 - Update to the latest Connect package.
 - Apply configuration changes to the `WormholeConnectConfig` object.
 - Understand new routing capabilities and plugin options.

These updates ensure better performance and a smoother integration experience.

!!! tip "Note"
    Connect versions v1.x and v2.x share the same configuration structure. This guide outlines a unified upgrade process to v3.x, regardless of whether you're using v0.x, v1.x, or v2.x.

## Update the Connect Package

To begin the migration process, update the Connect [**npm package**](https://www.npmjs.com/package/@wormhole-foundation/wormhole-connect){target=\_blank} to the latest version 3.0. Updating to the latest version provides access to the newest features and improvements, including the modernized design and enhanced routing capabilities.

Run the following command in your terminal:

```bash
npm install @wormhole-foundation/wormhole-connect@^3.0
```

This command installs the latest stable version of Wormhole Connect and prepares your environment for the new configuration changes.

## Update the `WormholeConnectConfig` Object

In version 3.0, the `config.WormholeConnectConfig` object underwent several breaking changes. Most of these changes are minor and can be applied quickly. Below is a summary of the key changes, followed by detailed examples.

### Summary of Breaking Changes

- Chain names are now capitalized. For example:`solana` → `Solana`.
- `env` renamed to `network` and is now capitalized. For example: `mainnet` → `Mainnet`.
- `networks` renamed to `chains`, with capitalized names.
- `routes` updated to use route plugins.
- `nttGroups` removed in favor of route plugin configuration.
- `tokensConfig` updated, with a new key `wrappedTokens` added.
- Many UI-related properties consolidated under a top-level `ui` key.
- `customTheme` and `mode` were removed, replaced by a top-level `theme` property.

These changes are explained in more detail below, with examples for easy reference.

### Capitalize Chain Names

In version 3.0, chain names are now consistent with the `Chain` type from the [Wormhole TypeScript SDK](https://github.com/wormhole-foundation/wormhole-sdk-ts){target=\_blank}, and must be capitalized. This affects all config properties where a chain is referenced, including `rpcs`, `rest`, `graphql`, and `chains`.

=== "v0.x"

    ```typescript
    import { WormholeConnectConfig } from '@wormhole-foundation/wormhole-connect';

    const config: WormholeConnectConfig = {
      rpcs: {
        ethereum: 'INSERT_ETH_RPC_URL',
        solana: 'INSERT_SOLANA_RPC_URL',
      },
    };
    ```

=== "v1.x"

    ```typescript
    import { WormholeConnectConfig } from '@wormhole-foundation/wormhole-connect';

    const config: WormholeConnectConfig = {
      rpcs: {
        Ethereum: 'INSERT_ETH_RPC_URL',
        Solana: 'INSERT_SOLANA_RPC_URL',
      },
    };
    ```

=== "v3.x"

    ```typescript
    import { type config } from '@wormhole-foundation/wormhole-connect';

    const config: config.WormholeConnectConfig = {
      rpcs: {
        Ethereum: 'INSERT_ETH_RPC_URL',
        Solana: 'INSERT_SOLANA_RPC_URL',
      },
    };
    ```

You can find the complete list of supported chain names in the [Wormhole TypeScript SDK](https://github.com/wormhole-foundation/wormhole-sdk-ts/blob/main/core/base/src/constants/chains.ts#L6-L71){target=\_blank}.

### Rename `env` to `network`

The `env` property has been renamed to `network`, with capitalized values. This change affects how you configure Testnet and Mainnet environments.

=== "v0.x"

    ```typescript
    import { WormholeConnectConfig } from '@wormhole-foundation/wormhole-connect';

    const config: WormholeConnectConfig = {
      env: 'testnet',
    };
    ```

=== "v1.x"

    ```typescript
    import { WormholeConnectConfig } from '@wormhole-foundation/wormhole-connect';

    const config: WormholeConnectConfig = {
      network: 'Testnet',
    };
    ```

=== "v3.x"

    ```typescript
    import { type config } from '@wormhole-foundation/wormhole-connect';

    const config: config.WormholeConnectConfig = {
      network: 'Testnet',
    };
    ```

If you don’t explicitly set the `network` value, Connect will default to `Mainnet`.

```typescript
// Defaults to Mainnet
const config: config.WormholeConnectConfig = {};
```

For more information, refer to the [network constants list](https://github.com/wormhole-foundation/wormhole-sdk-ts/blob/main/core/base/src/constants/networks.ts){target=\_blank}.

### Rename `networks` to `chains`

The `networks` property, which allowed whitelisting chains, is now renamed `chains`, and the chain names are capitalized.

=== "v0.x"

    ```typescript
    import { WormholeConnectConfig } from '@wormhole-foundation/wormhole-connect';

    const config: WormholeConnectConfig = {
      networks: ['solana', 'ethereum'],
    };
    ```
=== "v1.x"

    ```typescript
    import { WormholeConnectConfig } from '@wormhole-foundation/wormhole-connect';

    const config: WormholeConnectConfig = {
      chains: ['Solana', 'Ethereum'],
    };
    ```
=== "v3.x"

    ```typescript
    import { type config } from '@wormhole-foundation/wormhole-connect';

    const config: config.WormholeConnectConfig = {
      chains: ['Solana', 'Ethereum'],
    };
    ```

### Update `routes` to Use Route Plugins

The `routes` property in Connect version 3.0 has significantly improved. Previously, `routes` was a simple array of strings. The latest version has been transformed into a flexible plugin system, allowing you to include specific routes for various protocols.

By default, if no `routes` property is set, Connect will provide routes for two core protocols:

 - [Wrapped Token Transfers (WTT)](/docs/products/token-transfers/wrapped-token-transfers/overview/){target=\_blank}
 - [CCTP](/docs/products/cctp-bridge/overview/){target=\_blank}

For most use cases, integrators require more than the default routes. The new `routes` property allows you to specify which protocols to include and exclude any routes unnecessary for your application, including both default and third-party routes.

#### Available `route` Plugins

The `@wormhole-foundation/wormhole-connect` package offers a variety of `route` plugins to give you flexibility in handling different protocols. You can choose from the following `route` exports for your integration:

???- tip "`route` Plugins"
    - **`TokenBridgeRoute`**: Manually redeemed WTT route.
    - **`AutomaticTokenBridgeRoute`**: Automatically redeemed (relayed) WTT route.
    - **`CCTPRoute`**: Manually redeemed CCTP route.
    - **`AutomaticCCTPRoute`**: Automatically redeemed (relayed) CCTP route.
    - **`DEFAULT_ROUTES`**: Array containing the four preceding routes (TokenBridgeRoute, AutomaticTokenBridgeRoute, CCTPRoute, AutomaticCCTPRoute).
    - **`nttAutomaticRoute(nttConfig)`**: Function that returns the automatically-redeemed (relayed) Native Token Transfer (NTT) route.
    - **`nttManualRoute(nttConfig)`**: Function that returns the manually-redeemed NTT route.
    - **`nttExecutorRoute(nttConfig)`**: Function that returns the Executor-powered NTT route for one-click transfers.
    - **`MayanRoute`**: Route that offers multiple Mayan protocols.
    - **`MayanRouteSWIFT`**: Route for Mayan’s Swift protocol only.
    - **`MayanRouteMCTP`**: Route for Mayan’s MCTP protocol only.
    - **`MayanRouteWH`**: Route for Mayan’s original Wormhole transfer protocol.

In addition to these routes, developers can create custom routes for their own Wormhole-based protocols. For examples, refer to the [NTT](https://github.com/wormhole-foundation/native-token-transfers/tree/main/sdk/route){target=\_blank} and the [Mayan](https://github.com/mayan-finance/wormhole-sdk-route){target=\_blank} example GitHub repositories.

For further details on the Route plugin interface, refer to the [Wormhole TypeScript SDK route code](https://github.com/wormhole-foundation/wormhole-sdk-ts/blob/main/connect/src/routes/route.ts){target=\_blank}.

Now that you know the available `route` plugins, let's explore some examples of configuring them.

#### Example: Offer Only CCTP Transfers

To configure Connect to offer only USDC transfers via the CCTP route, use the following configuration:

```typescript
import WormholeConnect, {
  AutomaticCCTPRoute,
  type config,
} from '@wormhole-foundation/wormhole-connect';

const config: config.WormholeConnectConfig = {
  routes: [AutomaticCCTPRoute],
};

<WormholeConnect config={config} />;
```

#### Example: Offer All Default Routes and Third-Party Plugins

In this example, Connect is configured with routes for both default protocols (WTT and CCTP), as well as third-party protocols like [Native Token Transfers (NTT)](/docs/products/token-transfers/native-token-transfers/overview/){target=\_blank} and [Mayan Swap](https://swap.mayan.finance/){target=\_blank}.

```typescript
import WormholeConnect, {
  DEFAULT_ROUTES,
  MayanRouteSWIFT,
  type config,
} from '@wormhole-foundation/wormhole-connect';
import { nttExecutorRoute } from '@wormhole-foundation/wormhole-connect/ntt';

import { myNttConfig } from './consts'; // Custom NTT configuration

const config: config.WormholeConnectConfig = {
  routes: [...DEFAULT_ROUTES, nttExecutorRoute({ ntt: myNttConfig }), MayanRouteSWIFT],
};

<WormholeConnect config={config} />;
```

This flexible plugin allows you to combine default routes (such as WTT and CCTP) with third-party protocols, offering complete control over which routes are available in your application.

### Update the `tokensConfig` Structure

In Connect version 3.0, the `tokensConfig` property has been updated to simplify the structure and improve flexibility for token handling across chains. The previous configuration has been streamlined, and a new key, `wrappedTokens,` has been introduced to handle foreign assets more effectively.

Key Changes to `tokensConfig`:

 - **Capitalized chain names**: All chain names, like `ethereum`, must now be capitalized, such as `Ethereum`, to maintain consistency with the rest of the Wormhole SDK.
 - **`wrappedTokens`**: This new key replaces `foreignAssets` and defines the wrapped token addresses on foreign chains, making it easier to manage cross-chain transfers. It consolidates the wrapped token addresses into a cleaner structure. These addresses must be specified to enable token transfers to and from the foreign chain via WTT routes.
 - **Simplified decimals**: Instead of using a map of decimal values for different chains, you now only need to provide a single decimals value for the token's native chain.

=== "v0.x"

    In the old structure, the `foreignAssets` field defined the token’s presence on other chains, and `decimals` were mapped across multiple chains.

    ```typescript
    import WormholeConnect, {
      WormholeConnectConfig,
    } from '@wormhole-foundation/wormhole-connect';

    const config: WormholeConnectConfig = {
      tokensConfig: {
        WETH: {
          key: 'WETH',
          symbol: 'WETH',
          nativeChain: 'ethereum',
          icon: Icon.ETH,
          tokenId: {
            chain: 'ethereum',
            address: '0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2',
          },
          coinGeckoId: 'ethereum',
          color: '#62688F',
          decimals: { Ethereum: 18, default: 8 },
          foreignAssets: {
            Solana: {
              address: '7vfCXTUXx5WJV5JADk17DUJ4ksgau7utNKj4b963voxs',
              decimals: 8,
            },
          },
        },
      },
    };
    ```

=== "v1.x"

    In v1.0, `foreignAssets` has been replaced with `wrappedTokens`, simplifying token transfers across chains by directly mapping wrapped token addresses. The `decimals` value is now a simple number representing the token’s decimals on its native chain.

    ```typescript
    import WormholeConnect, {
      WormholeConnectConfig,
    } from '@wormhole-foundation/wormhole-connect';

    const config: WormholeConnectConfig = {
      tokensConfig: {
        WETH: {
          key: 'WETH',
          symbol: 'WETH',
          nativeChain: 'Ethereum', // Chain name now capitalized
          icon: Icon.ETH,
          tokenId: {
            chain: 'Ethereum',
            address: '0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2',
          },
          coinGeckoId: 'ethereum',
          color: '#62688F',
          decimals: 18, // Simplified decimals field
        },
      },
      wrappedTokens: {
        WETH: {
          Solana: '7vfCXTUXx5WJV5JADk17DUJ4ksgau7utNKj4b963voxs',
          /* additional chains */
        },
      },
    };
    ```

=== "v3.x"

    In v3.0, `foreignAssets` has been replaced with `wrappedTokens`, simplifying token transfers across chains by directly mapping wrapped token addresses. The `decimals` value is now a simple number representing the token’s decimals on its native chain.

    ```typescript
    import WormholeConnect, {
      type config,
    } from '@wormhole-foundation/wormhole-connect';

    const config: config.WormholeConnectConfig = {
      tokensConfig: {
        WETH: {
          key: 'WETH',
          symbol: 'WETH',
          nativeChain: 'Ethereum', // Chain name now capitalized
          icon: Icon.ETH,
          tokenId: {
            chain: 'Ethereum',
            address: '0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2',
          },
          coinGeckoId: 'ethereum',
          color: '#62688F',
          decimals: 18, // Simplified decimals field
        },
      },
      wrappedTokens: {
        WETH: {
          Solana: '7vfCXTUXx5WJV5JADk17DUJ4ksgau7utNKj4b963voxs',
          /* additional chains */
        },
      },
    };
    ```

### Update NTT Configuration

In Connect version 3.0, the `nttGroups` property, which was used to configure Native Token Transfers (NTT), has been removed. Instead, the NTT configuration is passed directly to the NTT route constructor. This update simplifies the setup and provides more flexibility for defining NTT routes.

Key changes:

 - **Removed `nttGroups`**: The `nttGroups` property has been removed from the configuration and is now passed as an argument to the `nttExecutorRoute` function.
 - **Direct NTT route configuration**: NTT routes are now defined more explicitly, allowing for a more organized structure when specifying tokens, chains, and managers.

This change simplifies the configuration process by providing a cleaner, more flexible way to handle NTT routes across different chains.

=== "v0.x"

    In the previous version, `nttGroups` defined the NTT managers and transceivers for different tokens across multiple chains.

    ```typescript
    import WormholeConnect, {
      nttRoutes,
      WormholeConnectConfig,
    } from '@wormhole-foundation/wormhole-connect';

    const config: WormholeConnectConfig = {
      nttGroups: {
        Lido_wstETH: {
          nttManagers: [
            {
              chainName: 'ethereum',
              address: '0xb948a93827d68a82F6513Ad178964Da487fe2BD9',
              tokenKey: 'wstETH',
              transceivers: [
                {
                  address: '0xA1ACC1e6edaB281Febd91E3515093F1DE81F25c0',
                  type: 'wormhole',
                },
              ],
            },
            {
              chainName: 'bsc',
              address: '0x6981F5621691CBfE3DdD524dE71076b79F0A0278',
              tokenKey: 'wstETH',
              transceivers: [
                {
                  address: '0xbe3F7e06872E0dF6CD7FF35B7aa4Bb1446DC9986',
                  type: 'wormhole',
                },
              ],
            },
          ],
        },
      },
    };
    ```

=== "v1.x"

    In v1.0, `nttGroups` has been removed, and the configuration is passed to the NTT route constructor as an argument. The tokens and corresponding transceivers are now clearly defined within the `nttRoutes` configuration.

    ```typescript
    import WormholeConnect, {
      nttRoutes,
      WormholeConnectConfig,
    } from '@wormhole-foundation/wormhole-connect';

    const config: WormholeConnectConfig = {
      routes: [
        ...nttRoutes({
          tokens: {
            Lido_wstETH: [
              {
                chain: 'Ethereum',
                manager: '0xb948a93827d68a82F6513Ad178964Da487fe2BD9',
                token: '0x7f39C581F595B53c5cb19bD0b3f8dA6c935E2Ca0',
                transceiver: [
                  {
                    address: '0xA1ACC1e6edaB281Febd91E3515093F1DE81F25c0',
                    type: 'wormhole',
                  },
                ],
              },
              {
                chain: 'Bsc',
                manager: '0x6981F5621691CBfE3DdD524dE71076b79F0A0278',
                token: '0x26c5e01524d2E6280A48F2c50fF6De7e52E9611C',
                transceiver: [
                  {
                    address: '0xbe3F7e06872E0dF6CD7FF35B7aa4Bb1446DC9986',
                    type: 'wormhole',
                  },
                ],
              },
            ],
          },
        }),
        /* other routes */
      ],
    };
    ```

=== "v3.x"

    In v3.0, `nttGroups` has been removed, and the configuration is passed to the NTT route constructor as an argument. The tokens and corresponding transceivers are now clearly defined within the `nttExecutorRoute` configuration.

    ```typescript
    import WormholeConnect, {
      type config,
    } from '@wormhole-foundation/wormhole-connect';
    import { nttExecutorRoute } from '@wormhole-foundation/wormhole-connect/ntt';

    const config: config.WormholeConnectConfig = {
      routes: [
        nttExecutorRoute({
          ntt: {
            tokens: {
              Lido_wstETH: [
                {
                  chain: 'Ethereum',
                  manager: '0xb948a93827d68a82F6513Ad178964Da487fe2BD9',
                  token: '0x7f39C581F595B53c5cb19bD0b3f8dA6c935E2Ca0',
                  transceiver: [
                    {
                      address: '0xA1ACC1e6edaB281Febd91E3515093F1DE81F25c0',
                      type: 'wormhole',
                    },
                  ],
                },
                {
                  chain: 'Bsc',
                  manager: '0x6981F5621691CBfE3DdD524dE71076b79F0A0278',
                  token: '0x26c5e01524d2E6280A48F2c50fF6De7e52E9611C',
                  transceiver: [
                    {
                      address: '0xbe3F7e06872E0dF6CD7FF35B7aa4Bb1446DC9986',
                      type: 'wormhole',
                    },
                  ],
                },
              ],
            },
          },
        }),
        /* other routes */
      ],
    };
    ```

    In this new structure, NTT routes are passed directly through the `nttExecutorRoute` function, with the `token`, `chain`, `manager` and `transceiver` clearly defined for each supported asset.

### Update UI Configuration

In Connect version 3.0, the user interface configuration has been significantly updated. Several previously scattered UI properties have now been consolidated under a new `ui` key, making the UI configuration cleaner and easier to manage.

Key UI changes:

 - **Consolidated UI properties**: Many UI-related properties moved under a new top-level ui key for better organization.
 - **Removed `customTheme` and `mode`**: These properties have been removed in favor of a new top-level prop called `theme`, which simplifies theming and allows dynamic switching between themes.

#### UI Properties

The following properties that were previously defined at the root level of the configuration are now part of the `ui` key:

 - **`explorer` → `ui.explorer`**: Specifies the explorer to use for viewing transactions.
 - **`bridgeDefaults` → `ui.defaultInputs`**: Sets default input values for the bridge, such as the source and destination chains and token.
 - **`pageHeader` → `ui.pageHeader`**: Sets the title and header for the page.
 - **`menu` → `ui.menu`**: Defines the menu items displayed in the interface.
 - **`searchTx` → `ui.searchTx`**: Configures the transaction search functionality.
 - **`partnerLogo` → `ui.partnerLogo`**: Displays a partner's logo on the interface.
 - **`walletConnectProjectId` → `ui.walletConnectProjectId`**: Integrates WalletConnect into the UI.
 - **`showHamburgerMenu` → `ui.showHamburgerMenu`**: Enables or disables the hamburger menu for navigation.

Additionally, there are two new properties under `ui`:

 - **`ui.title`**: Sets the title rendered in the top left corner of the UI. The default is "Wormhole Connect".
 - **`ui.getHelpUrl`**: URL that Connect will render when an unknown error occurs, allowing users to seek help. This can link to a Discord server or any other support channel.

```typescript
import WormholeConnect, {
  type config,
} from '@wormhole-foundation/wormhole-connect';

const config: config.WormholeConnectConfig = {
  ui: {
    title: 'My Custom Bridge Example',
    getHelpUrl: 'https://examplehelp.com/',
    menu: [
      {
        label: 'Support',
        href: 'https://examplehelp.com/support',
        target: '_blank',
        order: 1, // Order of appearance in the menu
      },
      {
        label: 'About',
        href: 'https://examplehelp.com/about',
        target: '_blank',
        order: 2,
      },
    ],
    showHamburgerMenu: false,
  },
};
```

#### UI Configuration

In the old structure, UI-related settings like `explorer` and `bridgeDefaults` were defined at the root level of the configuration. In version 3.0, these properties are now organized under the `ui` key, improving the configuration's readability and manageability.

=== "v0.x"

    ```typescript
    
    const config: WormholeConnectConfig = {
      bridgeDefaults: {
        fromNetwork: 'solana',
        toNetwork: 'ethereum',
        tokenKey: 'USDC',
        requiredNetwork: 'solana',
      },
      showHamburgerMenu: true,
    };
    ```

=== "v1.x"

    ```typescript
    const config: WormholeConnectConfig = {
      ui: {
        defaultInputs: {
          fromChain: 'Solana', // Chain names now capitalized
          toChain: 'Ethereum',
          tokenKey: 'USDC',
          requiredChain: 'Solana',
        },
        showHamburgerMenu: true,
      },
    };
    ```

=== "v3.x"

    ```typescript
    const config: config.WormholeConnectConfig = {
      ui: {
        defaultInputs: {
          fromChain: 'Solana', // Chain names now capitalized
          toChain: 'Ethereum',
          tokenKey: 'USDC',
          requiredChain: 'Solana',
        },
        showHamburgerMenu: true,
      },
    };
    ```

#### Remove `customTheme` and `mode` Properties

In version 3.0, the `customTheme` and `mode` properties, which were previously used to set themes, have been removed. They have been replaced by a new top-level prop called `theme`, which allows for more flexibility and dynamic updates to themes.

Important details:

 - The `theme` prop is not part of the `config` object and is passed separately to Connect.
 - `config` cannot be modified after Connect has mounted, but the `theme` can be updated dynamically to support changes such as switching between light and dark modes or updating color schemes.

=== "v0.x"

    ```typescript
    import WormholeConnect, {
      WormholeConnectConfig,
    } from '@wormhole-foundation/wormhole-connect';

    const config: WormholeConnectConfig = {
      customTheme: {
        primaryColor: '#4266f5',
        secondaryColor: '#ff5733',
      },
      mode: 'dark',
    };

    <WormholeConnect config={config} />;
    ```

=== "^v1.x" 

    ```typescript
    import WormholeConnect, {
      WormholeConnectTheme,
    } from '@wormhole-foundation/wormhole-connect';

    const theme: WormholeConnectTheme = {
      mode: 'dark', // Can be dynamically changed
      font: 'Arial',
      button: {
        primary: '#4266f5',
      },
    };

    <WormholeConnect config={config} theme={theme} />;
    ```

### Removed Configuration Properties

Several configuration properties have been removed in Connect version 3.0. These keys no longer have any effect, and providing values for them in the configuration will not result in any changes.

Removed config keys:

 - `cta`
 - `cctpWarning`
 - `pageSubHeader`
 - `moreTokens`
 - `moreChains`
 - `ethBridgeMaxAmount`
 - `wstETHBridgeMaxAmount`
 - `customTheme`
 - `mode`

If your current setup includes any of these properties, you can safely remove them, as they are no longer supported in v3.0.

## Use the CDN-Hosted Version of Wormhole Connect

For those using the CDN-hosted version of Wormhole Connect, the package's installation and integration have been updated. You must install the Connect package from npm and use the new `wormholeConnectHosted` utility function.

### Install and Integrate the Hosted Version

1. Install the Connect package via npm:

    ```bash
    npm install @wormhole-foundation/wormhole-connect@^3.0
    ```

2. After installing the package, you can embed Connect into your page by adding the following code:

    ```typescript
    import { wormholeConnectHosted } from '@wormhole-foundation/wormhole-connect';

    const container = document.getElementById('connect')!;

    wormholeConnectHosted(container);
    ```

### Example: Custom Configuration for Hosted Version

The `wormholeConnectHosted` function accepts two parameters: `config` and `theme`. This allows you to customize the routes and apply a theme directly within the hosted version. Here’s an example of how you can pass a custom configuration:

```typescript
import {
  wormholeConnectHosted,
  MayanRoute,
} from '@wormhole-foundation/wormhole-connect';

const container = document.getElementById('connect')!;

wormholeConnectHosted(container, {
  config: {
    routes: [MayanRoute],
    eventHandler: (e) => {
      console.log('Connect event', e);
    },
  },
  theme: {
    background: {
      default: '#004547',
    },
  },
});
```

In this example, the `config` object defines the routes (in this case, using the Mayan route), while the `theme` object allows customization of the Connect interface (e.g., background color).


---

Page Title: Wormhole Finality | Consistency Levels

- Resolved Markdown: https://wormhole.com/docs/ai/pages/products-reference-consistency-levels.md
- Canonical (HTML): https://wormhole.com/docs/products/reference/consistency-levels/
- Summary: This page documents how long to wait for finality before signing, based on each chain’s consistency (finality) level and consensus mechanism.
- Word Count: 2208; Token Estimate: 5327

# Wormhole Finality

Wormhole allows integrators to specify the finality level at which a VAA is verified. This determines how long the Guardians wait before attesting to a message.

These options provide different trade-offs between latency and re-org resistance:

- `instant` is sufficient when low latency is required and limited reorg risk is acceptable.
- `safe` provides additional protection while maintaining reasonable latency.
- `finalized` offers the strongest guarantees but increases confirmation time.

`finalized` provides the strongest protection against chain re-orgs. Selecting `instant`, `safe`, or a custom finality level increases exposure to re-org risk and should be evaluated carefully based on the application's risk profile.

!!! warning

    Some Wormhole-supported EVM chains support setting a custom finality level. Wormhole Contributors recommend using this advanced feature with caution. Choosing a level of finality other than `finalized` — including `instant`, `safe`, or any custom configuration — on EVM chains exposes you to [re-org risk](https://www.alchemy.com/overviews/what-is-a-reorg){target=\_blank}. This is especially dangerous when moving assets cross-chain, because assets released or minted on the destination chain may not have been burned or locked on the source chain. This risk can extend to other types of cross-chain data, depending on your application. 

    Assumption of risk; no warranty; no liability. By selecting a Custom finality level, you acknowledge and accept all risk of chain re-orgs/rollbacks and any resulting loss, imbalance, or data inconsistency. Wormhole contributors, and their affiliates (“Wormhole Parties”) provide this feature “as is,” make no warranties of any kind, and will not be liable for any losses or damages arising from your selection or use of Custom finality. You are solely responsible for appropriate safeguards (e.g., caps, delays, monitoring, circuit breakers).
    
    See the [Custom Consistency Levels](#custom-consistency-levels-advanced) section.


The following table documents each chain's `consistencyLevel` values (i.e., finality reached before signing). The consistency level defines how long the Guardians should wait before signing a VAA. The finalization time depends on the specific chain's consensus mechanism. The consistency level is a `u8`, so any single byte may be used. However, a small subset has particular meanings. If the `consistencyLevel` isn't one of those specific values, the `Otherwise` column describes how it's interpreted.



<table data-full-width="true" markdown><thead><th>Chain</th><th>Instant</th><th>Safe</th><th>Finalized</th><th>Custom</th><th>Otherwise</th><th>Time to Finalize</th><th>Details</th></thead><tbody><tr><td>Ethereum</td><td>200</td><td>201</td><td>202</td><td>203</td><td>finalized</td><td>~ 19min</td><td><a href="https://www.alchemy.com/overviews/ethereum-commitment-levels" target="_blank">Details</a></td></tr><tr><td>Solana</td><td></td><td>0</td><td>1</td><td>N/A</td><td></td><td>~ 14s</td><td><a href="https://docs.anza.xyz/consensus/commitments/" target="_blank">Details</a></td></tr><tr><td>0G (Zero Gravity)</td><td></td><td></td><td>0</td><td>N/A</td><td></td><td>~ 69min</td><td></td></tr><tr><td>Algorand</td><td></td><td></td><td>0</td><td>N/A</td><td></td><td>~ 4s</td><td><a href="https://dev.algorand.co/getting-started/why-algorand/#instant-finality" target="_blank">Details</a></td></tr><tr><td>Aptos</td><td></td><td></td><td>0</td><td>N/A</td><td></td><td>~ 4s</td><td><a href="https://aptos.dev/network/blockchain/validator-nodes#overview" target="_blank">Details</a></td></tr><tr><td>Arbitrum</td><td>200</td><td>201</td><td></td><td>N/A</td><td>finalized</td><td>~ 18min</td><td><a href="https://docs.arbitrum.io/learn-more/faq#how-many-blocks-are-needed-for-a-transaction-to-be-confirmedfinalized-in-arbitrum" target="_blank">Details</a></td></tr><tr><td>Avalanche</td><td>200</td><td></td><td></td><td>N/A</td><td>finalized</td><td>~ 2s</td><td><a href="https://build.avax.network/docs/primary-network/exchange-integration#determining-finality" target="_blank">Details</a></td></tr><tr><td>Base</td><td>200</td><td>201</td><td></td><td>N/A</td><td>finalized</td><td>~ 18min</td><td></td></tr><tr><td>Berachain</td><td>200</td><td></td><td></td><td>N/A</td><td>finalized</td><td>~ 4s</td><td></td></tr><tr><td>BNB Smart Chain</td><td>200</td><td>201</td><td></td><td>N/A</td><td>finalized</td><td>~ 12s</td><td><a href="https://docs.bnbchain.org/bnb-smart-chain/introduction/?h=finality" target="_blank">Details</a></td></tr><tr><td>Celestia</td><td></td><td></td><td>0</td><td>N/A</td><td></td><td>~ 5s</td><td></td></tr><tr><td>Celo</td><td>200</td><td></td><td></td><td>N/A</td><td>finalized</td><td>~ 10s</td><td></td></tr><tr><td>Converge</td><td></td><td></td><td>0</td><td>N/A</td><td></td><td>~ 7min</td><td></td></tr><tr><td>Cosmos Hub</td><td></td><td></td><td>0</td><td>N/A</td><td></td><td>~ 5s</td><td></td></tr><tr><td>CreditCoin</td><td></td><td></td><td>0</td><td>N/A</td><td></td><td>~ 60s</td><td></td></tr><tr><td>Dymension</td><td></td><td></td><td>0</td><td>N/A</td><td></td><td>~ 5s</td><td></td></tr><tr><td>Evmos</td><td></td><td></td><td>0</td><td>N/A</td><td></td><td>~ 2s</td><td></td></tr><tr><td>Fantom</td><td>200</td><td></td><td></td><td>N/A</td><td>finalized</td><td>~ 5s</td><td></td></tr><tr><td>Fogo</td><td></td><td></td><td>0</td><td>N/A</td><td></td><td>~ 14s</td><td></td></tr><tr><td>HyperEVM :material-alert:{ title='⚠️ The HyperEVM integration is experimental, as its node software is not open source. Use Wormhole messaging on HyperEVM with caution.' }</td><td></td><td></td><td>0</td><td>N/A</td><td></td><td>~ 2s</td><td></td></tr><tr><td>Injective</td><td></td><td></td><td>0</td><td>N/A</td><td></td><td>~ 3s</td><td></td></tr><tr><td>Ink</td><td></td><td></td><td>0</td><td>N/A</td><td></td><td>~ 9min</td><td></td></tr><tr><td>Kaia</td><td>200</td><td></td><td></td><td>N/A</td><td>finalized</td><td>~ 1s</td><td></td></tr><tr><td>Kujira</td><td></td><td></td><td>0</td><td>N/A</td><td></td><td>~ 3s</td><td></td></tr><tr><td>Mantle</td><td>200</td><td>201</td><td></td><td>N/A</td><td>finalized</td><td>~ 18min</td><td></td></tr><tr><td>MegaETH</td><td></td><td></td><td>0</td><td>N/A</td><td></td><td>~ 69min</td><td></td></tr><tr><td>Mezo</td><td></td><td></td><td>0</td><td>N/A</td><td></td><td>~ 8s</td><td></td></tr><tr><td>Moca</td><td></td><td></td><td>0</td><td>N/A</td><td></td><td>~ 1s</td><td></td></tr><tr><td>Monad</td><td></td><td></td><td>0</td><td>N/A</td><td></td><td>~ 2s</td><td></td></tr><tr><td>Moonbeam</td><td>200</td><td>201</td><td></td><td>N/A</td><td>finalized</td><td>~ 24s</td><td><a href="https://docs.moonbeam.network/builders/ethereum/json-rpc/moonbeam-custom-api/#finality-rpc-endpoints" target="_blank">Details</a></td></tr><tr><td>NEAR</td><td></td><td></td><td>0</td><td>N/A</td><td></td><td>~ 2s</td><td><a href="https://nomicon.io/ChainSpec/Consensus" target="_blank">Details</a></td></tr><tr><td>Neutron</td><td></td><td></td><td>0</td><td>N/A</td><td></td><td>~ 5s</td><td></td></tr><tr><td>Optimism</td><td>200</td><td>201</td><td></td><td>N/A</td><td>finalized</td><td>~ 18min</td><td></td></tr><tr><td>Osmosis</td><td></td><td></td><td>0</td><td>N/A</td><td></td><td>~ 6s</td><td></td></tr><tr><td>Plasma</td><td></td><td></td><td>0</td><td>N/A</td><td></td><td>~ 3s</td><td></td></tr><tr><td>Plume</td><td></td><td></td><td>0</td><td>N/A</td><td></td><td>~ 18min</td><td></td></tr><tr><td>Polygon</td><td>200</td><td></td><td></td><td>N/A</td><td>finalized</td><td>~ 6s</td><td><a href="https://docs.polygon.technology/pos/architecture/heimdall_v2/checkpoints/" target="_blank">Details</a></td></tr><tr><td>Scroll</td><td>200</td><td></td><td></td><td>N/A</td><td>finalized</td><td>~ 50min</td><td></td></tr><tr><td>Sei</td><td></td><td></td><td>0</td><td>N/A</td><td></td><td>~ 1s</td><td></td></tr><tr><td>SeiEVM</td><td></td><td></td><td>0</td><td>N/A</td><td></td><td>~ 1s</td><td></td></tr><tr><td>Sonic</td><td></td><td></td><td>0</td><td>N/A</td><td></td><td>~ 1s</td><td></td></tr><tr><td>Stacks</td><td></td><td></td><td>0</td><td>N/A</td><td></td><td>~ 61min</td><td></td></tr><tr><td>Stargaze</td><td></td><td></td><td>0</td><td>N/A</td><td></td><td>~ 5s</td><td></td></tr><tr><td>Sui</td><td></td><td></td><td>0</td><td>N/A</td><td></td><td>~ 3s</td><td><a href="https://docs.sui.io/concepts/sui-architecture/consensus" target="_blank">Details</a></td></tr><tr><td>Unichain</td><td>200</td><td>201</td><td></td><td>N/A</td><td>finalized</td><td>~ 18min</td><td></td></tr><tr><td>World Chain</td><td></td><td></td><td>0</td><td>N/A</td><td></td><td>~ 18min</td><td></td></tr><tr><td>X Layer</td><td>200</td><td>201</td><td></td><td>N/A</td><td>finalized</td><td>~ 16min</td><td></td></tr><tr><td>Xrpl</td><td></td><td></td><td>0</td><td>N/A</td><td></td><td>~ 4s</td><td></td></tr><tr><td>XRPL-EVM</td><td></td><td></td><td>0</td><td>N/A</td><td></td><td>~ 10s</td><td></td></tr></tbody></table>

## Custom Consistency Levels (Advanced)

On supported EVM chains (currently Ethereum and Linea), integrators may specify a custom consistency level. See the [white paper](https://github.com/wormhole-foundation/wormhole/blob/main/whitepapers/0001_generic_message_passing.md#custom-handling){target=\_blank} to learn how this works. 

!!!warning
    **Custom finality is an advanced feature and Wormhole Contributors recommend to use this with caution.** Custom consistency should only be used when standard finality options do not meet the application’s requirements. Most integrations **do not** require custom consistency levels. Using custom finality exposes users to re-org risk. Lower finality levels increase the chance that a source-chain transaction may be reverted after assets are released or minted on the destination chain. Custom finality should be used only with a clear understanding of these risks.
    
How to select a Custom Finality Level:

- For L1s: Wormhole Contributors recommend referring to information on forked blocks in blockchain explorers such as [Etherscan](https://etherscan.io/blocks_forked?p=1){target=\_blank}, [Polygonscan](https://polygonscan.com/blocks_forked){target=\_blank}, and others, paying specific attention to the “ReorgDepth” column. Polygon, for instance, has been known to have reorgs with a depth of up to 128 blocks! 
- For L2s: Wormhole Contributors recommend reviewing L2 block explorers as well as details around whether the sequencer is centralized and how the L2 RPC node treats finality. Typically, the risks one is exposed to when not waiting for full finality from an L2 are: (1) a centralized (or compromised) sequencer censoring transactions, (2) re-orgs if sequencing is not centralized, and (3) L1 reorg risk and the L2 sequencer not re-submitting the transaction batch to the L1.


### CCL Contract Addresses

Custom Consistency Level (CCL) enables advanced finality control for EVM chains. CCL is currently supported on select EVM chains. The contract addresses below are the on-chain contracts queried when 203 (Custom) is used.

=== "Mainnet"

    <table data-full-width="true" markdown><thead><tr><th>Chain Name</th><th>Contract Address</th></tr></thead><tbody><tr><td>Ethereum</td><td><code>0x6A4B4A882F5F0a447078b4Fd0b4B571A82371ec2</code></td></tr><tr><td>Linea</td><td><code>0x6A4B4A882F5F0a447078b4Fd0b4B571A82371ec2</code></td></tr></tbody></table>

=== "Testnet"

    <table data-full-width="true" markdown><thead><tr><th>Chain Name</th><th>Contract Address</th></tr></thead><tbody><tr><td>Ethereum</td><td><code>0x6A4B4A882F5F0a447078b4Fd0b4B571A82371ec2</code></td></tr><tr><td>Sepolia</td><td><code>0x6A4B4A882F5F0a447078b4Fd0b4B571A82371ec2</code></td></tr><tr><td>Linea</td><td><code>0x6A4B4A882F5F0a447078b4Fd0b4B571A82371ec2</code></td></tr></tbody></table>

=== "Devnet"

    <table data-full-width="true" markdown><thead><tr><th>Chain Name</th><th>Contract Address</th></tr></thead><tbody><tr><td>Ethereum</td><td><code>0x6A4B4A882F5F0a447078b4Fd0b4B571A82371ec2</code></td></tr></tbody></table>


---

Page Title: Wormhole Formatted Addresses

- Resolved Markdown: https://wormhole.com/docs/ai/pages/products-reference-wormhole-formatted-addresses.md
- Canonical (HTML): https://wormhole.com/docs/products/reference/wormhole-formatted-addresses/
- Summary: Explanation of Wormhole formatted 32-byte hex addresses, their conversion, and usage across different blockchain platforms.
- Word Count: 799; Token Estimate: 1437

# Wormhole Formatted Addresses

Wormhole formatted addresses are 32-byte hex representations of addresses from any supported blockchain. Whether an address originates from EVM, Solana, Cosmos, or another ecosystem, Wormhole standardizes all addresses into this format to ensure cross-chain compatibility.

This uniform format is essential for smooth interoperability in token transfers and messaging across chains. Wormhole uses formatted addresses throughout the [Wormhole SDK](https://github.com/wormhole-foundation/wormhole-sdk-ts){target=\_blank}, especially in cross-chain transactions, such as transfer functions that utilize the `bytes32` representation for recipient addresses.

## Platform-Specific Address Formats

Each blockchain ecosystem Wormhole supports has its method for formatting native addresses. To enable cross-chain compatibility, Wormhole converts these native addresses into the standardized 32-byte hex format.

Here’s an overview of the native address formats and how they are normalized to the Wormhole format:

| Platform        | Native Address Format            | Wormhole Formatted Address |
|-----------------|----------------------------------|----------------------------|
| EVM             |  Hex (e.g., 0x...)               |  32-byte Hex               |
| Solana          |  Base58                          |  32-byte Hex               |
| CosmWasm        |  Bech32                          |  32-byte Hex               |
| Algorand        |  Algorand App ID                 |  32-byte Hex               |
| Sui             |  Hex                             |  32-byte Hex               |
| Aptos           |  Hex                             |  32-byte Hex               |
| Near            |  SHA-256                         |  32-byte Hex               |

These conversions allow Wormhole to interact seamlessly with various chains using a uniform format for all addresses.

### Address Format Handling

The Wormhole SDK provides mappings that associate each platform with its native address format. You can find this mapping in the Wormhole SDK file [`platforms.ts`](https://github.com/wormhole-foundation/wormhole-sdk-ts/blob/007f61b27c650c1cf0fada2436f79940dfa4f211/core/base/src/constants/platforms.ts#L93-L102){target=\_blank}:

```typescript
const platformAddressFormatEntries = [
  ['Evm', 'hex'],
  ['Solana', 'base58'],
  ['Cosmwasm', 'bech32'],
  ['Algorand', 'algorandAppId'],
  ['Sui', 'hex'],
  ['Aptos', 'hex'],
  ['Near', 'sha256'],
];
```

These entries define how the [`UniversalAddress`](https://github.com/wormhole-foundation/wormhole-sdk-ts/blob/007f61b27c650c1cf0fada2436f79940dfa4f211/core/definitions/src/universalAddress.ts#L23){target=\_blank} class handles different address formats based on the platform.

## Universal Address Methods

The `UniversalAddress` class is essential for working with Wormhole formatted addresses. It converts native blockchain addresses into the standardized 32-byte hex format used across Wormhole operations.

Key functions:

 - **`new UniversalAddress()`**: Use the `UniversalAddress` constructor to convert native addresses into the Wormhole format.

    ```typescript
    const universalAddress = new UniversalAddress('0x123...', 'hex');
    ```

 - **`toUniversalAddress()`**: Converts a platform-specific address into the Wormhole formatted 32-byte hex address.

    ```typescript
    const ethAddress: NativeAddress<'Evm'> = toNative('Ethereum', '0x0C9...');
    const universalAddress = ethAddress.toUniversalAddress().toString();
    ```

 - **`toNative()`**: Converts the Wormhole formatted address back to a native address for a specific blockchain platform.

    ```typescript
    const nativeAddress = universalAddress.toNative('Evm');
    ```

 - **`toString()`**: Returns the Wormhole formatted address as a hex string, which can be used in various SDK operations.

    ```typescript
    console.log(universalAddress.toString());
    ```

These methods allow developers to convert between native addresses and the Wormhole format, ensuring cross-chain compatibility.

## Convert Between Native and Wormhole Formatted Addresses

The Wormhole SDK allows developers to easily convert between native addresses and Wormhole formatted addresses when building cross-chain applications.

### Convert a Native Address to a Wormhole Formatted Address

Example conversions for EVM and Solana:

=== "EVM"

    ```typescript
    import { toNative } from '@wormhole-foundation/sdk-core';

    const ethAddress: NativeAddress<'Evm'> = toNative(
      'Ethereum',
      '0x0C99567DC6f8f1864cafb580797b4B56944EEd28'
    );
    const universalAddress = ethAddress.toUniversalAddress().toString();
    console.log('Universal Address (EVM):', universalAddress);
    ```

=== "Solana"

    ```typescript
    import { toNative } from '@wormhole-foundation/sdk-core';

    const solAddress: NativeAddress<'Solana'> = toNative(
      'Solana',
      '6zZHv9EiqQYcdg52ueADRY6NbCXa37VKPngEHaokZq5J'
    );
    const universalAddressSol = solAddress.toUniversalAddress().toString();
    console.log('Universal Address (Solana):', universalAddressSol);
    ```

The result is a standardized address format that is ready for cross-chain operations.

### Convert Back to Native Addresses

Below is how you can convert a Wormhole formatted address back to an EVM or Solana native address:

```typescript
const nativeAddressEvm = universalAddress.toNative('Evm');
console.log('EVM Native Address:', nativeAddressEvm);

const nativeAddressSolana = universalAddress.toNative('Solana');
console.log('Solana Native Address:', nativeAddressSolana);
```

These conversions ensure that your cross-chain applications can seamlessly handle addresses across different ecosystems.

## Use Cases for Wormhole Formatted Addresses

### Cross-chain Token Transfers

Cross-chain token transfers require addresses to be converted into a standard format. For example, when transferring tokens from Ethereum to Solana, the Ethereum address is converted into a Wormhole formatted address to ensure compatibility. After the transfer, the Wormhole formatted address is converted back into the Solana native format.

### Smart Contract Interactions

In smart contract interactions, especially when building dApps that communicate across multiple chains, Wormhole formatted addresses provide a uniform way to reference addresses. This ensures that addresses from different blockchains can interact seamlessly, whether you're sending messages or making cross-chain contract calls.

### DApp Development

For cross-chain dApp development, Wormhole formatted addresses simplify handling user wallet addresses across various blockchains. This allows developers to manage addresses consistently, regardless of whether they work with EVM, Solana, or another supported platform.

### Relayers and Infrastructure

Finally, relayers and infrastructure components, such as Wormhole Guardians, rely on the standardized format to efficiently process and relay cross-chain messages. A uniform address format simplifies operations, ensuring smooth interoperability across multiple blockchains.
