Solana程序第二部分:理解SPL关联代币账户

  • Sec3dev
  • 发布于 2022-04-12 19:56
  • 阅读 38

本篇文章深入介绍了Solana的SPL关联代币账户(ATA)程序,包括其技术细节、创建和管理用户代币账户的机制,以及在创建嵌套ATA时可能遇到的问题与解决方案。文章详细阐述了相关指令的使用和实现逻辑,适合对Solana生态系统和智能合约深入了解的开发者。

第 1 部分:理解 SPL 代币铸币 后,本文介绍了 SPL 关联代币程序 的技术细节,这是另一个流行的官方 Solana 智能合约。

该程序提供了一种便利的方式来管理用户的代币账户,来自一个钱包地址。它的程序 ID: ATokenGPvbdGVxr1b2hvZbsiqW5xWH25efTNsLJA8knL

其思路是从用户的钱包地址和代币铸币中创建一个 PDA(即程序派生账户)。 优势有 两个主要好处

  1. PDA 可以作为用户对每种代币所拥有的身份代币账户(相对于一种铸币)
  2. 代币可以直接使用用户的 PDA 作为转账目的地,发送给任何用户,例如,在空投中。

关于关联代币账户(ATA)的一些要点

  • 每个 ATA 是一个 PDA
  • 每个 ATA 是一个 代币账户
  • 每个 ATA 相应于一个 公钥(例如,钱包地址)* 和一个 代币铸币, 并且由 *钱包地址*拥有(详情见下文 \
  • ATA 可以被 任何人 创建(不一定是钱包地址的签名者)
  • 嵌套 ATA 可以被创建,且可以使用 RecoverNested 指令关闭嵌套 ATA。

*钱包地址 — 实际上,它可以是任何一个可以被某个权限签名的 pubkey;例如,系统账户或 PDA(详见 深入探讨 Solana 账户模型)。

细节

接下来,我们将详细说明两个指令:

  • AssociatedTokenAccountInstruction::Create
  • AssociatedTokenAccountInstruction::RecoverNested

SPL 关联代币程序 提供的指令

创建关联代币账户

要创建一个新的关联代币账户( ATA),用户需要向 process_create_associated_token_account 函数提供以下六个账户:

  1. funder_info — 资金账户(必须是系统账户)
  2. associated_token_account_info将要创建的 ATA 地址
  3. wallet_account_info — 新 ATA 的钱包地址
  4. spl_token_mint_info — 新 ATA 的代币铸币
  5. system_program_info — 系统程序
  6. spl_token_program — SPL 代币程序

该函数首先调用 get_associated_token_address_and_bump_seed_internal 计算 associated_token_address(即 PDA)并验证用户输入:

在内部,PDA 是通过 Pubkey::find_program_address 计算的,并由三个地址(在 seeds 中)唯一确定:

  • wallet_address
  • token_program_id
  • token_mint_address

然后,ATA 通过调用 create_pda_account 创建,且其 程序 所有者被设定为 spl_token_program_id(即,只有 spl_token_program 可以修改 PDA 账户的数据):

spl_token_2022 中,它还确保 ATA 的所有者不能被修改,方法是调用 initialize_immutable_owner

最后,ATA(这是一个 Token 账户)通过将其 account.mint 设定为 token_mint_addressaccount.owner 设定为 wallet_address 初始化:

initialize_account3 函数初始化一个代币账户

注意 1:account.owner 这里不是 ATA 的程序级所有者(即 spl_token_program),而是 真实权限(即 wallet_address)。换句话说,wallet_address 完全拥有新创建的 ATA,并且 wallet_address 的所有者必须签名才能从 ATA 转移代币。

注意 2: 如果给定的 wallet_address 的 ATA 尚不存在,则可以通过发出包含 AssociatedTokenAccountInstruction::Create 指令的交易由 任何人 创建。

恢复嵌套

使用关联代币程序的一个 警告 是用户可能( 意外地)创建了一个 嵌套 ATA

由关联代币账户拥有的关联代币账户

一旦发生这种情况,用户无法从嵌套 ATA 移动资金,因为它不属于用户的钱包地址,而是一个 PDA。

RecoverNested 指令用于解决此问题。它关闭嵌套 ATA 并将其代币转账到钱包的 ATA(并将其 lamports 转移到钱包)。

输入的 wallet_account_info 账户 必须被签名,而 destination_associated_token_account_info 账户是转移代币的收件人:

转移的代币 amount 和铸币 decimals 从嵌套 ATA 中提取。signer_seeds(即 owner_associated_token_account_signer_seeds)包括三个地址和 bump_seed

  1. wallet_account_info.key
  2. spl_token_program_id
  3. owner_token_mint_info.key
  4. bump_seed

bump_seed 是从创建 owner_associated_token_address 返回的增量种子,是嵌套 ATA 的 PDA 所有者(即 nested_associated_token_account_info)。

在接下来的几篇文章中,我们将继续强调一些常用的 Solana 程序的技术细节。


Sec3 审计

Sec3(以前的 Soteria)由区块链安全和软件验证领域的领先专家创立。

我们很高兴为在 Solana 上的高影响力 Dapps 提供审核服务。请访问 sec3.dev 或发送电子邮件至 contact@sec3.dev

  • 原文链接: sec3.dev/blog/solana-pro...
  • 登链社区 AI 助手,为大家转译优秀英文文章,如有翻译不通的地方,还请包涵~
点赞 0
收藏 0
分享
本文参与登链社区写作激励计划 ,好文好收益,欢迎正在阅读的你也加入。

0 条评论

请先 登录 后评论
Sec3dev
Sec3dev
https://www.sec3.dev/