# Cross-Chain Token Setup: BurnMint with SPL Token Multisig Tutorial
Source: https://docs.chain.link/ccip/tutorials/svm/cross-chain-tokens/spl-token-multisig-tutorial
Last Updated: 2025-08-13


This educational tutorial demonstrates how to create and configure cross-chain tokens using Chainlink's Cross-Chain Interoperability Protocol (CCIP) between Solana Devnet and Ethereum Sepolia using **SPL token multisig concepts**. You will learn to implement the **SPL token multisig** approach within **Path A** from the [CCIP Cross-Chain Token Integration Guide](/ccip/concepts/cross-chain-token/svm/integration-guide#path-a-full-self-service-mint-authority-controlled).

**Path A Mint Authority Options:**

- **Direct Transfer**: Transfer mint authority directly to Pool Signer PDA - suitable for development and testing ([see tutorial](/ccip/tutorials/svm/cross-chain-tokens/direct-mint-authority))
- **Multisig Setup** (this tutorial): Learn SPL token multisig concepts with Pool Signer PDA as a member - foundation for production systems
- **Production Multisig**: Enterprise-grade dual-layer governance with Squads + SPL multisig ([see tutorial](/ccip/tutorials/svm/cross-chain-tokens/production-multisig-tutorial))

This tutorial focuses on demonstrating multisig architecture concepts, helping you understand governance controls while maintaining autonomous cross-chain token transfers through BurnMint token pools.

> **NOTE: Educational Multisig Tutorial**
>
> **Important**: This tutorial demonstrates **SPL token multisig concepts** for learning purposes, using simplified
> configurations (1-of-2 with single admin wallet). While the multisig architecture shown provides a foundation for
> production systems, **real production deployments require additional considerations**: proper governance multisig
> (like Squads), higher signature thresholds, and comprehensive security audits. For development and testing
> environments, consider the simpler [Direct Mint Authority Transfer
> tutorial](/ccip/tutorials/svm/cross-chain-tokens/direct-mint-authority).

> **CAUTION: SPL Token Multisig Limitations**
>
> **Critical Understanding**: The SPL token multisig demonstrated in this tutorial can **ONLY execute SPL token
> instructions** (mint, burn, transfer, etc.). It **cannot execute arbitrary transactions** or general governance
> operations like transferring CCIP admin roles or pool ownership. For comprehensive production governance, you would
> typically implement a separate governance multisig (such as Squads) that controls broader aspects including CCIP
> administration, while potentially being one of the signers in the SPL token multisig shown here.

## What You Will Build

This tutorial implements the **SPL token multisig** variant of **Path A** from the [CCIP Cross-Chain Token Integration Guide](/ccip/concepts/cross-chain-token/svm/integration-guide). This approach is designed for **learning multisig concepts** and provides a foundation for production systems.

### Cross-Chain Token Architecture

This tutorial implements the **[Burn and Mint](/ccip/concepts/cross-chain-token/overview#burn-and-mint)** token handling mechanism between Solana Devnet and Ethereum Sepolia with **SPL token multisig governance**. You'll deploy **two BurnMint pools** (one on each chain) that work together to maintain consistent token supply across chains while learning multisig architecture concepts.

**How Burn and Mint Works:**

1. **Source Chain**: Burns tokens from sender's account
2. **CCIP Protocol**: Transmits message cross-chain
3. **Destination Chain**: Mints equivalent tokens to the receiver

### Component Overview

| Component            | Implementation                      | Authority Model                                    |
| -------------------- | ----------------------------------- | -------------------------------------------------- |
| **Ethereum Sepolia** | ERC20 token with CCIP BurnMint pool | Multiple minters: EOA + Pool                       |
| **Solana Devnet**    | SPL token with CCIP BurnMint pool   | SPL Token Multisig: Pool Signer PDA + Admin wallet |

### SPL Token Multisig Architecture

**Key Approach**: You will create an SPL token multisig that includes the Pool Signer PDA as a required member, enabling both autonomous CCIP operations and governance-controlled minting.

**Educational Focus**: This tutorial demonstrates multisig architecture concepts using a simplified 1-of-2 configuration for learning purposes.

## Prerequisites

This tutorial requires setting up two different repositories in separate terminal windows. Follow the setup instructions for both environments before proceeding.

### Development Environment Requirements

**System Requirements:**

- **Anchor and Solana CLI Tools**: Install following the [installation guide](https://www.anchor-lang.com/docs/installation). Requires Rust to be installed.
- **Node.js v20 or higher**: Use the [nvm package](https://www.npmjs.com/package/nvm) to install and manage versions. Verify with `node -v`
- **Yarn**: For dependency management
- **Git**: For cloning repositories

### Terminal 1: Solana Starter Kit Setup

**Clone and setup the Solana Starter Kit:**

```bash
git clone https://github.com/smartcontractkit/solana-starter-kit.git && cd solana-starter-kit
```

**Install dependencies:**

```bash
yarn install
```

**Configure your Solana environment:**

```bash
# Set Solana CLI to use devnet
solana config set --url https://api.devnet.solana.com

# Set your keypair (create one if needed)
solana config set --keypair ~/.config/solana/id.json

# If you do not have a keypair, create one:
solana-keygen new --outfile ~/.config/solana/id.json
```

**Fund your Solana wallet:**

```bash
# Get your wallet address
solana address

# Request SOL from the devnet faucet
solana airdrop 2
```

**Verify your setup:**

```bash
# Check your SOL balance
solana balance

# Verify you are on devnet
solana config get
```

### Terminal 2: Smart Contract Examples Setup

**Clone the repository and navigate to the Hardhat project:**

```bash
git clone https://github.com/smartcontractkit/smart-contract-examples.git
cd smart-contract-examples/ccip/cct/hardhat
```

**Install and compile dependencies:**

```bash
npm install
npm run compile
```

**Set up encrypted environment variables:**

```bash
# Set encryption password
npx env-enc set-pw

# Configure environment variables
npx env-enc set
```

**Required environment variables for Ethereum Sepolia:**

- `ETHEREUM_SEPOLIA_RPC_URL`: RPC endpoint from [Alchemy](https://www.alchemy.com/) or [Infura](https://www.infura.io/)
- `PRIVATE_KEY`: Your testnet wallet private key ([MetaMask export guide](https://support.metamask.io/managing-my-wallet/secret-recovery-phrase-and-private-keys/how-to-export-an-accounts-private-key/))
- `ETHERSCAN_API_KEY`: API key from [Etherscan](https://docs.etherscan.io/getting-started/viewing-api-usage-statistics)

**Fund your wallet:**

- Acquire LINK and ETH on Ethereum Sepolia using [Chainlink faucets](https://faucets.chain.link/)

> **NOTE: Two-Terminal Workflow**
>
> Keep both terminal windows open throughout the tutorial. You will switch between the Solana Starter Kit (Terminal 1)
> and Hardhat project (Terminal 2) as you progress through the phases.

## Tutorial Approach

This tutorial provides step-by-step instructions with detailed explanations of what each command does and why. You'll work primarily in Terminal 1 (Solana) with occasional switches to Terminal 2 (EVM).

**Environment Variable Management**: This tutorial uses phase-based variable files (e.g., `~/.phase1_vars`, `~/.ccip_complete_vars`) to eliminate manual variable re-entry when switching between terminals. Each phase saves its variables to files that subsequent phases can load automatically.

For detailed implementation code explanations, refer to the comprehensive READMEs in both repositories:

- **[Solana Starter Kit README](https://github.com/smartcontractkit/solana-starter-kit/blob/main/README.md)**: Detailed explanations of all SVM commands and implementation
- **[Smart Contract Examples README](https://github.com/smartcontractkit/smart-contract-examples/blob/main/ccip/cct/hardhat/README.md)**: Comprehensive EVM implementation guide

The READMEs contain detailed technical explanations, troubleshooting guides, and advanced configuration options.

## Phase 1: Ethereum Sepolia Token Setup

In this step, you will use Hardhat tasks to deploy an ERC20 token contract and a corresponding burn and mint token pool on Ethereum Sepolia. The tasks interact with the `BurnMintERC20` contract for token deployment and the `BurnMintTokenPool` contract for pool creation.

**Current Terminal: Terminal 2** (Smart Contract Examples - Hardhat) Verify your location:

```bash
pwd
# Should show: .../smart-contract-examples/ccip/cct/hardhat
```

### Step 1: Deploy ERC20 Token

Using the `deployToken` task, deploy a burnable and mintable ERC20 token on Ethereum Sepolia:

Export your token address for later use:

### Step 2: Deploy Token Pool

In this step, you will use the `deployTokenPool` task to deploy a CCIP BurnMint token pool for the token on Ethereum Sepolia. This task interacts with the `BurnMintTokenPool` contract and grants the necessary mint and burn privileges to the pool.

Export your pool address for later use:

### Step 3: Mint Tokens

In this step, you will use the `mintTokens` task to mint tokens on Ethereum Sepolia for your Externally Owned Account (EOA). Since you assigned mint and burn privileges to your EOA when deploying the tokens, you can now mint tokens for testing purposes. This ensures that you have enough tokens in your EOA to perform cross-chain transfers later.

### Step 4: Claim Admin

In this step, you will use the `claimAdmin` task to register your EOA as the administrator for the deployed token on Ethereum Sepolia. This process involves calling the `RegistryModuleOwnerCustom` contract, which will fetch the CCIP admin of the token and set it up as the admin in the registry.

### Step 5: Accept Admin Role

In this step, you will use the `acceptAdminRole` task to accept the admin role for the deployed token on Ethereum Sepolia. Once you have claimed the role, accepting the role finalizes your control over the token administration.

Save the Phase 1 variables for cross-terminal access:

## Phase 2: Solana Devnet Token Setup

In this phase, you will create an SPL token, initialize the CCIP token pool, and complete CCIP registration **before\*\*** setting up the SPL token multisig. This sequence is critical because the self-service registration requires you to hold the mint authority.

**Switch to Terminal 1** (Solana Starter Kit) Verify your location:

```bash
pwd
# Should show: .../solana-starter-kit
```

Load the Ethereum addresses from Phase 1:

```bash
source ~/.phase1_vars
echo "Loaded Phase 1 variables: ETH_TOKEN_ADDRESS=$ETH_TOKEN_ADDRESS, ETH_POOL_ADDRESS=$ETH_POOL_ADDRESS"
```

### Step 1: Create SPL Token

In this step, you will use the `svm:token:create` script to create an SPL token with Metaplex metadata support on Solana Devnet. This script leverages the TokenManager library to create a comprehensive token with metadata, initial supply, and proper configuration for CCIP integration.

### Set Environment Variables

Set up environment variables for easier reference throughout the tutorial:

### Step 2: Initialize CCIP Token Pool

In this step, you will use the `svm:pool:initialize` script to initialize a CCIP token pool for your SPL token. This process creates the necessary on-chain state for cross-chain operations and establishes the Pool Signer PDA that will manage token operations.

### Step 3: Verify Pool Creation

In this step, you will use the `svm:pool:get-info` script to verify that your token pool was initialized correctly. This command queries the on-chain state and displays comprehensive information about your pool configuration, including the Pool Signer PDA and current ownership.

### Step 4: Create Pool Token Account

In this step, you will use the `svm:pool:create-token-account` script to create an Associated Token Account (ATA) for the Pool Signer PDA. This ATA is required for the pool to hold and manage tokens during cross-chain transfer operations.

### Step 5: Set Pool Environment Variables

Set the Pool Signer PDA and Pool Config PDA from the Step 3 output above:

### Step 6: Claim Admin

In this step, you will use the `svm:admin:propose-administrator` and `svm:admin:accept-admin-role` scripts to register yourself as the CCIP administrator for the Solana token. This process establishes your control over the token's CCIP configuration on Solana.

### Step 7: Accept Admin Role

In this step, you will use the `svm:admin:accept-admin-role` script to accept the proposed administrator role. This process establishes your control over the token's CCIP configuration on Solana.

### Step 8: Create SPL Token Multisig

Now that CCIP registration is complete, create the SPL token multisig that will serve as the mint authority:

**Set the multisig address environment variable:**

### Step 9: Transfer Mint Authority to Multisig

Now transfer the mint authority from your wallet to the multisig:

### Step 10: Verify Multisig Configuration

Verify that the multisig has been properly configured and the mint authority has been transferred:

Save the Phase 2 variables for cross-terminal access:

```bash
# Save all variables from Phases 1 and 2 to complete vars file
cat > ~/.ccip_complete_vars << EOF
export ETH_TOKEN_ADDRESS="$ETH_TOKEN_ADDRESS"
export ETH_POOL_ADDRESS="$ETH_POOL_ADDRESS"
export SOL_TOKEN_MINT="$SOL_TOKEN_MINT"
export SOL_ADMIN_WALLET="$SOL_ADMIN_WALLET"
export CCIP_POOL_PROGRAM="$CCIP_POOL_PROGRAM"
export SOL_POOL_SIGNER_PDA="$SOL_POOL_SIGNER_PDA"
export SOL_POOL_CONFIG_PDA="$SOL_POOL_CONFIG_PDA"
export SOL_MULTISIG_ADDRESS="$SOL_MULTISIG_ADDRESS"
EOF

echo "All variables saved to ~/.ccip_complete_vars for cross-terminal access"
```

## Phase 3: Cross-Chain Configuration

In this step, you will configure bidirectional connectivity between the token pools on both chains. Each chain uses different tools: **Solana** uses Starter Kit scripts to configure its pool to recognize Ethereum tokens and pools, while **Ethereum** uses Hardhat tasks to configure its pool to recognize Solana tokens and pools.

### Step 1: Configure Solana -> Ethereum

#### Initialize Chain Remote Configuration

In this step, you will use the `svm:pool:init-chain-remote-config` script to initialize the configuration for Ethereum Sepolia as a remote chain. This creates the basic chain configuration with token information but without pool addresses (those will be added in the next step).

#### Add Ethereum Pool Address

In this step, you will use the `svm:pool:edit-chain-remote-config` script to update the previously created chain configuration with the Ethereum pool address. This completes the configuration by telling the Solana pool which Ethereum pool it should interact with for cross-chain transfers.

#### Verify Configuration

In this step, you will use the `svm:pool:get-chain-config` script to verify that the Solana pool configuration for Ethereum Sepolia has been set up correctly with both the token address and pool address.

### Step 2: Configure Ethereum → Solana

**Switch to Terminal 2 (Smart Contract Examples)**

```bash
pwd
# Should show: .../smart-contract-examples/ccip/cct/hardhat
```

Load all variables from previous phases:

#### Configure Remote Chain

In this step, you will use the `applyChainUpdates` Hardhat task to configure the Ethereum pool to recognize the Solana token and pool. This tells the Ethereum pool which Solana pool (via its Pool Config PDA) and token it should interact with for cross-chain transfers.

#### Verify Remote Chain Configuration

Verify that the Ethereum pool is correctly configured to recognize the Solana chain:

## Phase 4: Pool Registration

In this step, you will register the token pools with their respective tokens on both chains. This is the final configuration step that enables cross-chain operations by linking tokens to their pools in the CCIP registry.

Pool registration works differently on each platform:

- **Ethereum**: Links the token directly to its pool contract address
- **Solana**: Links the token to an Address Lookup Table containing all necessary pool accounts

### Step 1: Ethereum Sepolia Pool Registration

**Stay in Terminal 2 (Smart Contract Examples)**

```bash
pwd
# Should show: .../smart-contract-examples/ccip/cct/hardhat
```

In this step, you will use the `setPool` Hardhat task to register the BurnMint token pool with the token in Ethereum's TokenAdminRegistry contract. This function sets the pool contract address for the token, enabling it for CCIP cross-chain transfers. Only the token administrator can call this function.

### Step 2: Solana Devnet Pool Registration

**Switch to Terminal 1 (Solana Starter Kit)**

```bash
pwd
# Should show: .../solana-starter-kit
```

#### Create Address Lookup Table

Create an Address Lookup Table (ALT) containing all required accounts for CCIP operations:

**Set ALT environment variable:**

#### Register Pool with Router

Register your token pool with the CCIP Router using the Address Lookup Table:

## Phase 5: Testing Cross-Chain Transfers

Test the complete cross-chain token transfer functionality in both directions.

### Step 1: Transfer Solana → Ethereum

**Stay in Terminal 1 (Solana Starter Kit)**

Confirm you are in the correct directory:

```bash
pwd
# Should show: .../solana-starter-kit
```

#### Prepare for Testing

Your Associated Token Account (ATA) was already created during token creation in Phase 1. Now verify your token balance and prepare for cross-chain transfers:

#### Execute Transfer

#### Monitor and Verify Transaction

Upon successful execution, the system generates critical tracking identifiers for transaction monitoring and verification.

**Transaction Identifiers:**

- **Transaction Signature**: `sb2kHXW3M4P56WNNH74LviWcPmeYXjNA4f6opmt8iPrYF1cu5FC9grLhyu2XTEwkABQUrTdaJoDWc5CHe2gQL2u`
- **CCIP Message ID**: `0x9c486ce15650d0bbff3f9cd8ead0510aadd854f7247bf9b775918a1296408aaa`

**CCIP Explorer** (Primary monitoring interface):

```
https://ccip.chain.link/msg/0x9c486ce15650d0bbff3f9cd8ead0510aadd854f7247bf9b775918a1296408aaa
```

The CCIP Explorer provides comprehensive transaction visibility:

- Source chain (Solana) transaction confirmation
- CCIP message processing and routing
- Destination chain (Ethereum) message delivery
- Token minting completion on Ethereum

**Solana Explorer** (Source chain verification):

```
https://explorer.solana.com/tx/sb2kHXW3M4P56WNNH74LviWcPmeYXjNA4f6opmt8iPrYF1cu5FC9grLhyu2XTEwkABQUrTdaJoDWc5CHe2gQL2u?cluster=devnet
```

### Step 2: Transfer Ethereum → Solana

**In Terminal 1 (Solana Starter Kit)**

#### Execute Transfer

#### Monitor and Verify Transaction

Upon successful execution, the system generates distinct tracking identifiers for comprehensive monitoring across both blockchain networks.

**Transaction Identifiers:**

- **Ethereum Transaction Hash**: `0xb2d48398a4d57dde2aaf0551209abad448b092602ca5087e0d108eadd8a8c319`
- **CCIP Message ID**: `0x567f4cdb2e1c52f6aef6354bd9acbeac6761aa4b1a5e74a356785c2e67197d88`

**CCIP Explorer** (Primary monitoring interface):

```
https://ccip.chain.link/msg/0x567f4cdb2e1c52f6aef6354bd9acbeac6761aa4b1a5e74a356785c2e67197d88
```

The CCIP Explorer provides comprehensive transaction visibility:

- Source chain (Ethereum) transaction confirmation
- CCIP message processing and routing
- Destination chain (Solana) message delivery
- Token minting completion on Solana network

**Ethereum Sepolia Explorer** (Source chain verification):

```
https://sepolia.etherscan.io/tx/0xb2d48398a4d57dde2aaf0551209abad448b092602ca5087e0d108eadd8a8c319
```

## Optional: Verify Mint Authority Control

### Demonstrate Manual Minting Through Multisig

This optional section demonstrates that transferring mint authority to the multisig doesn't mean "losing control" - you can still mint tokens manually through the **Admin Wallet** (the non-PDA signer in your multisig). This proves the multisig setup is working correctly and that you retain administrative capabilities.

> **CAUTION: Educational Example Disclaimer**
>
> This page includes an educational example to use a Chainlink system, product, or service and is provided to
> demonstrate how to interact with Chainlink's systems, products, and services to integrate them into your own. This
> template is provided "AS IS" and "AS AVAILABLE" without warranties of any kind, it has not been audited, and it may be
> missing key checks or error handling to make the usage of the system, product or service more clear. Do not use the
> code in this example in a production environment without completing your own audits and application of best practices.
> Neither Chainlink Labs, the Chainlink Foundation, nor Chainlink node operators are responsible for unintended outputs
> that are generated due to errors in code.