本文分析了在使用Anchor框架开发Solana程序时,当交易的to token和quote token相同时,由于Anchor的序列化机制可能导致的问题。文章通过WooFi Sherlock contest中的一个例子,说明了重复账户在序列化时可能导致数据覆盖,并提供了一种解决方案,即在处理重复账户时,只更新其中一个变量。
本文将使用 WooFi Sherlock 竞赛 中的这份报告作为底层示例。
#[derive(Accounts)]
pub struct Swap<'info> {
// ... 所有账户定义 ...
woopool_from: Box<Account<'info, WooPool>>,
woopool_to: Box<Account<'info, WooPool>>,
woopool_quote: Box<Account<'info, WooPool>>,
// ... 更多账户 ...
}
pub fn handler(ctx: Context<Swap>, from_amount: u128,
min_to_amount: u128) -> Result<()>
{
// ... 逻辑
在上面的代码片段中,Swap 结构体是由 handler 函数表示的 swap 指令的输入上下文。这允许用户将 from token 兑换为 to token,其中 quote 是兑换的单位。
例如,我想将 ABC 兑换为 XYZ,但没有 ABC/XYZ 预言机。但存在两个预言机 ABC/USDC 和 XYZ/USDC。那么我可以卖出 ABC 换取 USDC,并用 USDC 购买 XYZ。最后,这类似于将 ABC 兑换为 XYZ,但多了一个步骤;USDC 在这里是 quote token。
回到我们的 swap 指令,用户可以通过在 woopool_from、woopool_to 和 woopool_quote 中提供正确的账户来描述他们的 swap。如果我们保留之前的例子:
在 swap 操作期间,woopool_quote 接收费用,而 woopool_from 和 woopool_to 会更新其 token 数量。
woopool_from.add_reserve(from_amount).unwrap();
woopool_to.sub_reserve(to_amount).unwrap();
// 将费用记录到账户中
woopool_quote.sub_reserve(swap_fee).unwrap();
woopool_quote.add_unclaimed_fee(swap_fee).unwrap();
但是,如果 swap 路径是直接的会发生什么?假设我们的用户想要将 ABC(from token)兑换为 USDC(to token),那么 USDC 也可以作为 quote token,这意味着用户将向指令提供:
我们可以在这里看到 woopool_to 和 woopool_quote 与同一个账户相关。这就是事情变得有趣的地方:这些账户是如何提供给指令的?
当 Anchor 处理你的账户时,它遵循三个步骤:
问题在于最后一步,当数据写回账户时:
那么,这里的解决方案是什么?
解决此问题的一种方法是仅将更改应用于其中一个变量,即 woopool_to 或 woopool_quote,以用于影响 USDC WooPool 的两个操作。
我们可以对 woopool_to 执行两项操作,而不是更新 woopool_to 上的 token 余额并将费用分配给 woopool_quote:
woopool_from.add_reserve(from_amount).unwrap();
woopool_to.sub_reserve(to_amount).unwrap();
// 将费用记录到账户中
if ctx.accounts.woopool_to.key() == ctx.accounts.woopool_quote.key() {
woopool_to.sub_reserve(swap_fee).unwrap();
woopool_to.add_unclaimed_fee(swap_fee).unwrap();
} else {
// ...
}
这个解决方案有效,因为:
你可以使用这个Solana Playground亲自尝试一下
说明:
总的来说,Anchor 非常强大,但它不是魔法。理解它的序列化机制对于构建安全、可预测的 Solana 程序至关重要。通过正确管理内存和整合状态更改,你可以避免那些会悄无声息地破坏你的逻辑的陷阱。
想了解更多?请继续关注更多深入的内容、真实的错误和智能合约最佳实践。
在 X / LinkedIn 上关注 @AdevarLabs - 安全交付!
- 原文链接: adevarlabs.com/blog/anch...
- 登链社区 AI 助手,为大家转译优秀英文文章,如有翻译不通的地方,还请包涵~
如果觉得我的文章对您有用,请随意打赏。你的支持将鼓励我继续创作!