本篇文章深入介绍了Solana的SPL关联代币账户(ATA)程序,包括其技术细节、创建和管理用户代币账户的机制,以及在创建嵌套ATA时可能遇到的问题与解决方案。文章详细阐述了相关指令的使用和实现逻辑,适合对Solana生态系统和智能合约深入了解的开发者。
继 第 1 部分:理解 SPL 代币铸币 后,本文介绍了 SPL 关联代币程序 的技术细节,这是另一个流行的官方 Solana 智能合约。
该程序提供了一种便利的方式来管理用户的代币账户,来自一个钱包地址。它的程序 ID: ATokenGPvbdGVxr1b2hvZbsiqW5xWH25efTNsLJA8knL
其思路是从用户的钱包地址和代币铸币中创建一个 PDA(即程序派生账户)。 优势有 两个主要好处:
*钱包地址 — 实际上,它可以是任何一个可以被某个权限签名的 pubkey;例如,系统账户或 PDA(详见 深入探讨 Solana 账户模型)。
接下来,我们将详细说明两个指令:
由 SPL 关联代币程序 提供的指令
要创建一个新的关联代币账户( ATA),用户需要向 process_create_associated_token_account 函数提供以下六个账户:
该函数首先调用 get_associated_token_address_and_bump_seed_internal 计算 associated_token_address(即 PDA)并验证用户输入:
在内部,PDA 是通过 Pubkey::find_program_address 计算的,并由三个地址(在 seeds 中)唯一确定:
然后,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_address 和 account.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:
bump_seed 是从创建 owner_associated_token_address 返回的增量种子,是嵌套 ATA 的 PDA 所有者(即 nested_associated_token_account_info)。
在接下来的几篇文章中,我们将继续强调一些常用的 Solana 程序的技术细节。
Sec3(以前的 Soteria)由区块链安全和软件验证领域的领先专家创立。
我们很高兴为在 Solana 上的高影响力 Dapps 提供审核服务。请访问 sec3.dev 或发送电子邮件至 contact@sec3.dev
- 原文链接: sec3.dev/blog/solana-pro...
- 登链社区 AI 助手,为大家转译优秀英文文章,如有翻译不通的地方,还请包涵~
如果觉得我的文章对您有用,请随意打赏。你的支持将鼓励我继续创作!