> ## Documentation Index
> Fetch the complete documentation index at: https://docs.raydium.io/llms.txt
> Use this file to discover all available pages before exploring further.

# SPL Token 和 Token-2022

> Raydium 支持的两个代币标准 —— 遗留的 SPL Token 程序和支持扩展的 Token-2022 程序。了解各自的概念、异同点以及 Raydium 的哪些产品支持哪个标准。

<Info>
  **本页内容由 AI 自动翻译，所有内容以英文版本为准。**

  [查看英文版 →](/solana-fundamentals/spl-token-and-token-2022)
</Info>

Solana 上的每一种可交易资产（包括每个 Raydium 池的基础资产和报价资产）都是由两个程序之一铸造的代币：遗留的 **SPL Token** 程序或其继任者 **Token-2022**。它们是在不同地址的独立程序，具有不同的账户布局和扩展语义。Raydium 支持两者，但并非处处都支持：CPMM、CLMM 和 Farm v6 接受 Token-2022 铸币；AMM v4 则不接受。在与任何池集成前，理解这种分化至关重要。

## 两个程序

|            | SPL Token                                     | Token-2022                                    |
| ---------- | --------------------------------------------- | --------------------------------------------- |
| 程序 ID      | `TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA` | `TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb` |
| 发布时间       | 2020                                          | 2022                                          |
| 账户大小（代币账户） | 165 B                                         | 165 B + 扩展（可变）                                |
| 扩展         | 否                                             | 是 —— 17+ 官方扩展                                 |
| 遗留兼容性      | 完全                                            | 按铸币可选                                         |

两者均由 Solana Labs 团队（现为 Anza）维护，并存放在 `solana-program-library` 仓库下。

## 为何有两个程序？

SPL Token 被冻结以保证向前兼容性 —— 其字节码实际上是不可变的，为整个生态系统提供了一个清晰的基线。随着用例的增长（稳定币需要转账费、机构铸币需要精细化的冻结权限、NFT 需要元数据指针），Solana 团队引入了 **Token-2022** 作为一个独立的、可扩展的程序，而非升级 SPL Token。这保留了现有集成，并让每个铸币只需选择它需要的确切扩展。

Token-2022 在功能上是严格的超集，但在地址空间上不是：两个程序共存，给定地址的铸币恰好属于其中之一。

## 账户结构

### 铸币账户

定义代币的身份。

SPL Token 铸币（82 字节）：

```
u32   mint_authority_option
Pubkey mint_authority
u64   supply
u8    decimals
bool  is_initialized
u32   freeze_authority_option
Pubkey freeze_authority
```

Token-2022 铸币：相同的基础布局，加上零个或多个追加在基础后的 **扩展 TLV**（类型-长度-值）记录。

### 代币账户

保有特定铸币对特定所有者的余额。

SPL Token 账户（165 字节）：

```
Pubkey mint
Pubkey owner
u64    amount
u32    delegate_option
Pubkey delegate
u8     state         // initialized, frozen
u32    is_native_option
u64    is_native
u64    delegated_amount
u32    close_authority_option
Pubkey close_authority
```

Token-2022 账户：相同的基础，加上任何活跃扩展的扩展 TLV 记录。

## Token-2022 扩展

扩展是可附加到铸币或账户的模块化特性。每个扩展都是一条单独的 TLV 记录。对 Raydium 至关重要的包括：

### 转账费

铸币可以对每次转账收取百分比费用。费用流向配置的提取权限持有者。通过 `SwapV2` 被 Raydium CPMM 和 CLMM 支持 —— 程序在计算汇率时考虑该费用，以便池的数学保持一致。

```rust theme={null}
let extension = TransferFeeConfig {
    transfer_fee_config_authority,
    withdraw_withheld_authority,
    withheld_amount: 0,
    older_transfer_fee: ...,
    newer_transfer_fee: ...,
};
```

### 转账钩子

铸币指向一个程序，运行时在每次转账时调用该程序。钩子程序可以拒绝转账或执行副作用（更新合规状态、记录日志等）。Raydium CPMM/CLMM 通过 `SwapV2` 调用钩子 —— 交易包含钩子程序和它需要的任何额外账户。

### 生息

链上余额以配置的利率产生利息。仅限显示（余额随时间增加）而非实际铸币；底层供应量不变。

### 铸币关闭权限

允许在供应量达到零后关闭铸币。

### 永久委托

指定的钱包可以无条件地从任何账户转账或销毁代币。**Raydium 阻止为具有此扩展的铸币创建池** —— 这与"池储备不能被夺取"的不变量不兼容。

### 不可转账

代币无法从铸造它们的账户移出。**Raydium 阻止池创建** —— 不可交易的资产不能作为 LP 池的基础或报价资产。

### 默认账户状态

此铸币的新代币账户默认被冻结，必须由冻结权限解冻。可用但罕见。

### 机密转账

余额和转账金额被加密。Raydium 不支持机密转账铸币（池数学需要明文余额）。

### 元数据指针 + 代币元数据

为 Token-2022 铸币替代 Metaplex 元数据。支持 Raydium 池列表。

### 组 / 成员指针

声明铸币属于一个组（例如 NFT 集合）。仅供信息使用；Raydium 将其用于显示。

查看[官方 Token-2022 扩展页面](https://spl.solana.com/token-2022/extensions)获取完整列表。

## Raydium 产品支持情况

| 产品        | SPL Token | Token-2022 | 备注                         |
| --------- | --------- | ---------- | -------------------------- |
| AMM v4    | 是         | 否          | OpenBook 集成需要 SPL Token    |
| CPMM      | 是         | 是          | Token-2022 池需要 `SwapV2`    |
| CLMM      | 是         | 是          | Token-2022 池需要 `SwapV2`    |
| Farm v6   | 是         | 是          | 支持质押铸币和奖励铸币                |
| LaunchLab | 是         | 是          | 毕业的 CPMM 池继承 Token-2022 支持 |

Raydium 池的铸币资格 —— 除非列出，否则所有扩展都允许：

* **被阻止**：不可转账、永久委托、机密转账、默认账户状态（在被拒配置中）。
* **条件允许**（LP 必须接受风险）：转账费、转账钩子、冻结权限活跃。
* **完全允许**：生息、元数据指针、组指针、铸币关闭权限。

`getPoolInfoFromRpc` 响应包含铸币的扩展标志 —— 客户端在成为 LP 前应检查。

## 代币账户标准

### 关联代币账户（ATA）

两个程序共享 **关联代币账户** 约定：通过关联代币程序 (`ATokenGPvbdGVxr1b2hvZbsiqW5xWH25efTNsLJA8knL`) 从 `[owner, programId, mint]` 派生的 PDA。Solana 上几乎每个用户代币账户都是 ATA。

```ts theme={null}
import { getAssociatedTokenAddressSync } from "@solana/spl-token";

// SPL Token
const ata = getAssociatedTokenAddressSync(mint, owner);

// Token-2022
const ata22 = getAssociatedTokenAddressSync(
  mint,
  owner,
  false,               // allowOwnerOffCurve
  TOKEN_2022_PROGRAM_ID,
);
```

ATA 程序根据哪个程序拥有铸币来创建由相应代币程序拥有的账户。

### 非 ATA 代币账户

钱包可以为单个铸币拥有多个代币账户；ATA 只是约定。例如，池金库不是 ATA —— 它们是池程序的 PDA，持有池的储备。

## 检测铸币属于哪个程序

每个铸币的账户都有一个 `owner` 字段，指向 SPL Token 或 Token-2022：

```ts theme={null}
const mintInfo = await connection.getAccountInfo(mintPubkey);
if (mintInfo.owner.equals(TOKEN_PROGRAM_ID)) {
  console.log("SPL Token mint");
} else if (mintInfo.owner.equals(TOKEN_2022_PROGRAM_ID)) {
  console.log("Token-2022 mint");
}
```

Raydium SDK 会自动处理此检测 —— `getPoolInfoFromRpc` 为每个代币返回相应的 `programId`，以便客户端可以构建正确的 ATA。

## 按程序划分的交换指令

Raydium 的 CPMM 和 CLMM 各有两个交换指令：

| 指令                           | 支持的铸币                  |
| ---------------------------- | ---------------------- |
| `Swap` / `SwapBaseInput`（遗留） | 仅 SPL Token            |
| `SwapV2` / `SwapBaseInputV2` | SPL Token 和 Token-2022 |

`SwapV2` 接受额外的账户：两侧的铸币账户、每侧的代币程序（因为它们可能不同），以及 —— 对于转账钩子铸币 —— 钩子程序和其所需账户。

当至少一侧是 Token-2022 时，客户端应始终使用 `SwapV2`；`SwapV2` 也适用于仅 SPL 的池，但遗留的 `Swap` 在计算上更便宜。

SDK 会自动选择正确的变体。

## 将 SPL Token 项目迁移到 Token-2022

Token-2022 在铸币级别上不是即插即用的替代品 —— 地址 X 处的铸币要么是 SPL，要么是 Token-2022，这在创建时就固定了。要"迁移"你必须：

1. 在 Token-2022 下创建一个新铸币，配置你需要的扩展。
2. 为旧 SPL 铸币的持有者提供交换/包装机制以换取新铸币。
3. 更新所有 LP 池、农场和集成以引用新铸币。

这很繁重。大多数在 SPL 下推出的项目除非特定扩展需求强制迁移，否则会保持在 SPL。

## 实战例子：创建带转账费的 Token-2022 铸币

```ts theme={null}
import {
  Connection, Keypair, SystemProgram, Transaction, sendAndConfirmTransaction,
} from "@solana/web3.js";
import {
  TOKEN_2022_PROGRAM_ID, ExtensionType, createInitializeMintInstruction,
  getMintLen, createInitializeTransferFeeConfigInstruction,
} from "@solana/spl-token";

const connection = new Connection("https://api.mainnet-beta.solana.com");
const payer      = Keypair.generate();
const mint       = Keypair.generate();

const extensions    = [ExtensionType.TransferFeeConfig];
const mintLen       = getMintLen(extensions);
const rentLamports  = await connection.getMinimumBalanceForRentExemption(mintLen);

const tx = new Transaction().add(
  SystemProgram.createAccount({
    fromPubkey:       payer.publicKey,
    newAccountPubkey: mint.publicKey,
    space:            mintLen,
    lamports:         rentLamports,
    programId:        TOKEN_2022_PROGRAM_ID,
  }),
  createInitializeTransferFeeConfigInstruction(
    mint.publicKey,
    payer.publicKey,                  // transfer fee authority
    payer.publicKey,                  // withdraw-withheld authority
    50,                               // 50 bps = 0.5%
    BigInt(1_000_000),                // max fee per transfer (smallest units)
    TOKEN_2022_PROGRAM_ID,
  ),
  createInitializeMintInstruction(
    mint.publicKey,
    9,                                // decimals
    payer.publicKey,                  // mint authority
    null,                             // freeze authority
    TOKEN_2022_PROGRAM_ID,
  ),
);

await sendAndConfirmTransaction(connection, tx, [payer, mint]);
```

这个铸币可以被 LP 到 Raydium CPMM 池；交换者除了池的交换费外还需支付 0.5% 的转账费。

## 安全考虑

在 LP 到或通过 Token-2022 铸币交换之前：

* **检查 `freeze_authority`**。如果非空且由中心化方控制，他们可以冻结你的 ATA（以及可能的池金库）。
* **检查 `transfer_hook`**。钩子程序可以任意阻止转账 —— 对钩子的源代码进行尽职调查。
* **检查 `transfer_fee`**。在预期交换输出中考虑费用。
* **检查 `permanent_delegate` 和 `non_transferable`**。Raydium 的程序会拒绝这些，但如果构建自定义集成需验证。

查看 [`security/oracle-and-token-risks`](/zh/security/oracle-and-token-risks) 以了解完整的风险接受框架。

## 相关指南

* [`solana-fundamentals/account-model`](/zh/solana-fundamentals/account-model) —— 一般账户模型。
* [`reference/token-2022-support`](/zh/reference/token-2022-support) —— CPMM 和 CLMM 的 Token-2022 细节。
* [`security/oracle-and-token-risks`](/zh/security/oracle-and-token-risks) —— 恶意铸币扩展带来的风险。

参考资料：

* [SPL Token 文档](https://spl.solana.com/token)。
* [Token-2022 文档](https://spl.solana.com/token-2022) —— 完整的扩展列表。
* [关联代币账户](https://spl.solana.com/associated-token-account)。
