Solana Anchor调用lamports报错如何划转SOL至卖家账户
报错根因
该错误核心原因是 Anchor 框架中 Account<'info, T> 类型本身没有直接暴露 lamports() 方法和 lamports 字段,这类属性/方法属于底层 AccountInfo 类型。你当前持有的是 Box<Account<'info, ListingConfig>> 类型引用,直接调用 lamports 相关方法自然会匹配不到。
除此之外你的原有逻辑还有3个隐含问题:
- 手动修改lamports值再调用系统程序转账的写法不符合Solana账户操作规范,容易触发运行时错误
- 代码中使用了未定义的
lamports变量,会触发第二个编译错误 listing_config账户缺少mut约束,修改余额时会触发权限校验失败
修复方案
优先使用Anchor原生封装的账户关闭API,不需要手动操作lamports、手动构造转账指令,该API会自动完成:将账户内所有剩余SOL划转至指定接收账户、把账户所有权交还给系统程序、重置账户数据长度为0的全流程,符合Solana账户关闭标准。
第一步:修改账户约束
给listing_config字段添加mut标记,开放账户修改权限:
/// The Listing Config used for listing settings #[account( mut, seeds=[ LISTING_CONFIG.as_bytes(), seller.key().as_ref(), auction_house.key().as_ref(), token_account.key().as_ref(), auction_house.treasury_mint.as_ref(), token_mint.key().as_ref(), &token_size.to_le_bytes() ], bump=listing_config.bump, )] pub listing_config: Box<Account<'info, ListingConfig>>,
第二步:替换错误的关闭逻辑
删除invoke_signed调用后所有手动操作lamports、手动构造转账指令的代码,替换为原生close调用:
invoke_signed(&ix, &cpi_accounts.to_account_infos(), &[&auctioneer_seeds])?; // 关闭ListingConfig账户,账户内所有留存SOL自动转入卖家账户 listing_config.close(ctx.accounts.seller.to_account_info())?; Ok(())
特殊场景手动操作Lamports写法(不推荐)
如果因业务特殊需求不能使用原生close方法,需要先将Account类型转换为底层AccountInfo再操作lamports:
let listing_config_acct = listing_config.to_account_info(); let seller_acct = ctx.accounts.seller.to_account_info(); let config_lamports = listing_config_acct.lamports(); **listing_config_acct.lamports.borrow_mut() = 0; **seller_acct.lamports.borrow_mut() += config_lamports;
注意:手动修改lamports必须严格保证所有账户增减的lamports总和为0,否则会直接触发链上运行时错误,非必要不要手动操作。
内容的提问来源于stack exchange,提问作者Asjad khan
相关产品推荐
相关产品推荐

