Install NTT CLI

## Install NTT CLI

The NTT CLI is recommended to deploy and manage your cross-chain token configuration.

1. Run the installation commands in your terminal:

    ```bash
    curl -fsSL https://raw.githubusercontent.com/wormhole-foundation/native-token-transfers/main/cli/install.sh | bash
    ```
2. Verify the NTT CLI is installed:

    ```bash
    ntt --version
    ```
    ??? warning "Command not found?"
        If the `ntt` command is not recognized after installation, ensure that [Bun](https://bun.sh/) v1.2.23 is installed and that its binary directory is included in your shell’s PATH.

        Append this line to your shell config (e.g., `~/.zshrc` or `~/.bashrc`):

        ```bash
        echo 'export PATH="$HOME/.bun/bin:$PATH"' >> ~/.zshrc
        ```

        Then, restart your terminal or run `source ~/.zshrc`.


Initialize a New NTT Project

## Initialize a New NTT Project

1. Once the CLI is installed, scaffold a new project by running:

    ```bash
    ntt new my-ntt-project
    cd my-ntt-project
    ```

2. Initialize a new `deployment.json` file specifying the network:

    === "Mainnet"
        ```bash
        ntt init Mainnet
        ```

    === "Testnet"
        ```bash
        ntt init Testnet
        ```

    After initialization, the `deployment.json` file contains your NTT configuration and starts with the selected network.

    === "Mainnet"
        ```json
        {
            "network": "Mainnet",
            "chains": {}
        }
        ```

    === "Testnet"
        ```json
        {
            "network": "Testnet",
            "chains": {}
        }
        ```

In the deployment steps, you will add your supported chains, their token addresses, deployment modes, and any custom settings.


Next Steps

## Next Steps

You have scaffolded your NTT project and initialized the configuration file. Next, follow the appropriate guide below to configure your supported chains and deploy NTT contracts.

<div class="grid cards" markdown>

-   :octicons-tools-16:{ .lg .middle } **Deploy to EVM Chains**

    ---

    Learn how to deploy NTT on EVM-compatible chains.

    [:custom-arrow: Get Started](/docs/products/token-transfers/native-token-transfers/guides/deploy-to-evm/)

-   :octicons-tools-16:{ .lg .middle } **Deploy to SVM Chains**

    ---

    Follow the guide to deploy and configure NTT for SVM chains.

    [:custom-arrow: Get Started](/docs/products/token-transfers/native-token-transfers/guides/deploy-to-solana/){target=\_blank}

-   :octicons-tools-16:{ .lg .middle } **Deploy to Sui**

    ---

    Learn how to deploy NTT to Sui.

    [:custom-arrow: Get Started](/docs/products/token-transfers/native-token-transfers/guides/deploy-to-sui/){target=\_blank}

-   :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>


Prerequisites

## Prerequisites

Before deploying NTT on EVM chains, ensure you have the following prerequisites:

- [Node.js and npm installed](https://docs.npmjs.com/downloading-and-installing-node-js-and-npm){target=\_blank}.
- [Bun installed](https://bun.sh/){target=\_blank}.
- A wallet private key with tokens on supported chains.
- ERC-20 tokens already deployed on the source and destination chains.


Overview of the Deployment Process

## Overview of the Deployment Process

Deploying NTT on EVM chains follows a structured process:

1. **Choose your token setup**: Use an existing ERC-20 token or deploy a new one.

    ???- interface "Deploy an ERC-20 Token on EVM"
        Use the [example NTT token repository](https://github.com/wormhole-foundation/example-ntt-token-evm){target=\_blank} to deploy a basic ERC-20 token contract on testnet.

        1. **Install Foundry**: Install the [Forge CLI](https://getfoundry.sh/introduction/installation/){target=\_blank}.

        2. **Clone the repository**: Fetch the example contract repository.

            ```bash
            git clone https://github.com/wormhole-foundation/example-ntt-token-evm.git
            cd example-ntt-token
            ```
        3. **Deploy the token contract**: Deploy to testnet with your preferred name, symbol, minter, and owner addresses.

            ```bash
            forge create --broadcast \
                --rpc-url INSERT_RPC_URL \
                --private-key INSERT_YOUR_PRIVATE_KEY \
                src/PeerToken.sol:PeerToken \
                --constructor-args "INSERT_TOKEN_NAME" "INSERT_TOKEN_SYMBOL" INSERT_MINTER_ADDRESS INSERT_OWNER_ADDRESS
            ```

        4. **Mint tokens**: Send tokens to your address.

            ```bash
            cast send INSERT_TOKEN_ADDRESS \
                "mint(address,uint256)" \
                INSERT_RECIPIENT_ADDRESS \
                INSERT_AMOUNT_IN_WEI \
                --private-key INSERT_YOUR_PRIVATE_KEY \
                --rpc-url INSERT_RPC_URL
            ```

        !!! note
            This token uses 18 decimals by default. All minting values must be specified in `wei` (1 token = 10^18).
2. **Choose your deployment model**: Choose a deployment model. The NTT framework supports two [deployment models](/docs/products/token-transfers/native-token-transfers/overview/#deployment-models){target=\_blank}: burn-and-mint and hub-and-spoke.

    ??? interface "Burn-and-Mint"

        Tokens must implement the following non-standard ERC-20 functions:

        - `burn(uint256 amount)`
        - `mint(address account, uint256 amount)`

        You’ll also need to set mint authority to the relevant `NttManager` contract.

        These functions aren't part of the standard ERC-20 interface. Refer to the [`INttToken` interface](https://github.com/wormhole-foundation/native-token-transfers/blob/main/evm/src/interfaces/INttToken.sol){target=\_blank} for examples of the mentioned functions, as well as optional errors and events.

        ??? interface "`INttToken` Interface"
            ```solidity
            // SPDX-License-Identifier: Apache 2
            pragma solidity >=0.8.8 <0.9.0;

            interface INttToken {
                /// @notice Error when the caller is not the minter.
                /// @dev Selector 0x5fb5729e.
                /// @param caller The caller of the function.
                error CallerNotMinter(address caller);

                /// @notice Error when the minter is the zero address.
                /// @dev Selector 0x04a208c7.
                error InvalidMinterZeroAddress();

                /// @notice Error when insufficient balance to burn the amount.
                /// @dev Selector 0xcf479181.
                /// @param balance The balance of the account.
                /// @param amount The amount to burn.
                error InsufficientBalance(uint256 balance, uint256 amount);

                /// @notice The minter has been changed.
                /// @dev Topic0
                ///      0x0b5e7be615a67a819aff3f47c967d1535cead1b98db60fafdcbf22dcaa8fa5a9.
                /// @param newMinter The new minter.
                event NewMinter(address previousMinter, address newMinter);

                // NOTE: the `mint` method is not present in the standard ERC20 interface.
                function mint(address account, uint256 amount) external;

                // NOTE: the `setMinter` method is not present in the standard ERC20 interface.
                function setMinter(address newMinter) external;

                // NOTE: NttTokens in `burn` mode require the `burn` method to be present.
                //       This method is not present in the standard ERC20 interface, but is
                //       found in the `ERC20Burnable` interface.
                function burn(uint256 amount) external;
            }
            ```

    ??? interface "Hub-and-Spoke"

        Tokens only need to be ERC-20 compliant. The hub chain serves as the source of truth for supply consistency, while only spoke chains need to support minting and burning. For example, if Ethereum is the hub and Polygon is a spoke:

        - Tokens are locked on Ethereum.
        - Tokens are minted or burned on Polygon.

        This setup maintains a consistent total supply across all chains.

        To bridge native gas tokens (e.g., ETH) in hub-and-spoke mode, see the [WethUnwrap variant](#wethunwrap-variant) below.

    Example deployment scripts for both models are available in the [`example-ntt-token` GitHub repository](https://github.com/wormhole-foundation/example-ntt-token-evm){target=\_blank}.

3. **Configure your chains**: Use the NTT CLI to add EVM chains and configure deployment parameters.
4. **Set Mint Authority**: Set the NTT Manager as a minter for your tokens on the relevant chains.
    - For burn-and-mint mode, set the NTT Manager as a minter on all chains.
    - For hub-and-spoke, set the NTT Manager as a minter only on spoke chains.


Set Up NTT

## Set Up NTT

Before deploying NTT contracts on EVM chains, you need to scaffold a project and initialize your deployment configuration.

!!! note
    If you already have an NTT deployment to another chain (like Solana), you can skip the `ntt new` and `ntt init` commands. Simply navigate to your existing NTT project directory and proceed directly to the [Deploy and Configure NTT](#deploy-and-configure-ntt) section.

The [NTT CLI](/docs/products/native-token-transfers/reference/cli-commands/){target=\_blank} manages deployments, configures settings, and interacts with the NTT system. Follow these steps to set up NTT using the CLI tool:

???- interface "Install the NTT CLI and Scaffold a New Project"

    1. Install the NTT CLI:

        ```bash
        curl -fsSL https://raw.githubusercontent.com/wormhole-foundation/native-token-transfers/main/cli/install.sh | bash
        ```

        Verify installation:

        ```bash
        ntt --version
        ```

    2. Initialize a new NTT project:

        ```bash
        ntt new my-ntt-project
        cd my-ntt-project
        ```

    3. Create the deployment config using the following command. This will generate a `deployment.json` file where your settings are stored:

        === "Mainnet"

            ```bash
            ntt init Mainnet
            ```
        === "Testnet"

            ```bash
            ntt init Testnet
            ```


Deploy and Configure NTT

## Deploy and Configure NTT

Once you've set up NTT, proceed with adding your EVM chains and deploying contracts.

1. **Environment Setup**: Ensure you have set up your environment correctly, open your terminal, and run the `export` commands:

    ```bash
    export ETH_PRIVATE_KEY=INSERT_PRIVATE_KEY
    export SEPOLIA_SCAN_API_KEY=INSERT_ETHERSCAN_SEPOLIA_API_KEY
    export ARBITRUMSEPOLIA_SCAN_API_KEY=INSERT_ARBISCAN_SEPOLIA_API_KEY
    ```

2. **Deploy NTT to EVM**: Add each chain you'll be deploying to using the `ntt add-chain` command. The following example demonstrates configuring NTT in burn-and-mint mode on Ethereum Sepolia and Arbitrum Sepolia:

    ```bash

    # Add each chain
    # The contracts will be automatically verified using the scanner API keys above
    ntt add-chain Sepolia --latest --mode burning --token INSERT_YOUR_TOKEN_ADDRESS
    ntt add-chain ArbitrumSepolia --latest --mode burning --token INSERT_YOUR_TOKEN_ADDRESS
    ```

    The `ntt add-chain` command takes the following parameters:

    - Name of each chain.
    - Version of NTT to deploy (use `--latest` for the latest contract versions).
    - Mode - either `burning` or `locking`.
    - Your token contract address.

    For more advanced deployment configuration options, see the [Advanced](#advanced) section below.

    While not recommended, you can pass the `-skip-verify` flag to the `ntt add-chain` command if you want to skip contract verification.

3. **Verify deployment status**: After deployment, check if your `deployment.json` file matches the on-chain configuration using the following command:

    ```bash
    ntt status
    ```

    If needed, sync your local configuration with the on-chain configuration:

    ```bash
    ntt pull
    ```

4. **Configure rate limits**: Set up inbound and outbound rate limits. By default, limits are set to 0 and must be updated before deployment. For EVM chains, values must be set using 18 decimals.

    Open your `deployment.json` file and adjust the values based on your use case:

    ```json
    "outbound": "1000.000000000000000000",
    "inbound": {
        "Arbitrum": "1000.000000000000000000"
    }
    ```

    - **`outbound`** - a single value that sets the maximum tokens allowed to leave the chain (applies to all destination chains)
    - **`inbound`** - configures per-chain receiving limits for tokens arriving from specific source chains (e.g., the example above limits tokens received from Arbitrum)

    This configuration ensures your rate limits align with the token's precision on each chain, preventing mismatches that could block or miscalculate transfers. Before setting these values, confirm your token's decimals on each chain by checking the token contract on the relevant block explorer.

    For more details on rate limiting configuration and behavior, see the [Rate Limiting](/docs/products/token-transfers/native-token-transfers/configuration/rate-limiting/){target=\_blank} page.

5. **Push the final deployment**: Once rate limits are set, sync the on-chain configuration with local changes made to your `deployment.json` file.

    ```bash
    ntt push
    ```

After you deploy the NTT contracts, ensure that the deployment is properly configured and your local representation is consistent with the actual on-chain state by running `ntt status` and following the instructions shown on the screen.


Set Mint Authority

## Set Mint Authority

The final step in the deployment process is to set the NTT Manager as a minter of your token on all chains you have deployed to in `burning` mode. When performing a hub-and-spoke deployment, it is only necessary to set the NTT Manager as a minter of the token on each spoke chain.

!!! note
    The required NTT Manager address can be found in the `deployment.json` file.

- If you followed the [`INttToken`](https://github.com/wormhole-foundation/native-token-transfers/blob/main/evm/src/interfaces/INttToken.sol){target=\_blank} interface, you can execute the `setMinter(address newMinter)` function.
    ```json
    cast send $TOKEN_ADDRESS "setMinter(address)" $NTT_MANAGER_ADDRESS --private-key $ETH_PRIVATE_KEY --rpc-url $YOUR_RPC_URL
    ```

- If you have a custom process to manage token minters, you should now follow that process to add the corresponding NTT Manager as a minter.


NTT Manager Deployment Parameters

## NTT Manager Deployment Parameters

This table compares the configuration parameters available when deploying the NTT Manager using the CLI versus those available during a manual deployment with a Forge script. It highlights which options are configurable via each method, whether values are auto-detected or hardcoded, and includes additional comments to help guide deployment decisions.

|
Parameter
 | Forge Script           | CLI                                 | Both   | Comments                                     |
|-------------------------|------------------------|-------------------------------------|--------|----------------------------------------------|
| `token`                 | Input                  | `--token <address>`                 | Yes    |                                              |
| `mode`                  | Input                  | `--mode <locking/burning>`          | Yes    | Key decision: hub-and-spoke or mint-and-burn |
| `wormhole`              | Input                  | Auto-detected via SDK/`ChainContext`  | Similar|                                              |
| `wormholeRelayer`       | Input                  | Auto-detected via on-chain query/SDK| Similar|                                              |
| `specialRelayer`        | Input                  | Not exposed                         | No     | Take into consideration if using custom relaying. Not recommended |
| `decimals`              | Input, overridable     | Auto-detected via token contract, not overridable  | Similar |                              |
| `wormholeChainId`       | Queried from Wormhole contract | `--chain` (network param, mapped internally) | Yes     |                              |
| `rateLimitDuration`     | Hardcoded (`86400`)    | Hardcoded (`86400`)                 | Yes    | Rate limit duration. A day is normal but worth deciding  |
| `shouldSkipRatelimiter` | Hardcoded (`false`)      | Hardcoded (`false`)                   | Yes    | If rate limit should be disabled (when the manager supports it)         |
| `consistencyLevel`      | Hardcoded (`202`)      | Hardcoded (`202`)                   | Yes    | `202` (finalized) is the standard — lower is not recommended  |
| `gasLimit`              | Hardcoded (`500000`)   | Hardcoded (`500000`)                | Yes    |             |
| `outboundLimit`         | Computed               | Auto-detected/Hardcoded             | Similar| Relative to rate limit             |
| `managerVariant`        | Input (`MANAGER_VARIANT`)  | `--manager-variant <string>`        | Yes    | Choices: `standard` (default), `noRateLimiting`, `wethUnwrap`. EVM only |


Manager Variants

## Manager Variants

The NTT CLI supports three manager variants for EVM deployments, configured via the `--manager-variant` flag on `ntt add-chain`. The default variant is `standard`.

| Variant | Description |
|---------|-------------|
| `standard` | Default NTT Manager with rate limiting enabled. Suitable for most deployments. |
| `noRateLimiting` | Removes the rate limiter to free contract code space. Use when rate limiting is not required. |
| `wethUnwrap` | Automatically unwraps WETH to native ETH when tokens are unlocked on the hub chain. Use for bridging native gas tokens. |


WethUnwrap Variant

### WethUnwrap Variant

The `wethUnwrap` variant enables bridging of native gas tokens (e.g., ETH). On the hub chain, WETH is used as the locked token. When tokens arrive back at the hub via an inbound transfer, the manager automatically unwraps WETH and sends native ETH to the recipient.

**Requirements:**

- **EVM only** — no Solana or Sui equivalent
- **Locking mode only** — the unwrap occurs during token unlock, which only happens in locking mode
- **Token must be the WETH contract** — the manager casts the token address to the [IWETH interface](https://github.com/wormhole-foundation/native-token-transfers/blob/main/evm/src/interfaces/IWETH.sol){target=\_blank}, so it must implement `deposit()` and `withdraw(uint256)`

**Add the hub chain with the `wethUnwrap` variant:**

```bash
ntt add-chain Ethereum --latest --mode locking \
  --token <WETH_ADDRESS> \
  --manager-variant wethUnwrap
```


Advanced

## Advanced

By default, cross-chain token transfers with NTT wait for full finality on the source chain. On some EVM chains, this can be a few seconds. On other EVM chains, such as Ethereum and L2s, this can be 15-20 minutes. This is the safest option for cross-chain token transfers. For faster cross-chain transfers, we recommend pairing NTT with a fast-transfers product such as [Mayan Swift](/docs/products/settlement/overview/#mayan-swift){target=\_blank}.

If you would like to transfer tokens faster than finality natively, you can use the `--unsafe-custom-finality` flag to configure this. **Custom finality is an advanced feature, and Wormhole Contributors recommend using this with caution.** Choosing a level of finality other than `finalized` 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.

To select a custom finality level on an L1 chain, Wormhole Contributors recommend consulting 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 particular attention to the “ReorgDepth” column. Polygon, for instance, has been known to have reorgs with a depth of up to 128 blocks!

To select a custom finality level on an L2 chain, Wormhole Contributors recommend reviewing L2 block explorers and details on whether the sequencer is centralized and how the L2 RPC node handles 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
3. L1 reorg risk and the L2 sequencer not re-submitting the transaction batch to the L1.


Next Steps

## Next Steps

<div class="grid cards" markdown>

-   :octicons-tools-16:{ .lg .middle } **Test Your Deployment**

    ---

    Follow the NTT Post Deployment Guide for integration examples and testing instructions.

    [:custom-arrow: Test Your NTT deployment](/docs/products/token-transfers/native-token-transfers/guides/post-deployment/)

-   :octicons-tools-16:{ .lg .middle } **Deploy NTT to SVM Chains**

    ---

    Follow the guide to deploy and configure Wormhole's Native Token Transfers (NTT) for SVM chains.

    [:custom-arrow: Deploy NTT to SVM Chains](/docs/products/token-transfers/native-token-transfers/guides/deploy-to-solana/)

-   :octicons-tools-16:{ .lg .middle } **Launch a Multichain Native Memecoin**

    ---

    Learn how to use the NTT framework to launch a multi-chain native Memecoin 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-8140-9ec4-e800f40a41bc){target=\_blank}

-   :octicons-question-16:{ .lg .middle } **View FAQs**

    ---

    Find answers to common questions about NTT.

    [:custom-arrow: View FAQs](/docs/products/token-transfers/native-token-transfers/faqs/)

</div>


Native Token Transfers Hyperliquid Deployment

Prerequisites

## Prerequisites

Before following this guide, ensure you have:

- An NTT deployment on HyperEVM. If you haven't deployed yet, follow the [Deploy NTT to EVM Chains](/docs/products/token-transfers/native-token-transfers/guides/deploy-to-evm/){target=\_blank} guide using HyperEVM as your target chain.
- Your `ETH_PRIVATE_KEY` environment variable set to the deployer wallet private key.
- The [NTT CLI](/docs/products/token-transfers/native-token-transfers/reference/cli-commands/){target=\_blank} installed and up to date.


Overview of the Deployment Process

## Overview of the Deployment Process

After deploying NTT on HyperEVM, integrating with HyperCore follows these steps:

1. **Deploy a spot token on HyperCore** - use the Hyperliquid Deploy Spot UI to register your token and obtain a token index.
2. **Link HyperCore to HyperEVM** - use `ntt hype link` to connect your HyperCore spot token to its HyperEVM ERC-20 contract.
3. **Bridge tokens** - use `ntt hype bridge-in` and `ntt hype bridge-out` to move tokens between HyperEVM and HyperCore.


Deploy a Spot Token on HyperCore

## Deploy a Spot Token on HyperCore

Before linking your ERC-20 token on HyperEVM to HyperCore, you must first deploy a [HIP-1](https://hyperliquid.gitbook.io/hyperliquid-docs/hyperliquid-improvement-proposals-hips/hip-1-native-token-standard){target=\_blank} spot token through Hyperliquid's Deploy Spot interface. This is a multi-step process performed directly on the Hyperliquid platform.

Navigate to the Deploy Spot page:

- **Testnet** - [app.hyperliquid-testnet.xyz/deploySpot](https://app.hyperliquid-testnet.xyz/deploySpot){target=\_blank}
- **Mainnet** - [app.hyperliquid.xyz/deploySpot](https://app.hyperliquid.xyz/deploySpot){target=\_blank}

!!! warning
    Each step is permanent. You cannot change inputs after proceeding to the next step. Hyperliquid recommends testing the exact configuration on testnet before using mainnet.


Step 1: Deploy Token

### Step 1: Deploy Token

Register the token name and configure its decimal precision:

- **`szDecimals`** - tradable precision on the order book. For example, `2` means the minimum order increment is `0.01` tokens.
- **`weiDecimals`** - smallest indivisible unit. For example, `8` means the smallest unit is `0.00000001` tokens.

These values must satisfy the constraint: **`szDecimals + 5 <= weiDecimals`** as defined in the [HIP-1 specification](https://hyperliquid.gitbook.io/hyperliquid-docs/hyperliquid-improvement-proposals-hips/hip-1-native-token-standard){target=\_blank}.

!!! note
    The HIP-1 token on HyperCore uses `weiDecimals`, which may differ from your ERC-20 token's decimals on HyperEVM. The asset bridge handles the conversion between the two.


Step 2: Set Deployer Trading Fee Share

### Step 2: Set Deployer Trading Fee Share

Configure the percentage of trading fees on the spot pair that go to your deployer address. The remainder is burned. This value can only be **decreased** after deployment, never increased.

After completing this step, the **Progress So Far** panel on the right side of the screen displays your **Token Index**, the unique integer identifier for your spot token on HyperCore. Save this value as you'll need it for the `ntt hype link` command after completing the Deploy Spot process.

![The Progress So Far panel in the Deploy Spot UI after Step 2, showing Token Index and fee share](/docs/images/products/native-token-transfers/guides/hyperliquid/deploy-spot-progress-step2.jpeg)


Step 3: Set Genesis Balances

### Step 3: Set Genesis Balances

This step allocates the initial HIP-1 token supply. For an NTT bridge token, you must mint the genesis supply to the **asset bridge address** so the bridge has reserves to back bridged tokens.

!!! warning
    Hyperliquidity (Step 5) reserves a portion of the genesis supply for its automated market making. Account for this when choosing your genesis amount.

The asset bridge address is deterministic based on your token index. The format is a fixed prefix followed by the token index as a 4-character hex value:

```text
0x2000000000000000000000000000000000000{tokenIndex as 4-char hex}
```

For example, token index `1591` = hex `0637`:

```text
0x2000000000000000000000000000000000000637
```

In the Deploy Spot UI:

1. Enter the **asset bridge address** in the **User** field.
2. Enter the genesis amount in the **Amount** field. This is a whole number in the smallest unit (wei). For example, with `weiDecimals=8`, an amount of `10000000000000000` equals 100 million tokens.
3. Click **Register User Genesis** to register the entry.
4. Click **Complete User Genesis** to finalize (irreversible).

!!! note
    Why mint to the asset bridge? The bridge credits HIP-1 tokens on HyperCore when ERC-20 deposits arrive on HyperEVM. It can only release tokens it already holds. Minting the genesis supply to the bridge ensures it has reserves to back any deposited ERC-20 tokens.


Step 4: Deploy Spot Trading Pair

### Step 4: Deploy Spot Trading Pair

This step creates the trading pair between your token and USDC on HyperCore via a `RegisterSpot` action. It requires specifying the base token index (your token) and the quote token index (USDC). The initial pricing is determined through a [Dutch auction](https://hyperliquid.gitbook.io/hyperliquid-docs/for-developers/api/deploying-hip-1-and-hip-2-assets){target=\_blank} mechanism.


Step 5: Deploy Hyperliquidity

### Step 5: Deploy Hyperliquidity

[Hyperliquidity](https://hyperliquid.gitbook.io/hyperliquid-docs/hyperliquid-improvement-proposals-hips/hip-2-hyperliquidity){target=\_blank} commits permanent on-chain liquidity to the order book. It is not required for the asset bridge to function, but the UI requires you to configure it before proceeding to Step 6.


Step 6: Review and Trigger Genesis

### Step 6: Review and Trigger Genesis

Review all inputs and trigger genesis. This step creates the HIP-1 token on HyperCore and is **irreversible**. Without triggering genesis, the token does not exist on HyperCore.

The **Progress So Far** panel on the right side of the screen summarizes your deployment, including the **Token Index** you'll need for the next step.

![The Progress So Far panel in the Deploy Spot UI showing the Token Index](/docs/images/products/native-token-transfers/guides/hyperliquid/deploy-spot-token-index.jpeg)


Link HyperCore to HyperEVM

## Link HyperCore to HyperEVM

Once your spot token is deployed on HyperCore, use the `ntt hype link` command to connect it to your HyperEVM ERC-20 contract. This two-step process registers the EVM contract with HyperCore and finalizes the link.

```bash
ntt hype link --token-index INSERT_TOKEN_INDEX
```

Replace `INSERT_TOKEN_INDEX` with the token index from the Deploy Spot process (e.g., `1591`).

The command performs two actions automatically:

1. **Request** - registers the EVM contract address with HyperCore.
2. **Finalize** - completes the link by confirming the contract deployment nonce.

After the command completes, it saves the `tokenIndex` to your `deployment.json` under a `hypercore` key:

```json
{
  "network": "Testnet",
  "chains": {
    "HyperEVM": {
      "token": "0x..."
    }
  },
  "hypercore": {
    "tokenIndex": 1591
  }
}
```

??? interface "Additional Options"

    | Option | Description | Default |
    |---|---|---|
    | `--only-finalize` | Skip the request step and only run finalize. Useful if the request was already submitted separately. | `false` |
    | `--evm-extra-wei-decimals` | Set `evmExtraWeiDecimals` (ERC-20 decimals minus `weiDecimals`). | `10` |
    | `--deploy-nonce` | Explicitly set the ERC-20 CREATE deploy nonce. Auto-derived from the deployer address if omitted. | Auto |
    | `--testnet` | Override the network setting from `deployment.json` to use testnet. | From `deployment.json` |


## Bridge Tokens Between HyperEVM and HyperCore

After linking, you can move tokens between HyperEVM and HyperCore using the asset bridge. Each HyperCore spot token has a deterministic asset bridge address derived from its token index.


Bridge Into HyperCore

### Bridge Into HyperCore

Transfer tokens from HyperEVM into HyperCore:

```bash
ntt hype bridge-in INSERT_AMOUNT_DECIMAL
```

Replace `INSERT_AMOUNT_DECIMAL` with the human-readable token amount (e.g., `100`, `0.5`). This sends an ERC-20 `transfer` to the asset bridge address on HyperEVM, which credits the equivalent HIP-1 tokens to your HyperCore account.


Bridge Out to HyperEVM

### Bridge Out to HyperEVM

Transfer tokens from HyperCore back to HyperEVM:

```bash
ntt hype bridge-out INSERT_AMOUNT_DECIMAL
```

Replace `INSERT_AMOUNT_DECIMAL` with the token amount to withdraw. This performs a `spotSend` on HyperCore to the asset bridge, which releases the tokens as ERC-20 on HyperEVM to your wallet address.


Check Status

## Check Status

At any point after linking, you can check your HyperCore token configuration:

```bash
ntt hype status
```

This displays:

- **Token index** - the HyperCore spot token identifier.
- **Asset bridge address** - the deterministic bridge address for your token.
- **Token string** - the HyperCore token identifier (e.g., `WSV:0x7d816f...`).
- **Network** - testnet or mainnet.
- **EVM token address** - the linked ERC-20 contract on HyperEVM.


Prerequisites

## Prerequisites

Before deploying NTT on SVM chains, ensure you have the following:

- [Rust](https://rust-lang.org/tools/install/){target=\_blank} installed.
- The correct versions of the Solana CLI and Anchor installed, depending on your NTT version:

    === "v3"
        | Dependency | Version |
        |------------|---------|
        | [Solana](https://docs.anza.xyz/cli/install/){target=\_blank} | `v1.18.26` |
        | [Anchor](https://www.anchor-lang.com/docs/installation){target=\_blank} | `v0.29.0` |

    === "v2/v1"
        | Dependency | Version |
        |------------|---------|
        | [Solana](https://docs.anza.xyz/cli/install/){target=\_blank} | `v1.18.10` |
        | [Anchor](https://www.anchor-lang.com/docs/installation){target=\_blank} | `v0.29.0` |

Use the Solana and Anchor versions listed above to avoid compatibility issues while following this guide.


Overview of the Deployment Process

## Overview of the Deployment Process

Deploying NTT with the CLI on SVM chains follows a structured process:

1. Choose your token setup:

     - **Use an existing SPL token**: If your token is already deployed on a [supported SVM chain](/docs/products/reference/supported-networks/#ntt){target=\_blank}, you can skip token creation and move directly to the [Set Up NTT](#set-up-ntt) section.
     - **Create a new SPL token**: If you don't already have an SPL token deployed, you'll need to deploy and configure it on a supported SVM chain before integrating with Wormhole's NTT.

        ???- interface "Create and Mint an SPL Token"
            This section walks you through generating a Solana wallet, deploying an SPL token, creating a token account, and minting tokens.

            1. **Generate a key pair**: Run the following command to create a new wallet compatible with supported SVM chains.

                ```bash
                solana-keygen grind --starts-with w:1 --ignore-case
                ```

            2. **Set CLI keypair configuration**: Configure the Solana CLI to use the generated key pair.

                ```bash
                solana config set --keypair INSERT_PATH_TO_KEYPAIR_JSON
                ```

            3. **Select an RPC URL**: Configure the CLI to use the appropriate network using one of the following commands.

                === "Mainnet"
                    ```bash
                    solana config set -um
                    ```

                === "Testnet (Solana's Devnet)"
                    ```bash
                    solana config set -ud
                    ```

                === "Fogo Testnet"
                    ```bash
                    solana config set --url INSERT_FOGO_TESTNET_RPC_URL
                    ```

                !!! note
                    Solana's official testnet cluster is not supported for token creation or deployment with NTT. You must use the Solana devnet instead.

            4. **Fund your wallet**: Ensure your wallet has enough native tokens to cover transaction fees.

                - On Solana Devnet, you can request an airdrop:

                    ```bash
                    solana airdrop 2
                    solana balance
                    ```

            5. **Install SPL Token CLI**: Install or update the required [CLI tool](https://www.solana-program.com/docs/token#setup){target=\_blank}.

                ```bash
                cargo install spl-token-cli
                ```

            6. **Create a new SPL token**: Initialize the token on your connected SVM chain.

                ```bash
                spl-token create-token
                ```

            7. **Create a token account**: Generate an account to hold the token.

                ```bash
                spl-token create-account INSERT_TOKEN_ADDRESS
                ```

            8. **Mint tokens**: Send 1000 tokens to the created account.

                ```bash
                spl-token mint INSERT_TOKEN_ADDRESS 1000
                ```

            !!! note
                NTT versions `>=v2.0.0+solana` support SPL tokens with [transfer hooks](https://www.solana-program.com/docs/transfer-hook-interface){target=\_blank}.
2. **Choose your deployment model**:

    - **Hub-and-spoke**: Tokens are locked on a hub chain and minted on destination spoke chains. Since the token supply remains controlled by the hub chain, no changes to the minting authority are required.
    - **Burn-and-mint**: Tokens are burned on the source chain and minted on the destination chain. This requires transferring the SPL token's minting authority to the Program Derived Address (PDA) controlled by the NTT program.

3. **Deploy and configure NTT**: Use the NTT CLI to initialize and deploy the NTT program, specifying your SPL token and deployment mode.

![SVM NTT deployment diagram](/docs/images/products/native-token-transfers/guides/solana/ntt-solana-guide-1.webp)

Following this process, your token will fully integrate with NTT, enabling seamless transfers between SVM chains and other chains.


Set Up NTT

## Set Up NTT

To integrate your token with NTT on a SVM chain, you must initialize the deployment and configure its parameters. This process sets up the required contracts and may generate key pairs if they don't exist. These key pairs are used to sign transactions and authorize actions within the NTT deployment.

!!! note
    If you already have an NTT deployment to another chain (like Ethereum), you can skip the `ntt new` and `ntt init` commands. Simply navigate to your existing NTT project directory and proceed directly to the [Generate an NTT Program Key Pair](#generate-an-ntt-program-key-pair) section.

The [NTT CLI](/docs/products/native-token-transfers/reference/cli-commands/){target=\_blank} manages deployments, configures settings, and interacts with the NTT system. Follow these steps to set up NTT using the CLI tool:

???- interface "Install the NTT CLI and Scaffold a New Project"

    1. Install the NTT CLI:

        ```bash
        curl -fsSL https://raw.githubusercontent.com/wormhole-foundation/native-token-transfers/main/cli/install.sh | bash
        ```

        Verify installation:

        ```bash
        ntt --version
        ```

    2. Initialize a new NTT project:

        ```bash
        ntt new my-ntt-project
        cd my-ntt-project
        ```

    3. Create the deployment config using the following command. This will generate a `deployment.json` file where your settings are stored:

        === "Mainnet"

            ```bash
            ntt init Mainnet
            ```
        === "Testnet"

            ```bash
            ntt init Testnet
            ```

!!! note
    When deploying NTT to Solana in `Testnet` mode, you must use [**Devnet tokens**](https://faucet.solana.com/){target=\_blank}. Solana's official testnet cluster is not supported for token creation or deployment in NTT.


Generate an NTT Program Key Pair

### Generate an NTT Program Key Pair

Create a unique key pair for the NTT program:

```bash
solana-keygen grind --starts-with ntt:1 --ignore-case
```


Set Mint Authority

### Set Mint Authority

If you use burn-and-mint mode, follow these steps to enable the NTT program to mint tokens on a SVM chain. This involves deriving the PDA as the token authority and updating the SPL token's minting permissions.

For hub-and-spoke and a SVM chain as the hubchain skip this section and proceed to [Deploy and Configure NTT](#deploy-and-configure-ntt), otherwise follow the burn-and-mint instructions below for the SVM chain as a spoke.

Before updating the mint authority, you must create metadata for your SPL token. You can visit this repository to see an example of [how to create metadata for your SPL token](https://github.com/wormhole-foundation/demo-metaplex-metadata/blob/main/src/token-metadata.ts){target=\_blank}.

Options to set the mint authority for your SPL token:

**For undeployed programs:**

- **Set to token authority PDA:**
```bash
ntt set-mint-authority --chain INSERT_SVM_CHAIN --token INSERT_TOKEN_ADDRESS --manager INSERT_NTT_PROGRAM_ADDRESS --payer INSERT_KEYPAIR_JSON
```

- **Set to SPL Multisig:**
    If you don’t already have one, first [create an SPL Multisig](#create-an-spl-multisig-optional). Then set it:
    ```bash
    ntt set-mint-authority --chain INSERT_SVM_CHAIN --token INSERT_TOKEN_ADDRESS --manager INSERT_NTT_PROGRAM_ADDRESS --multisig INSERT_MULTISIG_ADDRESS --payer INSERT_KEYPAIR_JSON
    ```

**For deployed programs:**

- **Set to token authority PDA:**

```bash
ntt set-mint-authority --chain INSERT_SVM_CHAIN --payer INSERT_KEYPAIR_JSON
```

- **Set to SPL Multisig**: If you don’t already have one, first [create an SPL Multisig](#create-an-spl-multisig-optional).
```bash
ntt set-mint-authority --chain INSERT_SVM_CHAIN --multisig INSERT_MULTISIG_ADDRESS --payer INSERT_KEYPAIR_JSON
```

#### Create an SPL Multisig (optional)

If you want the mint authority controlled by a multisig, create it once and reuse it across flows:

```bash
ntt solana create-spl-multisig INSERT_MINTER_PUBKEY_1 INSERT_MINTER_PUBKEY_2 ... \
  --token INSERT_TOKEN_ADDRESS \
  --manager INSERT_NTT_PROGRAM_ADDRESS \
  --payer INSERT_KEYPAIR_JSON
```

!!! note
    Check out [this utility script](https://github.com/wormhole-foundation/demo-ntt-token-mint-authority-transfer/tree/main){target=\_blank} for transferring token mint authority out of NTT.


Deploy and Configure NTT

## Deploy and Configure NTT

!!! warning
    If deploying to Solana mainnet, you must use a custom RPC. See how to [set it up in your project](/docs/products/token-transfers/native-token-transfers/faqs/#how-can-i-specify-a-custom-rpc-for-ntt){target=\_blank} using an `overrides.json` file. For optimal performance, consider using a staked RPC connection from either Triton or Helius.

After setting up your deployment, finalize the configuration and deploy the NTT program on the SVM chain by following these steps:

1. **Deploy NTT to the SVM chain**: Run the appropriate command based on your deployment mode.

    === "Burn-and-Mint"

        ```bash
        ntt add-chain INSERT_SVM_CHAIN --latest --mode burning --token INSERT_TOKEN_ADDRESS --payer INSERT_YOUR_KEYPAIR_JSON --program-key INSERT_YOUR_NTT_PROGRAM_KEYPAIR_JSON
        ```

    === "Hub-and-Spoke"

        ```bash
        ntt add-chain INSERT_SVM_CHAIN --latest --mode locking --token INSERT_TOKEN_ADDRESS --payer INSERT_YOUR_KEYPAIR_JSON --program-key INSERT_YOUR_NTT_PROGRAM_KEYPAIR_JSON
        ```

    You can optionally add `--solana-priority-fee` to the script to increase the priority fee in microlamports. The default is `50000`.

2. **Verify deployment status**: After deployment, check if your `deployment.json` file matches the on-chain configuration using the following command.

    ```bash
    ntt status
    ```

    If needed, sync your local configuration with the on-chain state:

    ```bash
    ntt pull
    ```

3. **Configure inbound and outbound rate limits**: By default, the inbound and outbound limits are set to `0` and must be updated before deployment. For EVM chains, values must be set using 18 decimals, while SVM chains use nine decimals.

    Open your `deployment.json` file and adjust the values based on your use case:

    ```json
    "outbound": "1000.000000000",
    "inbound": {
        "Sepolia": "1000.000000000"
    }
    ```

    - **`outbound`** - a single value that sets the maximum tokens allowed to leave the chain (applies to all destination chains)
    - **`inbound`** - configures per-chain receiving limits for tokens arriving from specific source chains (e.g., the example above limits tokens received from Sepolia)

    This configuration ensures your rate limits align with the token's precision on each chain, preventing mismatches that could block or miscalculate transfers. Before setting these values, confirm your token's decimals on each chain by checking the token contract on the relevant block explorer.

    For more details on rate limiting configuration and behavior, see the [Rate Limiting](/docs/products/token-transfers/native-token-transfers/configuration/rate-limiting/){target=\_blank} page.

4. **Push the final deployment**: Once rate limits are set, push the deployment to the SVM chain using the specified key pair to cover gas fees.

    ```bash
    ntt push --payer INSERT_YOUR_KEYPAIR_JSON
    ```


### Recovering Rent for Failed SVM Deployments

Failed SVM deployments don't result in loss of tokens. Instead, the native tokens may be locked in deployment buffer accounts that persist after interruptions. To recover these funds, refer to the [Solana program deployment guide](https://solana.com/docs/programs/deploying#program-buffer-accounts){target=\_blank} for instructions on identifying and closing these buffer accounts.


Next Steps

## Next Steps

<div class="grid cards" markdown>

-   :octicons-tools-16:{ .lg .middle } **Deploy on EVM Chains**

    ---

    After deploying NTT on SVM chains, deploy and integrate it on EVM chains to enable seamless multichain transfers.

    [:custom-arrow: Deploy NTT on EVM Chains](/docs/products/token-transfers/native-token-transfers/guides/deploy-to-evm/)

-   :octicons-tools-16:{ .lg .middle } **Test Your Deployment**

    ---

    Follow the NTT Post Deployment Guide for integration examples and testing instructions.

    [:custom-arrow: Test Your NTT deployment](/docs/products/token-transfers/native-token-transfers/guides/post-deployment/)

-   :octicons-tools-16:{ .lg .middle } **Launch a Multichain Native Memecoin**

    ---

    Learn how to use the NTT framework to launch a multi-chain native Memecoin 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-8140-9ec4-e800f40a41bc){target=\_blank}

-   :octicons-question-16:{ .lg .middle } **View FAQs**

    ---

    Find answers to common questions about NTT.

    [:custom-arrow: View FAQs](/docs/products/token-transfers/native-token-transfers/faqs/)

</div>


Prerequisites

## Prerequisites

Before deploying NTT on Sui, ensure you have the following prerequisites:

- [Sui Client CLI installed](https://docs.sui.io/guides/developer/getting-started/sui-install){target=\_blank}.


Overview of the Deployment Process

## Overview of the Deployment Process

Deploying NTT on the Sui network follows a structured process:

1. **Choose your token setup**:

     - **Use an existing Sui token**: If your token is already deployed on the Sui network, you can skip token creation and move directly to the [Set Up NTT](#set-up-ntt) section.
     - **Create a new Sui token**: If you don't already have a Sui token deployed, you'll need to deploy and configure it on the Sui network before integrating with Wormhole's NTT.

        !!! warning "Token Compatibility Requirement"
            Your Sui token must be created with the legacy `CoinMetadata` type for NTT compatibility, which can be done using the `coin::create_currency` function.
            Once created, the token can be migrated to the `Currency` standard, but the legacy `CoinMetadata` type must exist initially.

        ???- interface "Create and Deploy a Sui Token"
            This section walks you through setting up a wallet, deploying a Sui Coin contract, and minting tokens on testnet.

            1. **Clone the repository**: Use the [example NTT token repository](https://github.com/wormhole-foundation/example-ntt-token-sui){target=\_blank} to deploy a Sui Coin contract on testnet.

                ```bash
                git clone https://github.com/wormhole-foundation/example-ntt-token-sui
                cd example-ntt-token-sui
                ```

            2. **Set up a new wallet on testnet**: Before building and deploying your token, you'll need to create a new wallet on the Sui testnet and fund it with test tokens.

                1. **Create a new testnet environment**: Configure your Sui client for testnet.

                    ```bash
                    sui client new-env --alias testnet --rpc https://fullnode.testnet.sui.io:443
                    ```

                2. **Generate a new address**: Create a new Ed25519 address for your wallet.

                    ```bash
                    sui client new-address ed25519
                    ```

                3. **Switch to the new address**: The above command will output a new address. Copy this address and switch to it.

                    ```bash
                    sui client switch --address YOUR_ADDRESS_STEP2
                    ```

                4. **Fund your wallet**: Use the faucet to get test tokens.

                    ```bash
                    sui client faucet
                    ```

                5. **Verify funding**: Check that your wallet has been funded.

                    ```bash
                    sui client balance
                    ```

            3. **Build the project**: Compile the Move contract.

                ```bash
                sui move build
                ```

            4. **Deploy the token contract**: Deploy to testnet.

                ```bash
                sui client publish --gas-budget 20000000
                ```

            5. **Mint tokens**: Send tokens to your address.

                ```bash
                sui client call \
                --package YOUR_DEPLOYED_PACKAGE_ID_STEP4 \
                --module MODULE_NAME_STEP1 \
                --function mint \
                --args TREASURYCAP_ID_STEP4 AMOUNT_WITH_DECIMALS RECIPIENT_ADDRESS \
                --gas-budget 10000000
                ```

            !!! note
                This token uses 9 decimals by default. All minting values must be specified with that in mind (1 token = 10^9).
2. **Choose your deployment model**:

    - **Hub-and-spoke**: Tokens are locked on a hub chain and minted on destination spoke chains. Since the token supply remains controlled by the hub chain, no changes to the minting authority are required.
    - **Burn-and-mint**: Tokens are burned on the source chain and minted on the destination chain. This requires transferring the Sui Treasury cap object to the NTT manager.

3. **Deploy and configure NTT**: Use the NTT CLI to initialize and deploy the NTT program, specifying your Sui token and deployment mode.


Set Up NTT

## Set Up NTT

Before deploying NTT contracts on Sui, you need to scaffold a project and initialize your deployment configuration.

!!! note
    If you already have an NTT deployment to another chain (like Solana), you can skip the `ntt new` and `ntt init` commands. Simply navigate to your existing NTT project directory and proceed directly to the [Deploy and Configure NTT](#deploy-and-configure-ntt) section.

The [NTT CLI](/docs/products/native-token-transfers/reference/cli-commands/){target=\_blank} manages deployments, configures settings, and interacts with the NTT system. Follow these steps to set up NTT using the CLI tool:

???- interface "Install the NTT CLI and Scaffold a New Project"

    1. Install the NTT CLI:

        ```bash
        curl -fsSL https://raw.githubusercontent.com/wormhole-foundation/native-token-transfers/main/cli/install.sh | bash
        ```

        Verify installation:

        ```bash
        ntt --version
        ```

    2. Initialize a new NTT project:

        ```bash
        ntt new my-ntt-project
        cd my-ntt-project
        ```

    3. Create the deployment config using the following command. This will generate a `deployment.json` file where your settings are stored:

        === "Mainnet"

            ```bash
            ntt init Mainnet
            ```
        === "Testnet"

            ```bash
            ntt init Testnet
            ```


Deploy and Configure NTT

## Deploy and Configure NTT

Once you've set up NTT, proceed with deploying the contracts.

1. **Environment Setup**: Ensure you have set up your environment correctly, open your terminal, and run the following commands:

    First, list your available key aliases:

    ```bash
    sui client addresses
    ```

    This command displays all available aliases. Note the alias you want to use for your deployment.

    Then, export the private key using your chosen alias:

    ```bash
    sui keytool export --key-identity goofy
    ```
    **Note**: Replace `goofy` with your actual key alias. This command exports the private key in the format required by the NTT add-chain command.

    ```bash
    export SUI_PRIVATE_KEY=INSERT_PRIVATE_KEY
    ```

    After setting up your deployment, finalize the configuration and deploy the NTT program onto the Sui network by following the steps below.

2. **Deploy NTT to Sui**: Run the appropriate command based on your deployment mode.

    !!! note
        The `--token` parameter requires the full Sui coin type in the format `0xADDRESS::module::struct`.
        For example, `0x2::sui::SUI` for the native SUI token, or `0x1234567890abcdef::my_module::MyToken` for a custom token.

    !!! warning
        In burning mode, the NTT CLI moves the treasury-cap object during the add-chain command to the NTT manager, enabling the NTT manager to mint tokens.
        **Important**: Once the treasury-cap object is moved to the NTT manager, you will no longer be able to modify the token's metadata (such as name, symbol, or icon).

    === "Burn-and-Mint"

        ```bash
        ntt add-chain Sui --latest --mode burning --token INSERT_FULL_COIN_TYPE --sui-treasury-cap YOUR_TREASURY_CAP_ID
        ```

    === "Hub-and-Spoke"

        ```bash
        ntt add-chain Sui --latest --mode locking --token INSERT_FULL_COIN_TYPE
        ```

3. **Verify deployment status**: After deployment, check if your `deployment.json` file matches the on-chain configuration using the following command.

    ```bash
    ntt status
    ```

    If needed, sync your local configuration with the on-chain state:

    ```bash
    ntt pull
    ```

4. **Configure inbound and outbound rate limits**: By default, the inbound and outbound limits are set to `0` and must be updated before deployment.

    Open your `deployment.json` file and adjust the values based on your use case:

    ```json
    "outbound": "1000.000000000",
    "inbound": {
        "Sepolia": "1000.000000000"
    }
    ```

    - **`outbound`** - a single value that sets the maximum tokens allowed to leave the chain (applies to all destination chains)
    - **`inbound`** - configures per-chain receiving limits for tokens arriving from specific source chains (e.g., the example above limits tokens received from Sepolia)

    This configuration ensures your rate limits align with the token's precision on each chain, preventing mismatches that could block or miscalculate transfers. Before setting these values, confirm your token's decimals on each chain by checking the token contract on the relevant block explorer.

    For more details on rate limiting configuration and behavior, see the [Rate Limiting](/docs/products/token-transfers/native-token-transfers/configuration/rate-limiting/){target=\_blank} page.

5. **Push the final deployment**: Once rate limits are set, sync the on-chain configuration with local changes made to your `deployment.json` file.

    ```bash
    ntt push
    ```

After you deploy the NTT contracts, ensure that the deployment is properly configured and your local representation is consistent with the actual on-chain state by running `ntt status` and following the instructions shown on the screen.


Next Steps

## Next Steps

<div class="grid cards" markdown>

-   :octicons-tools-16:{ .lg .middle } **Test Your Deployment**

    ---

    Follow the NTT Post Deployment Guide for integration examples and testing instructions.

    [:custom-arrow: Test Your NTT deployment](/docs/products/native-token-transfers/guides/post-deployment/)

-   :octicons-tools-16:{ .lg .middle } **Deploy to SVM Chains**

    ---

    Follow the guide to deploy and configure Wormhole's Native Token Transfers (NTT) for SVM chains.

    [:custom-arrow: Deploy NTT to SVM Chains](/docs/products/native-token-transfers/guides/deploy-to-solana/)

-   :octicons-tools-16:{ .lg .middle } **Launch a Multichain Native Memecoin**

    ---

    Learn how to use the NTT framework to launch a multi-chain native Memecoin 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-8140-9ec4-e800f40a41bc){target=\_blank}

-   :octicons-question-16:{ .lg .middle } **View FAQs**

    ---

    Find answers to common questions about NTT.

    [:custom-arrow: View FAQs](/docs/products/native-token-transfers/faqs)

</div>


Deploy Native Token Transfers with Launchpad

Prerequisites

## Prerequisites

 - An EVM-compatible wallet (e.g., [MetaMask](https://metamask.io/){target=\_blank}, [Phantom](https://phantom.com/){target=\_blank}, etc.).
 - Minimum ETH (or equivalent) for gas fees per deployment.


Supported Blockchains

## Supported Blockchains

The NTT Launchpad currently supports deployments on the following mainnet chains:

 - Ethereum
 - Arbitrum One
 - Base
 - Berachain
 - Blast
 - BNB Smart Chain
 - Ink
 - Optimism Mainnet
 - Polygon


Choose Your Path

## Choose Your Path

Once ready, choose an option to proceed:

 - **[Launch a Cross-Chain Token](#launch-a-cross-chain-token)**: Deploy a brand-new token that is NTT-ready from day one, enabling seamless transfers across multiple blockchains.
 - **[Expand Your Existing Token](#expand-your-existing-token)**: If you already have a token deployed on different chains, integrate it with NTT to enable NTT without modifying its original contract.


Launch a Cross-Chain Token

## Launch a Cross-Chain Token

Deploy a new NTT-compatible token that can be transferred across multiple chains. This process sets up your token on a home network and deploys it to additional blockchains. Follow the below steps to get started:

1. Open the [NTT Launchpad](https://ntt.wormhole.com/){target=\_blank}, connect your wallet, and click **Get Started**.

    ![](/docs/images/products/native-token-transfers/guides/evm-launchpad/ntt-launchpad-1.webp)

2. Select **Launch a Cross-Chain Token**.

    ![](/docs/images/products/native-token-transfers/guides/evm-launchpad/ntt-launchpad-2.webp)

3. Set the token details:
    1. Select the **home network** from the dropdown menu.
    2. Enter the **name** for the token.
    3. Enter the **symbol** of the token.
    4. Provide the **initial supply**.
    5. To the token details, click **Next**.

    ![](/docs/images/products/native-token-transfers/guides/evm-launchpad/ntt-launchpad-3.webp)

4. Select the deployment chains:
    1. The home network where your token will be deployed will be populated (e.g., Optimism).
    2. Choose any additional chains to deploy your token to (e.g., Base).
    3. To continue, click **Next**.

    ![](/docs/images/products/native-token-transfers/guides/evm-launchpad/ntt-launchpad-4.webp)

5. To deploy on the first chain (Optimism), click on **Deploy**; if prompted, switch your wallet to the correct network and confirm the transaction.

    ![](/docs/images/products/native-token-transfers/guides/evm-launchpad/ntt-launchpad-5.webp)

6. Once deployed, you can view the transaction in a block explorer and add the token to your wallet.

    ![](/docs/images/products/native-token-transfers/guides/evm-launchpad/ntt-launchpad-6.webp)

7. Repeat the previous step to deploy the token on the second chain (Base). The supply of tokens on Base will be zero since the tokens were all minted on Optimism in the previous step.

8. Once both deployments are completed, proceed to the [**Dashboard**](#explore-the-launchpad-dashboard) to manage your token.


Expand Your Existing Token

## Expand Your Existing Token

Expand an existing token to support NTT across multiple chains. This process integrates your deployed token with NTT without modifying its original contract. Follow the steps below to get started:

1. Open the [NTT Launchpad](https://ntt.wormhole.com/){target=\_blank}, connect your wallet, and click **Get Started**.

    ![](/docs/images/products/native-token-transfers/guides/evm-launchpad/ntt-launchpad-1.webp)

2. Select **Expand Your Existing Token**.

    ![](/docs/images/products/native-token-transfers/guides/evm-launchpad/ntt-launchpad-7.webp)

3. Enter the token details:
    1. Choose the home network where your token is already deployed (e.g., Optimism).
    2. Choose any additional chains to deploy your token to (e.g., Base).
    3. To continue, click **Next**.

    ![](/docs/images/products/native-token-transfers/guides/evm-launchpad/ntt-launchpad-8.webp)

4. Select the chains to deploy your token to:
    1. The home network where your token is already deployed will be populated (e.g., Optimism).
    2. Choose any additional chains to deploy your token to (e.g., Base).
    1. Click **Next**.

    ![](/docs/images/products/native-token-transfers/guides/evm-launchpad/ntt-launchpad-9.webp)

5. To deploy on the first chain (Optimism), click on **Deploy**; if prompted, switch your wallet to the correct network and confirm the transaction.

    ![](/docs/images/products/native-token-transfers/guides/evm-launchpad/ntt-launchpad-5.webp)

6. Once deployed, you can view the transaction in a block explorer and add the token to your wallet.

    ![](/docs/images/products/native-token-transfers/guides/evm-launchpad/ntt-launchpad-6.webp)

7. Repeat the previous step to deploy the token on the second chain (Base). The supply of tokens on Base will be zero since the tokens were all minted on Optimism in the previous step.

8. Now that your token has been deployed on multiple chains click [**Dashboard**](#explore-the-launchpad-dashboard) to review its details.


Explore the Launchpad Dashboard

## Explore the Launchpad Dashboard

To access the **Dashboard** from the [Launchpad home page](https://ntt.wormhole.com/){target=\_blank}, click on **Manage Deployment**. Here, you can view deployment status, monitor supply across chains, and configure transfer settings.

![](/docs/images/products/native-token-transfers/guides/evm-launchpad/ntt-launchpad-10.webp)

The dashboard provides a high-level view of your token across all deployed chains, including:

 - Token addresses for each chain.
 - Supply distribution visualization.
 - List of deployed chains, including inbound and outbound transfer limits, which can be modified in [**Settings**](#settings).

![](/docs/images/products/native-token-transfers/guides/evm-launchpad/ntt-launchpad-11.webp)


Settings

## Settings

The **Settings** page allows you to configure security parameters, role management, and transfer limits for your deployed token. You can switch between chains to manage these settings independently for each deployment.


Chain Management

### Chain Management

Use the drop-down menu at the top to select the chain you want to configure. The available options correspond to the chains where your token has already been deployed. Once selected, the page displays token details specific to that chain.

From this section, you can also:

 - **Pause the token**: Temporarily turn off transfers on the selected chain.
 - **Deploy to a new chain**: Expand your token by deploying it to an additional chain.

![](/docs/images/products/native-token-transfers/guides/evm-launchpad/ntt-launchpad-12.webp)


Role Management

### Role Management

This section displays key [roles](/docs/products/token-transfers/native-token-transfers/configuration/access-control/){target=\_blank} involved in token governance. You can view and modify these roles by selecting a new address and confirming the update.

 - **Manager’s Owner**: The owner through the `NTTOwner` proxy.
 - **Pauser**: The address authorized to pause transfers.

![](/docs/images/products/native-token-transfers/guides/evm-launchpad/ntt-launchpad-13.webp)


Security Threshold

### Security Threshold

Determine and update how transceivers interact with the token. [Transceivers](/docs/products/token-transfers/native-token-transfers/concepts/architecture/#transceivers){target=\_blank} route NTT transfers between blockchains, ensuring tokens are correctly sent and received across networks.

A higher transceiver threshold increases security by requiring more approvals before processing a transfer, but it may also slow down transactions. A lower threshold allows faster transfers but reduces redundancy in message verification.

 - **Registered Transceivers**: Displays the number of registered transceivers and their addresses.
 - **Transceivers Threshold**: A configurable value that must be less than or equal to the number of transceivers.

![](/docs/images/products/native-token-transfers/guides/evm-launchpad/ntt-launchpad-14.webp)


Peer Chains Limits

### Peer Chains Limits

Define the transfer restrictions for each connected network. You can adjust:

 - **Sending Limits**: The maximum amount of tokens that can be sent from the home chain.
 - **Receiving Limits**: The maximum amount of tokens that can be received for each of the supported peer chains.

Enter a new value to adjust limits and click **Update**. The changes will take effect immediately.

![](/docs/images/products/native-token-transfers/guides/evm-launchpad/ntt-launchpad-15.webp)


Post-Deployment Settings

## Post-Deployment Settings

The following table outlines post-deployment settings available on the NTT Manager contract. These allow you to update roles, pause activity, and adjust transfer limits—useful for upgrades, incident response, or protocol tuning after initial deployment.

| Setting                 | Effect                                   |
|-------------------------|------------------------------------------|
| `pause`                 | Pauses the manager.                      |
| `unpause`               | Unpauses the manager.                    |
| `setOwner`              | Changes the manager owner.               |
| `setPauser`             | Changes the pauser role.                 |
| `setOutboundLimit`      | Sets outbound transfer limit.            |
| `setInboundLimit`       | Sets inbound transfer limit (per chain). |
| `setTransceiverPauser ` | Changes pauser for a transceiver.        |


Next Steps

## Next Steps

<div class="grid cards" markdown>

- :octicons-tools-16:{ .lg .middle } **Transfer Ownership**

    ---

    Learn how to move ownership of your NTT deployment to a new owner address on EVM, Solana, and Sui with step-by-step instructions.

    [:custom-arrow: Follow the Transfer Ownership guide](/docs/products/token-transfers/native-token-transfers/guides/transfer-ownership/)

-   :octicons-tools-16:{ .lg .middle } **Wormhole NTT Connect Demo**

    ---

    Test a transfer or deployment quickly with a standalone [Connect](/docs/products/connect/overview/){target=\_blank} implementation with automatic NTT deployment configuration.

    [:custom-arrow: Explore the NTT Connect demo](https://github.com/wormhole-foundation/connect-w/){target=\_blank}

-   :octicons-tools-16:{ .lg .middle } **Wormhole NTT TypeScript SDK Demo**

    ---

    Reference an example project that uses the Wormhole TypeScript SDK to facilitate token transfers between different blockchain networks after deploying the NTT framework.

    [:custom-arrow: Explore the NTT TypeScript SDK demo](https://github.com/wormhole-foundation/demo-ntt-ts-sdk){target=\_blank}

-   :octicons-tools-16:{ .lg .middle } **Query NTT Token and Transfer Data**

    ---

    Learn how to explore NTT by querying token metadata and transfer activity using the Wormholescan API in a TypeScript project.

    [:custom-arrow: Try the NTT Token and Transfers Guide](/docs/products/messaging/guides/wormholescan-api/)

-   :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>


EVM

## EVM

The [NTT CLI](/docs/products/token-transfers/native-token-transfers/get-started/#install-ntt-cli){target=\_blank} supports transferring ownership on EVM chains. To transfer ownership on the EVM chains, you can do the following:

1. Set the private key used to sign the transaction.

    ```bash
    export ETH_PRIVATE_KEY=INSERT_EVM_PRIVATE_KEY
    ```

2. Run the `ntt transfer-ownership` command, specifying the chain and destination address.

    ```bash
    ntt transfer-ownership INSERT_CHAIN --destination INSERT_DESTINATION_ADDRESS
    ```

    You’ll see a confirmation prompt. Type `y` to proceed.

If successful, you will see the following output:

    export ETH_PRIVATE_KEY=INSERT_EVM_PRIVATE_KEY
	ntt transfer-ownership ArbitrumSepolia --destination 0xc96CE2a...

	Transferring ownership on ArbitrumSepolia (Testnet)
	Manager address: 0x00a97bE...
    New owner: 0xc96CE2a...
	Current owner: 0x0088DFA...

    ⚠ ⚠ ⚠ CRITICAL WARNING ⚠ ⚠ ⚠
    This ownership transfer is IRREVERSIBLE!
    Please TRIPLE-CHECK that the destination address is correct:
    0xc96CE2a...

    Are you absolutely certain you want to transfer ownership to 0xc96CE2a...? [y/N]y
    Transaction hash: 0x57da478...
    Waiting for 1 confirmation...
    Verifying ownership transfer...
    ✅ Ownership transferred successfully to 0xc96CE2a...

!!! tip "Managing NTT from a Safe Multisig?"
    If your NTT owner is a Safe multisig, check out the [NTT EVM Safe Multisig Tools](https://github.com/wormhole-foundation/demo-ntt-evm-multisig-tools){target=\_blank} demo for scripts that generate Safe Transaction Builder JSON files for common operations like peer registration, rate limits, pausing, and ownership transfer.


Solana

## Solana

Transferring ownership of Wormhole's NTT to a multisig on Solana is a two-step process for safety. This ensures that ownership is not transferred to an address that cannot claim it. Refer to the `transfer_ownership` method in the [NTT Manager Contract](https://github.com/wormhole-foundation/native-token-transfers/blob/main/solana/programs/example-native-token-transfers/src/instructions/admin/transfer_ownership.rs#L58){target=\_blank} to initiate the transfer.

1. **Initiate transfer**: Use the `transfer_ownership` method on the NTT Manager contract to set the new owner (the multisig).
2. **Claim ownership**: The multisig must then claim ownership via the `claim_ownership` instruction. If not claimed, the current owner can cancel the transfer.
3. **Single-step transfer (Riskier)**: You can also use the `transfer_ownership_one_step_unchecked` method to transfer ownership in a single step, but if the new owner cannot sign, the contract may become locked. Be cautious and ensure the new owner is a [Program Derived Address (PDA)](https://solana.com/docs/core/pda){target=\_blank}.

For a practical demonstration of transferring ownership of Wormhole's NTT to a multisig on Solana, visit the [GitHub demo](https://github.com/wormhole-foundation/demo-ntt-solana-multisig-tools), which provides scripts and guidance for managing an NTT program using Squads' multisig functionality, including procedures for ownership transfer.


Sui

## Sui

The [Sui CLI](https://docs.sui.io/guides/developer/getting-started/sui-install){target=\_blank} supports transferring ownership by moving the NTT Manager’s `AdminCap` and `UpgradeCap` to your multisig. You can transfer ownership as follows:

1. Find out the `AdminCap` and `UpgradeCap` for your NTT manager.

    ```bash
    sui client object INSERT_SUI_NTT_MANAGER_ADDRESS --json 2>/dev/null | jq -r '"AdminCap ID: \(.content.fields.admin_cap_id)\nUpgradeCap ID: \(.content.fields.upgrade_cap_id)"'
    ```

2. Transfer `AdminCap` object over to a multisig.

    ```bash
    sui client transfer --to INSERT_MULTISIG_ADDRESS --object-id INSERT_ADMIN_CAP_ID_STEP1
    ```

3. Transfer `UpgradeCap` object over to a multisig.

    ```bash
    sui client transfer --to INSERT_MULTISIG_ADDRESS --object-id INSERT_UPGRADE_CAP_ID_STEP1
    ```

4. Check the new owner of the `AdminCap` object.

    ```bash
    sui client object INSERT_ADMIN_CAP_ID_STEP1 --json \
        | jq -r '.owner'
    ```


Native Token Transfers Overview

## Native Token Transfers Overview

Native Token Transfers (NTT) provides an adaptable framework for transferring your native tokens across different blockchains. Unlike traditional wrapped assets, NTT maintains your token's native properties on every chain. This ensures that you retain complete control over crucial aspects, such as metadata, ownership, upgradeability, and custom features.


Key Features

## Key Features

- **Control and customization**: Ensure ownership and configurable access controls, permissions, and thresholds, preventing unauthorized calls.
- **Advanced rate limiting**: Set rate limits per chain and period to prevent abuse, manage network congestion, and control deployments.
- **Global accountant**: Ensures the amount burned and transferred on chains never exceeds the amount of tokens minted.
- **No wrapped tokens**: Tokens are used directly within their native ecosystem, eliminating intermediary transfer steps.


Deployment Models

## Deployment Models

NTT offers two operational modes for your existing tokens:

- **Hub-and-spoke**: Locks tokens on a central "hub" chain and mints equivalents on "spoke" chains, maintaining the total supply on the hub. It's ideal for integrating existing tokens onto new blockchains without altering their original contracts. A [`wethUnwrap` variant](/docs/products/token-transfers/native-token-transfers/guides/deploy-to-evm/#wethunwrap-variant){target=\_blank} is available for bridging native gas tokens (e.g., ETH) on EVM chains.
- **Burn-and-mint**: Burns tokens on the source chain and mints new ones on the destination, distributing the total supply across multiple chains. It's best suited for new token deployments or projects willing to upgrade existing contracts for a truly native multichain token.


Supported Token Standards

## Supported Token Standards

Native Token Transfers primarily support ERC-20 tokens, the most widely used standard for fungible assets on Ethereum and other EVM-compatible chains, including ERC-20 Burnable tokens, which can be burned on the source chain during cross-chain transfers when required. It also supports fungible SPL tokens on SVM-supported chains for secure cross-chain transfers.

The NttManager is a contract that oversees the secure and reliable transfer of native tokens across supported blockchains. It leverages the standard IERC20 interface and OpenZeppelin’s SafeERC20 library to interact with these tokens securely across chains.

NTT does not currently support non-fungible tokens (NFTs) or multi-token standards like ERC-1155. Support is limited to ERC-20 tokens.


Deployment Process

## Deployment Process

Here's a breakdown of the key steps involved when deploying NTT:

- **Prepare tokens**: Ensure your ERC-20 or SPL tokens are ready.
- **Choose deployment model**: Choose your cross-chain token model: either burn-and-mint or hub-and-spoke.

- **Initialization**: Specify target chains and token details, and set up your CLI environment if using it.
- **Deploy contracts**: Deploy NTT Manager contracts to all selected chains, confirming transactions and covering gas fees.
- **Finalize configurations**: Grant minting authority, configure rate limits, establish peer manager connections (bilateral via [`setPeer`](/docs/products/token-transfers/native-token-transfers/reference/manager/evm/#setpeer){target=\_blank} / [`set_peer`](/docs/products/token-transfers/native-token-transfers/reference/manager/solana/#set_peer){target=\_blank}; local configuration, no cross-chain message), and assign administrative roles.
- **Monitor and maintain**: Verify deployment, monitor total supply with the [Global Accountant](/docs/products/token-transfers/native-token-transfers/concepts/security/#global-accountant){target=\_blank}, and adjust configurations as needed.


Use Cases

## Use Cases

- **Cross-Chain Swaps and Liquidity Aggregation**

    - **[Native Token Transfers](/docs/products/token-transfers/native-token-transfers/get-started/)**: Transmits native assets across chains.
    - **[Connect](/docs/products/connect/overview/)**: Manages user-friendly asset transfers.
    - **[Queries](/docs/products/queries/overview/)**: Acquires real-time prices for optimal trade execution.

- **Borrowing and Lending Across Chains**

    - **[Native Token Transfers](/docs/products/token-transfers/native-token-transfers/get-started/)**: Moves collateral as native assets.
    - **[Messaging](/docs/products/messaging/overview/)**: Propagates loan requests and liquidations across chains.
    - **[Queries](/docs/products/queries/overview/)**: Retrieves interest rates and asset prices in real-time.

- **Gas Abstraction**

    - **[Native Token Transfers](/docs/products/token-transfers/native-token-transfers/get-started/)**: Facilitates native token conversion for gas payments.
    - **[Messaging](/docs/products/messaging/overview/)**: Sends gas fee payments across chains.

- **Cross-Chain Payment Widgets**

    - **[Native Token Transfers](/docs/products/token-transfers/native-token-transfers/get-started/)**: Ensures direct, native asset transfers.
    - **[Connect](/docs/products/connect/overview/)**: Facilitates seamless payments in various tokens.

- **Cross-Chain Staking**

    - **[Native Token Transfers](/docs/products/token-transfers/native-token-transfers/get-started/)**: Transfers staked assets natively between networks.
    - **[Messaging](/docs/products/messaging/overview/)**: Moves staking rewards and governance signals across chains.

- **Coordinated Asset Launches**

    - **[Native Token Transfers](/docs/products/token-transfers/native-token-transfers/get-started/)**: Delivers canonical tokens to the destination chain from day one.
    - **[Sunrise](https://www.sunrisedefi.com/){target=\_blank}**: Coordinates bridging, liquidity seeding, and DEX integration on top of NTT so assets arrive tradable across major venues immediately.


Next Steps

## Next Steps

Follow these steps to get started with NTT:

[timeline(docs/.snippets/text/products/native-token-transfers/overview/ntt-timeline.json)]


Table of Commands

## Table of Commands

The following table lists the available NTT CLI commands, descriptions, and examples.

To explore detailed information about any NTT CLI command, including its options and examples, you can append `--help` to the command. This will display a comprehensive guide for the specific command.


General Commands

### General Commands

| Command                                 | Description                                                                                | Example                                                                                |
|-----------------------------------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| `ntt update`                            | Update the NTT CLI.                                                                                | `ntt update`                                                                                |
| `ntt new <path>`                        | Create a new NTT project.                                                                                | `ntt new my-ntt-project`                                                                                |
| `ntt add-chain <chain>`                 | Add a chain to the deployment file. Supports `--manager-variant` (`standard`, `noRateLimiting`, `wethUnwrap`) for EVM chains.                                             | `ntt add-chain Ethereum --token 0x1234... --mode burning --latest --manager-variant standard`                                                                                |
| `ntt upgrade <chain>`                   | Upgrade the contract on a specific chain. Supports `--manager-variant` for EVM chains.                                                                                | `ntt upgrade Solana --ver 1.1.0`                                                                                |
| `ntt clone <network> <chain> <address>` | Initialize a deployment file from an existing contract.                                                                                | `ntt clone Mainnet Solana Sol5678...`                                                                                |
| `ntt init <network>`                    | Initialize a deployment file.                                                                                | `ntt init devnet`                                                                                |
| `ntt pull`                              | Pull the remote configuration.                                                                                | `ntt pull`                                                                                |
| `ntt push`                              | Push the local configuration.                                                                                | `ntt push`                                                                                |
| `ntt status`                            | Check the status of the deployment.                                                                                | `ntt status`                                                                                |
| `ntt set-mint-authority`                | Set token mint authority to token authority (or valid SPL Multisig if `--multisig` flag is provided).                                                                     | `ntt set-mint-authority --chain Solana --token Sol1234... --manager Sol3456... --payer <SOLANA_KEYPAIR_PATH>`                                                                                |
| `ntt transfer-ownership <chain>`        | [Transfer NTT manager ownership](/docs/products/token-transfers/native-token-transfers/guides/transfer-ownership/#evm){target=\_blank} to a new wallet (EVM chains only). | `ntt transfer-ownership Ethereum --destination 0x1234...`                                                                                |
| `ntt token-transfer`                    | Transfer tokens between chains using the NTT protocol.                                                                                | `ntt token-transfer --network Testnet --source-chain Sepolia --destination-chain Solana --amount 0.5 --destination-address 9yZwWH... --deployment-path ./deployment.json --destination-msg-value 20000000` |


Advanced Custom Finality

### Advanced Custom Finality

!!! warning
    Custom finality is an advanced feature. Wormhole Contributors recommend using this with caution.

The `ntt add-chain` command supports an optional flag that enables custom consistency levels for EVM chains. By default, NTT deployments use the `finalized` consistency level.

Choosing a level of finality other than finalized 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.

To select a custom finality level, Wormhole Contributors recommend consulting information on forked blocks in blockchain explorers, focusing on the “ReorgDepth” column.

By proceeding, you affirm that you understand and are comfortable with the risks of setting a custom finality level, and you understand the re-org/rollback risks of Custom finality, accept sole responsibility, and agree that the Wormhole Parties have no liability for losses arising from your selection.


Configuration Commands

### Configuration Commands

| Command                                      | Description                              | Example                                        |
|----------------------------------------------|------------------------------------------|------------------------------------------------|
| `ntt config set-chain <chain> <key> <value>` | Set a configuration value for a chain.   | `ntt config set-chain Ethereum scan_api_key`   |
| `ntt config unset-chain <chain> <key>`       | Unset a configuration value for a chain. | `ntt config unset-chain Ethereum scan_api_key` |
| `ntt config get-chain <chain> <key>`         | Get a configuration value for a chain.   | `ntt config get-chain Ethereum scan_api_key`   |


Hyperliquid Commands

### Hyperliquid Commands

| Command                          | Description                                                                                | Example                                  |
|----------------------------------|-----------------------------------------------------------------------------------------------------------|------------------------------------------|
| `ntt hype link`                  | Link a HyperCore spot token to its HyperEVM ERC-20 contract.                                             | `ntt hype link --token-index 1591`       |
| `ntt hype bridge-in <amount>`    | Bridge tokens from HyperEVM into HyperCore via the asset bridge.                                         | `ntt hype bridge-in 1.0`                 |
| `ntt hype bridge-out <amount>`   | Bridge tokens from HyperCore back to HyperEVM via spotSend.                                              | `ntt hype bridge-out 1.0`               |
| `ntt hype status`                | Display HyperCore token index, asset bridge address, and token identifier for the current deployment.     | `ntt hype status`                        |

For a complete walkthrough on using these commands, see the [Deploy to Hyperliquid](/docs/products/token-transfers/native-token-transfers/guides/deploy-to-hyperliquid/){target=\_blank} guide.


Solana Commands

### Solana Commands

| Command                                        | Description                                               | Example                                         |
|------------------------------------------------|-----------------------------------------------------------|-------------------------------------------------|
| `ntt solana key-base58 <keypair>`              | Print private key in base58.                              | `ntt solana key-base58 /path/to/keypair.json`   |
| `ntt solana token-authority <programId>`       | Print the token authority address for a given program ID. | `ntt solana token-authority Sol1234...`         |
| `ntt solana ata <mint> <owner> <tokenProgram>` | Print the token authority address for a given program ID. | `ntt solana ata Mint123... Owner123... token22` |


Next Steps

## Next Steps

<div class="grid cards" markdown>

-   :octicons-gear-16:{ .lg .middle } **Configure NTT**

    ---

    Find information on configuring NTT, including guidance on setting Owner and Pauser access control roles and management of rate-limiting.

    [:custom-arrow: Configure your NTT deployment](/docs/products/token-transfers/native-token-transfers/configuration/access-control/)

-   :octicons-question-16:{ .lg .middle } **NTT FAQs**

    ---

    Frequently asked questions about Wormhole Native Token Transfers, including cross-chain lending, SDK usage, custom RPCs, and integration challenges.

    [:custom-arrow: Check out the FAQs](/docs/products/token-transfers/native-token-transfers/faqs/)

</div>


Native Token Transfers Manager Contract (EVM)

Structure Overview

## Structure Overview

The NTT Manager system is built using a layered inheritance structure composed of multiple base contracts and interfaces.

```text
NttManager.sol
├── INttManager.sol
├── RateLimiter.sol
│   ├── IRateLimiter.sol
│   └── IRateLimiterEvents.sol
└── ManagerBase.sol
    ├── IManagerBase.sol
    ├── TransceiverRegistry.sol
    ├── PausableOwnable.sol
    ├── ReentrancyGuardUpgradeable.sol
    └── Implementation.sol
```

**Key Components:**

- **`NttManager.sol`**: The main contract that combines all functionality for token transfers with rate limiting.
- **`ManagerBase.sol`**: Provides core management functionality including message handling, threshold management, and transceiver coordination.
- **`RateLimiter.sol`**: Adds rate limiting capabilities with queuing mechanisms for both inbound and outbound transfers.
- **`TransceiverRegistry.sol`**: Manages the registration, enabling, and disabling of transceivers.
- **`PausableOwnable.sol`**: Provides ownership and emergency pause functionality.
- **`ReentrancyGuardUpgradeable.sol`**: Protects against reentrancy attacks in an upgradeable context.
- **`Implementation.sol`**: Handles proxy implementation logic for upgradeable contracts.


State Variables

## State Variables


Core Identification

### Core Identification

- `token` ++"address"++: Address of the token that this NTT Manager is tied to.
- `mode` ++"Mode"++: Mode of the NTT Manager (LOCKING=0 or BURNING=1).
- `chainId` ++"uint16"++: Wormhole chain ID that the NTT Manager is deployed on.
- `NTT_MANAGER_VERSION` ++"string"++: The version string of the NttManager contract implementation.
- `rateLimitDuration` ++"uint64"++: Duration (in seconds) until limits fully replenish.


### Cross-chain Peers and Governance Thresholds

- `peers` ++"mapping(uint16 ⇒ NttManagerPeer)"++: Mapping of peer chain IDs to their peer NTT Manager address and token decimals.
- `messageAttestations` ++"mapping(bytes32 ⇒ AttestationInfo)"++: Tracks whether a message has been executed and the bitmap of transceivers that have attested to it.
- `THRESHOLD_SLOT` ++"uint8"++: Number of attestation approvals required for message execution.
- `MESSAGE_SEQUENCE_SLOT` ++"uint64"++: Monotonic sequence number for outgoing messages.


Rate Limiting and Queues

### Rate Limiting and Queues

- `rateLimitDuration` ++"uint64"++: Duration (in seconds) until limits fully replenish.
- `outboundLimitParams` ++"RateLimitParams"++: Parameters controlling outbound transfer rate limits, including capacity and last transaction timestamp.
- `inboundLimitParams` ++"mapping(uint16 ⇒ RateLimitParams)"++: Parameters controlling inbound transfer rate limits per peer chain.
- `outboundQueue` ++"mapping(uint64 ⇒ OutboundQueuedTransfer)"++: Queue of outbound transfers when rate limits are exceeded, keyed by sequence number.
- `inboundQueue` ++"mapping(bytes32 ⇒ InboundQueuedTransfer)"++: Queue of inbound transfers when rate limits are exceeded, keyed by message digest.


Events

## Events


InboundTransferLimitUpdated

### InboundTransferLimitUpdated

Emitted when the inbound transfer limit is updated. *(Defined in [RateLimiter.sol](https://github.com/wormhole-foundation/native-token-transfers/blob/main/evm/src/libraries/RateLimiter.sol){target=\_blank})*

```sol
event InboundTransferLimitUpdated(
    uint16 chainId,
    uint256 oldLimit,
    uint256 newLimit
)
```

??? interface "Parameters"

    `chainId` ++"uint16"++

    The chain ID for which the limit was updated.

    ---

    `oldLimit` ++"uint256"++

    The previous inbound limit.

    ---

    `newLimit` ++"uint256"++

    The new inbound limit.


InboundTransferQueued

### InboundTransferQueued

Emitted when an inbound transfer is queued due to rate limiting. *([Defined in RateLimiter.sol](https://github.com/wormhole-foundation/native-token-transfers/blob/main/evm/src/libraries/RateLimiter.sol){target=\_blank})*

```sol
event InboundTransferQueued(bytes32 digest)
```

??? interface "Parameters"

    `digest` ++"bytes32"++

    The digest of the queued transfer.


MessageAlreadyExecuted

### MessageAlreadyExecuted

Emitted when a message has already been executed to notify client against retries. *(Defined in [ManagerBase.sol](https://github.com/wormhole-foundation/native-token-transfers/blob/main/evm/src/NttManager/ManagerBase.sol){target=\_blank})*

```sol
event MessageAlreadyExecuted(
    bytes32 indexed sourceNttManager,
    bytes32 indexed digest
)
```

??? interface "Parameters"

    `sourceNttManager` ++"bytes32"++

    The address of the source NttManager.

    ---

    `digest` ++"bytes32"++

    The keccak-256 hash of the message.


MessageAttestedTo

### MessageAttestedTo

Emitted when a message has been attested to by a transceiver. *(Defined in [ManagerBase.sol](https://github.com/wormhole-foundation/native-token-transfers/blob/main/evm/src/NttManager/ManagerBase.sol){target=\_blank})*

```sol
event MessageAttestedTo(bytes32 digest, address transceiver, uint8 index)
```

??? interface "Parameters"

    `digest` ++"bytes32"++

    The digest of the message.

    ---

    `transceiver` ++"address"++

    The address of the transceiver that attested to the message.

    ---

    `index` ++"uint8"++

    The index of the transceiver in the registry.


NotPaused

### NotPaused

Emitted when the contract is unpaused. *(Defined in [PausableUpgradeable.sol](https://github.com/wormhole-foundation/native-token-transfers/blob/main/evm/src/libraries/PausableUpgradeable.sol){target=\_blank})*

```sol
event NotPaused(bool notPaused)
```

??? interface "Parameters"

    `notPaused` ++"bool"++

    Whether the contract is not paused.


OutboundTransferCancelled

### OutboundTransferCancelled

Emitted when an outbound transfer has been cancelled. *(Defined in [NttManager.sol](https://github.com/wormhole-foundation/native-token-transfers/blob/main/evm/src/NttManager/NttManager.sol){target=\_blank})*

```sol
event OutboundTransferCancelled(uint256 sequence, address recipient, uint256 amount)
```

??? interface "Parameters"

    `sequence` ++"uint256"++

    The sequence number being cancelled.

    ---

    `recipient` ++"address"++

    The canceller and recipient of the funds.

    ---

    `amount` ++"uint256"++

    The amount of the transfer being cancelled.


OutboundTransferLimitUpdated

### OutboundTransferLimitUpdated

Emitted when the outbound transfer limit is updated. *(Defined in [RateLimiter.sol](https://github.com/wormhole-foundation/native-token-transfers/blob/main/evm/src/libraries/RateLimiter.sol){target=\_blank})*

```sol
event OutboundTransferLimitUpdated(uint256 oldLimit, uint256 newLimit)
```

??? interface "Parameters"

    `oldLimit` ++"uint256"++

    The previous outbound limit.

    ---

    `newLimit` ++"uint256"++

    The new outbound limit.


OutboundTransferQueued

### OutboundTransferQueued

Emitted when an outbound transfer is queued due to rate limiting. *(Defined in [RateLimiter.sol](https://github.com/wormhole-foundation/native-token-transfers/blob/main/evm/src/libraries/RateLimiter.sol){target=\_blank})*

```sol
event OutboundTransferQueued(uint64 sequence)
```

??? interface "Parameters"

    `sequence` ++"uint64"++

    The sequence number of the queued transfer.


OutboundTransferRateLimited

### OutboundTransferRateLimited

Emitted when an outbound transfer is rate limited. *(Defined in [RateLimiter.sol](https://github.com/wormhole-foundation/native-token-transfers/blob/main/evm/src/libraries/RateLimiter.sol){target=\_blank})*

```sol
event OutboundTransferRateLimited(
    address sender,
    uint64 sequence,
    uint256 amount,
    uint256 currentCapacity
)
```

??? interface "Parameters"

    `sender` ++"address"++

    The address that initiated the transfer.

    ---

    `sequence` ++"uint64"++

    The sequence number of the transfer.

    ---

    `amount` ++"uint256"++

    The amount being transferred.

    ---

    `currentCapacity` ++"uint256"++

    The current available capacity.


OwnershipTransferred

### OwnershipTransferred

Emitted when ownership of the contract is transferred. *(Defined in [OwnableUpgradeable.sol](https://github.com/wormhole-foundation/native-token-transfers/blob/main/evm/src/libraries/external/OwnableUpgradeable.sol){target=\_blank})*

```sol
event OwnershipTransferred(address indexed previousOwner, address indexed newOwner)
```

??? interface "Parameters"

    `previousOwner` ++"address"++

    The previous owner's address.

    ---

    `newOwner` ++"address"++

    The new owner's address.


Paused

### Paused

Emitted when the contract is paused. *(Defined in [PausableUpgradeable.sol](https://github.com/wormhole-foundation/native-token-transfers/blob/main/evm/src/libraries/PausableUpgradeable.sol){target=\_blank})*

```sol
event Paused(bool paused)
```

??? interface "Parameters"

    `paused` ++"bool"++

    Whether the contract is paused.


PauserTransferred

### PauserTransferred

Emitted when pauser capability is transferred. *(Defined in [PausableUpgradeable.sol](https://github.com/wormhole-foundation/native-token-transfers/blob/main/evm/src/libraries/PausableUpgradeable.sol){target=\_blank})*

```sol
event PauserTransferred(address indexed oldPauser, address indexed newPauser)
```

??? interface "Parameters"

    `oldPauser` ++"address"++

    The previous pauser's address.

    ---

    `newPauser` ++"address"++

    The new pauser's address.


PeerUpdated

### PeerUpdated

Emitted when the peer contract is updated. *(Defined in [NttManager.sol](https://github.com/wormhole-foundation/native-token-transfers/blob/main/evm/src/NttManager/NttManager.sol){target=\_blank})*

```sol
event PeerUpdated(
    uint16 indexed chainId_,
    bytes32 oldPeerContract,
    uint8 oldPeerDecimals,
    bytes32 peerContract,
    uint8 peerDecimals
)
```

??? interface "Parameters"

    `chainId_` ++"uint16"++

    The chain ID of the peer contract.

    ---

    `oldPeerContract` ++"bytes32"++

    The old peer contract address.

    ---

    `oldPeerDecimals` ++"uint8"++

    The old peer contract decimals.

    ---

    `peerContract` ++"bytes32"++

    The new peer contract address.

    ---

    `peerDecimals` ++"uint8"++

    The new peer contract decimals.


ThresholdChanged

### ThresholdChanged

Emitted when the threshold required for transceivers is changed. *(Defined in [ManagerBase.sol](https://github.com/wormhole-foundation/native-token-transfers/blob/main/evm/src/NttManager/ManagerBase.sol){target=\_blank})*

```sol
event ThresholdChanged(uint8 oldThreshold, uint8 threshold)
```

??? interface "Parameters"

    `oldThreshold` ++"uint8"++

    The old threshold.

    ---

    `threshold` ++"uint8"++

    The new threshold.


TransceiverAdded

### TransceiverAdded

Emitted when a transceiver is added to the NttManager. *(Defined in [ManagerBase.sol](https://github.com/wormhole-foundation/native-token-transfers/blob/main/evm/src/NttManager/ManagerBase.sol){target=\_blank})*

```sol
event TransceiverAdded(address transceiver, uint256 transceiversNum, uint8 threshold)
```

??? interface "Parameters"

    `transceiver` ++"address"++

    The address of the transceiver.

    ---

    `transceiversNum` ++"uint256"++

    The current number of transceivers.

    ---

    `threshold` ++"uint8"++

    The current threshold of transceivers.


TransceiverRemoved

### TransceiverRemoved

Emitted when a transceiver is removed from the NttManager. *(Defined in [ManagerBase.sol](https://github.com/wormhole-foundation/native-token-transfers/blob/main/evm/src/NttManager/ManagerBase.sol){target=\_blank})*

```sol
event TransceiverRemoved(address transceiver, uint8 threshold)
```

??? interface "Parameters"

    `transceiver` ++"address"++

    The address of the transceiver.

    ---

    `threshold` ++"uint8"++

    The current threshold of transceivers.