---
title: "什么是 Solana 上的 associated token account？"
description: "了解什么是 associated token account、它的工作原理，以及如何创建一个"
---

# 什么是 Solana 上的 associated token account？

[Solana Account Model](https://www.alchemy.com/overviews/solana-account-model) 组织和存储所有链上数据，Associated Token Accounts（ATA）是该模型的关键组成部分之一。本文将介绍什么是 ATA、它的工作原理，以及如何为自己创建一个 Associated Token Account。

## **什么是 Associated Token Account？**

**Associated Token Account 是通过 Solana Associated Token Account Program 创建的，它保存着特定代币的相关信息，包括余额和所有者。** 它是 [Program Derived Address](https://www.alchemy.com/overviews/program-derived-address) 的一种变体。

下面解释一下各个术语的含义：

- **Associated Token Account** - 一个与某个代币相关联的账户（可以联想到 Solana Token Program）
- **Program Derived Address** - 由某个 Solana Program（此处即 Associated Token Account Program）“派生”（创建）出来的地址

### Associated Token Account 及其之间的转账是如何运作的？

**Associated Token Account 之间的转账直接发生在账户之间，同时也间接通过它们的钱包地址进行。**

Token account 相当于 Ethereum 上的 ERC-20 代币，但有一个根本区别：Ethereum 智能合约拥有自己的状态和代码，而 Solana 上的 token account 只包含代码，并将其状态（例如代币余额）“导出”到 Associated Token Account 中，该账户会为该代币的每个所有者分别创建。

**让我们通过 USDC 来快速回顾一下目前学到的内容：**

- Solana 上的 USDC 是一个 token account
- token account 由 [System Program](https://www.alchemy.com/overviews/solana-data-vs-program-accounts) 创建，但由 SPL Token Program 初始化为 Token mint
- 一旦 USDC 代币被初始化，用户就可以开始进行转账
- 持有 USDC 代币的用户，其 Associated Token Account 是通过 Associated Token Account Program（ATP）创建的
- 两人之间的 USDC 交换发生在双方的 ATA 之间

<ImageBlock
  src="https://media.alchemy.com/1703696237-associated-token-account-on-solana.jpg"
  alt="USDC 转账在 Solana 上的关联代币账户之间流动的示意图"
  width={1600}
  height={901}
  caption="Solana 上的关联代币账户"
/>

USDC 转账直接发生在用户的 ATA 之间，同时间接通过 [Solana nodes](https://www.alchemy.com/overviews/solana-nodes) 上的钱包地址进行。这些转账必须发生在使用相同 token mint seed 创建 ATA 的用户之间。

## **什么是 Associated Token Account Program？**

作为 [**Solana Program Library**](https://www.alchemy.com/overviews/solana-program-library) 的一部分，Associated Token Account Program 是每个 ATA 的父程序，它将用户的钱包映射到该用户拥有权限的 ATA。此外，ATA Program 还确保：如果用户想向另一位用户发送代币，即使接收方没有对应代币的 ATA，也能收到该代币。在这种情况下，程序会在智能合约于 [RPC node](https://www.alchemy.com/overviews/solana-rpc) 上执行时自动创建一个 ATA 账户。

Associated Token Account Program 的源代码使用 Rust 编写，可以在 [GitHub](https://github.com/solana-labs/solana-program-library) 上查看。

下面展示了在 TypeScript 中 ATA 底层是如何创建的：

<ImageBlock
  src="https://media.alchemy.com/1703696380-creating-associated-account-source-code.jpg"
  alt="在 Solana 上创建 Associated Account Program 的源代码"
  width={1600}
  height={1338}
  caption="在 Solana 上创建 Associated Account Program 的源代码"
/>

### **Associated Token Account Program 是如何工作的？**

以下是 ATA program 内部发生的过程：

#### **1. 获取常量的 ID**

首先，我们获取 \`TOKEN_PROGRAM_ID\` 和 \`SPL_ASSOCIATED_TOKEN_ACCOUNT_PROGRAM_ID\` 常量。program ID 其实就是该程序地址的另一种说法。

#### **2. 获取 findAssociatedTokenAddress 函数**

接着，我们调用 \`findAssociatedTokenAddress\` 函数，它会返回 publicKey，即新创建的 ATA 的地址。

#### **3. 调用 findProgramAddress 方法**

在该函数内部，会调用 \`findProgramAddress\` 方法，并传入两个参数：

- 一个 Seeds 数组
- SPL_ASSOCIATED_TOKEN_ACCOUNT_PROGRAM_ID

由于 ATA 是 Program Derived Address（PDA）的一种形式，因此可以通过向程序传递参数来创建该账户。创建 PDA 需要将 seeds 作为参数传入，在这个例子中它们分别是：

1. **wallet_address** - 拥有 ATA 中资金的账户地址（authority）
1. **token_program_id** - SPL Token Program 的 program ID
1. **token_mint_address** - 将存储在 ATA 中的 Token account 的地址

Associated Token Account Program 的 ID 是 SPL_ASSOCIATED_TOKEN_ACCOUNT_PROGRAM_ID。

## **如何创建 Associated Token Account**

创建 Associated Token Account 非常简单，只需在 Solana 上使用 spl-token-cli 调用 create-token 即可。创建 ATA 的前提是，与之“关联”的代币已经存在。

<ImageBlock
  src="https://media.alchemy.com/1703696504-creating-associated-token-account-on-solana.jpg"
  alt="在 Solana 上创建关联代币账户"
  width={1600}
  height={749}
  caption="在 Solana 上创建关联代币账户"
/>

该代码调用了 \`create-account\` 命令，该命令接受 \`&lt;TOKEN_MINT_ADDRESS&gt;\` 作为参数。

要创建 Associated Token Account，需要完成以下四个步骤：

1. Transfer SOL - System Program 初始化 ATA 并使其满足 rent-exempt 条件
1. Create Free Space - System Program 为 ATA 分配空闲空间
1. Transfer Ownership - System Program 将该账户的所有权转移给 SPL Associated Token Account Program
1. Initialize the Account - 完成账户初始化，设置代币地址、新创建的 ATA 地址及其所有者

### **owner 和 authority 有什么区别？**

*owner* 是控制该 ATA 的 Solana program 类型，而 *authority* 是向 owner program 发送交易的账户（钱包），owner program 随后代表该 authority 修改 ATA 中的数据。

### **创建 Associated Token Account 需要多少费用？**

默认情况下，Associated Token Account 在创建时必须满足 [**rent-exempt**](https://www.alchemy.com/overviews/how-to-calculate-rent-for-solana-programs) 条件，因此账户中必须保有至少 0.00203928 SOL。System Program 会将这笔 SOL 转入 ATA，该金额从发起交易的账户中扣除。

除了这笔初始费用外，后续的任何交互产生的费用都不会超过 Solana 上普通交易的费用。

### **如何查看 Associated Token Account**

**你可以通过像 Phantom 这样的客户端来查看 Associated Token Account，它们会自动推导出用户钱包拥有权限的所有 ATA。** 此外，由于区块链是公开的，你也可以借助 Solscan.io 之类的浏览器获取这些信息。

粘贴你想查询的钱包地址，其 ATA 会显示在 Token Accounts 下：

<ImageBlock
  src="https://media.alchemy.com/1703696658-solscan-interface.png"
  alt="用于查看钱包 ATA 的 Solscan.io 界面"
  width={1600}
  height={785}
  caption="用于查看钱包 ATA 的 Solscan.io 界面"
/>

### **能否将 Associated Token Account 关联到一个已有账户？**

**将 Associated Token Account 关联到已有账户，这一操作默认已经在幕后完成。由于 ATA 的创建方式，program 或 client 可以很容易地看到每个账户的 seeds。** 这些 seeds 可以被视为指向以下内容的“链接”：

- 拥有该 ATA 权限的钱包
- Token account 的地址（即该 ATA 所持有的代币类型）

## **使用 Alchemy 构建你的 Solana 应用**

了解 Associated Token Account 是成为一名合格 Solana 开发者的第一步。在掌握了 Solana nodes 并选定 RPC provider 之后，你可以使用我们简单易用的 [Solana API](https://www.alchemy.com/docs/reference/solana-api-quickstart) 来抢先开始构建你的第一个 dApp。

## 常见问题

### 什么是 Solana 上的 Associated Token Account（ATA）？

Associated Token Account 是通过 Solana Associated Token Account Program 创建的，它保存着特定代币的相关信息，包括余额和所有者。它是 Program Derived Address 的一种变体，将用户的钱包映射到特定的代币。

### ATA 与普通的 token account 有什么区别？

Solana 上的 token account 只包含代码，并将其状态“导出”到 Associated Token Account 中，该账户会为该代币的每个所有者分别创建。ATA 是通过确定性方式推导出的地址，同时与某个钱包和某个特定的 token mint 相关联。

### 什么是 Associated Token Account Program？

Associated Token Account Program 是 Solana Program Library 的一部分，它将用户的钱包映射到用户拥有权限的 ATA。当用户向没有对应 ATA 的接收方发送代币时，它会自动创建 ATA 账户。

### 创建一个 Associated Token Account 需要多少费用？

ATA 在创建时必须满足 rent-exempt 条件，需要至少 0.00203928 SOL 的余额。这笔金额从发起交易的账户转出，用于满足持续的 rent 要求。

### 推导 ATA 地址使用了哪些 seeds？

ATA 地址通过三个 seeds 推导得出：钱包地址（authority）、token program ID 以及 token mint 地址。这些参数会被传给 Associated Token Account Program，以创建这个确定性地址。

### 我该如何创建一个 Associated Token Account？

你可以使用 spl-token-cli，通过调用 \`create-account\` 命令并传入 token mint 地址作为参数来创建 ATA。整个过程包括转账 SOL、创建空间、转移所有权以及初始化账户。

### 我该如何查看自己的 Associated Token Account？

你可以通过像 Phantom 这样的钱包查看你的 ATA，它们会自动推导出你的钱包拥有权限的所有 ATA；也可以使用 Solscan.io 等区块链浏览器，搜索你的钱包地址并查看 Token Accounts 部分。

### 如果我向没有 ATA 的用户发送代币，会发生什么？

如果接收方的 ATA 不存在，Associated Token Account Program 会在转账过程中自动为其创建 ATA，并从发送方账户中扣除满足 rent-exempt 所需的 SOL 金额，用于创建这个新的 ATA。
