Solana 文档LiteSVMRust附加模块litesvm-token

快速入门

安装

请确保您已安装所有必要的依赖项:

cargo add --dev litesvm litesvm-token solana-sdk spl-token spl-associated-token-account

SPL 代币基础

在 Solana 中,创建 token account 是一个两步流程。

创建 Mint Account

  • 没有代币余额
  • 保存代币的所有全局信息,如总供应量、小数位数、权限等
  • 每种代币对应一个 mint account
  • 所有者为 Token Program(TokenKeg 或 Token 2022)

创建 Token Account

  • 存储特定 SPL 代币的余额
  • 持有 mint account 以定义该账户中的 SPL 代币类型
  • 一个 mint account 可以对应多个 token account
  • 所有者即对该账户内代币拥有控制权的人

Token Account 类型

普通 Token Account

Token account 存储您特定 SPL 代币的余额:

// Can create token accounts at ANY address
let token_account = Keypair::new(); // Random address
let create_ix = system_instruction::create_account(
&payer.pubkey(),
&token_account.pubkey(), // Any address you want
rent,
165, // Token account size
&spl_token::id(),
);
let init_ix = spl_token::instruction::initialize_account(
&spl_token::id(),
&token_account.pubkey(),
&mint,
&owner.pubkey(),
)?;

优点

  • 可为相同的 mint/所有者创建多个账户
  • 灵活——可使用任意地址

缺点

  • 非确定性 - 需要手动追踪地址
  • 收款方必须告知您要发送至哪个账户
  • 多个账户容易造成混乱

适用场景: 临时/托管账户、具有自定义逻辑的程序所有账户、需要为同一代币创建多个账户时,以及高级 DeFi 策略。

Associated Token Account (ATA)

ATA 是位于确定性 PDA 地址的 token account:

// ATA address is ALWAYS the same for owner + mint
let ata = get_associated_token_address(&owner.pubkey(), &mint);
// Address derived from: [owner_pubkey, token_program_id, mint]

ATA 地址的派生方式:

// ATA is a PDA owned by the Associated Token Program
let (ata, bump) = Pubkey::find_program_address(
&[
owner.as_ref(),
spl_token::id().as_ref(),
mint.as_ref(),
],
&spl_associated_token_account::id(), // ATA program
);

优点

  • 每个所有者/铸币对拥有唯一的标准账户
  • 确定性 - 任何人均可计算出该地址
  • 简化支付流程 - 只需钱包地址和铸币地址即可
  • 所有 Solana 应用通用的标准规范

缺点

  • 每个所有者/铸币对只能拥有一个 ATA(设计如此)

适用于大多数场景: 钱包应用、DeFi 协议、NFT 持仓、支付系统,以及任何面向用户的代币转账。

快速示例

以下是创建代币铸造账户并铸造代币的完整示例:

use litesvm::LiteSVM;
use litesvm_token::{
get_spl_account,
spl_token::{native_mint::DECIMALS, state::Account as TokenAccount},
CreateAccount, CreateMint, MintTo, Transfer,
};
use solana_sdk::{
native_token::LAMPORTS_PER_SOL,
signature::{Keypair, Signer},
};
#[test]
fn test_create_and_mint_tokens() {
let mut svm = LiteSVM::new();
// Create payer account and fund it
let payer = Keypair::new();
svm.airdrop(&payer.pubkey(), 10 * LAMPORTS_PER_SOL).unwrap();
// Create a new SPL token mint with the payer as the mint authority
let mint = CreateMint::new(&mut svm, &payer)
.authority(&payer.pubkey())
.decimals(DECIMALS)
.send()
.unwrap();
// Create a token account for the payer
let token_account = CreateAccount::new(&mut svm, &payer, &mint)
.owner(&payer.pubkey())
.send()
.unwrap();
// Mint tokens into the payer's token account
MintTo::new(&mut svm, &payer, &mint, &token_account, 1000)
.owner(&payer)
.send()
.unwrap();
// Verify balance
let token_account: TokenAccount = get_spl_account(&svm, &token_account).unwrap();
let account_balance = token_account.amount;
assert_eq!(account_balance, 1000)
}

核心概念

代币精度(Decimals)

大多数代币使用小数位来表示分数数量:

// SOL has 9 decimals
let one_sol = 10_u64.pow(9); // 1_000_000_000 lamports
// USDC has 6 decimals
let one_usdc = 10_u64.pow(6); // 1_000_000 micro-USDC
// Always account for decimals in calculations
let amount_tokens = 100;
let amount_raw = amount_tokens * 10_u64.pow(decimals as u32);

账户关系

理解账户之间的关系至关重要:

  • 铸造账户(Mint Account):定义代币(供应量、精度、权限)
  • token account:为特定所有者持有代币
  • associated token account:为所有者与铸造账户组合生成的确定性 token account
  • 铸造权限(Mint Authority):可创建新代币
  • 冻结权限(Freeze Authority):可冻结 token account(可选)

故障排查

常见错误

错误原因解决方案
AccountNotFound尝试使用一个不存在的账户确保账户在使用前已创建
AccountAlreadyInitialized尝试初始化一个已初始化的账户在创建前检查账户是否已存在
InsufficientFundslamport 不足以支付 rent 或代币不足以完成转账确保充足的资金或铸造量
OwnerMismatch账户归属于错误的程序创建时验证正确的程序 ID

Is this page helpful?

Table of Contents

Edit Page
©️ 2026 Solana 基金会版权所有