Solana智能合约的安全性:SPL关联Token账户的两个注意事项

  • Sec3dev
  • 发布于 2022-09-24 17:22
  • 阅读 30

文章讨论了Solana智能合约中的SPL Associated Token程序的两个重要注意事项:不要将关联Token账户设置为其他Token账户的所有者,以及在验证关联Token账户时,不能仅依赖所有者和铸造信息。文中提供了相关的代码示例以及潜在的安全问题。

SPL关联代币程序在Solana智能合约中被频繁使用。我们在之前的一篇文章中回顾了其技术细节。在本文中,我们着重讨论Sec3核心团队了解到的使用关联代币账户的两个重要注意事项。

  1. 注意不要将任何关联代币账户设置为代币账户的所有者
  2. 注意不要仅通过其所有者和铸造来验证任何输入的关联代币账户

1. 不要将关联代币账户(ATA)设置为所有者

如果错误地将关联代币账户设置为代币账户的所有者,你可能会丢失所有代币,并且这些代币可能无法恢复。

使用系统程序创建新账户时,可以将任何Pubkey作为新账户的所有者传入:

查看 源代码

但是,如果你错误地将一个关联代币账户(ATA)传入作为所有者,那么你将失去对该账户的控制权,也就是说,无法修改账户数据。

原因在于ATA是一个PDA(即程序派生账户),并没有相应的私钥来进行签名。

这个问题已经发生在一些用户身上(例如, https://github.com/solana-labs/solana-program-library/pull/288 9),而Solana实施了一条名为RecoverNested的指令,以帮助恢复嵌套的ATA查看详细信息)。

如果一个ATA X是由另一个ATA Y拥有,那么X被称为嵌套的ATA,其代币可以通过RecoverNested指令恢复。该指令将X中所有代币转账到Y,并关闭X。

重要的是,截至2022年9月,RecoverNested指令不恢复非嵌套的ATA。也就是说,如果一个代币账户由一个ATA拥有,但该代币账户本身不是ATA,那么它不能被恢复。

2. 不要仅通过所有者和铸造验证关联代币账户

如果仅通过所有者/铸造来验证关联代币账户,而不是使用get_associated_token_address,可能会允许意想不到的代币账户传入,这可能会干扰你的协议。

仅通过所有者和铸造来验证关联代币账户是不够的。例如,在Anchor账户验证中,使用以下约束(而不是_get_associated_tokenaddress):

#[account(mut,
    constraint = vault_ata.owner == vault.key(),
    constraint = vault_ata.mint == vault.mint
)]
pub vault_ata: Box<Account<'info, TokenAccount>>,

上述代码仅验证vault_ata的所有者是vault,并且它与vault.mint具有相同的铸造,但是vault_ata可能根本不是ATA。

攻击者可以传入任意代币账户(将其ownermint分别设置为vault.key()vault.mint),并通过验证。根据协议逻辑,传入的伪造ATA可能会导致安全问题。

要验证ATA,请使用_get_associated_tokenaddress

#[account(mut,
    address = get_associated_token_address(&vault.key(), &vault.mint)
)]
pub vault_ata: Box<Account<'info, TokenAccount>>,

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

0 条评论

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