在 Anchor 中读取账户余额:Solana 的 address(account).balance

  • 0xE
  • 发布于 4天前
  • 阅读 298

本文介绍了在 Solana Anchor 中使用 Rust 读取账户余额的方法,阐释了 UncheckedAccount 的作用与安全性,解释了无需 [account] 结构体的原因,并提及账户余额与免租机制的相关注意事项。

在 Rust 中读取账户余额

在 Solana Anchor 程序中,可通过以下代码读取任意账户的 Lamports 余额:

use anchor_lang::prelude::*;

declare_id!("7caefaGpKb1E48AkThaVqZqV12WdxbigeVhmRJyVt1EL");

#[program]
pub mod balance {
    use super::*;

    pub fn read_balance(ctx: Context<ReadBalance>) -> Result<()> {
        let balance = ctx.accounts.acct.to_account_info().lamports();

        msg!("balance in Lamports is {}", balance);
        Ok(())
    }
}

#[derive(Accounts)]
pub struct ReadBalance<'info> {
    /// CHECK: although we read this account's balance, we don't do anything with the information
    pub acct: UncheckedAccount<'info>,
}

测试代码:

import * as anchor from "@coral-xyz/anchor";
import { Program } from "@coral-xyz/anchor";
import { Balance } from "../target/types/balance";

describe("balance", () => {
  anchor.setProvider(anchor.AnchorProvider.env());
  const program = anchor.workspace.Balance as Program<Balance>;
  let pubkey = new anchor.web3.PublicKey("5NhLjdFKocoRMqic9sqAe5TxLagJCoCBunzg51ioMYot");

  it("Tests the balance", async () => {
    const tx = await program.methods.readBalance().accounts({ acct: pubkey }).rpc();
  });
});

本例引入了 UncheckedAccount,与此前文章有所不同。


什么是 UncheckedAccount?

UncheckedAccount 是 Anchor 中的账户类型,指示不对账户的所有权进行检查。

背景

  • 默认情况下,Account<'info, T> 类型要求账户由当前程序拥有,Anchor 在幕后验证 owner 字段是否匹配程序 ID,否则交易失败。
  • 此检查防止恶意用户传入伪造账户,保障数据安全。例如,在银行程序中,若未验证所有权,黑客可能传入虚假余额账户。

用途

  • UncheckedAccount 绕过所有权检查,适用于读取非程序拥有的账户(如钱包余额)。
  • 与 AccountInfo 等效,均为低级账户引用。

安全性

  • 示例中仅读取 lamports,无后续逻辑依赖数据,故安全。
  • 若对 UncheckedAccount 的数据执行关键操作,需额外验证。

/// CHECK: 注释

  • Anchor 强制为 UncheckedAccount 添加 /// CHECK: 注释,说明无需类型检查的原因。

  • 移除注释,anchor build 将报错:

    Please add a `/// CHECK:` doc comment explaining why no checks through types are necessary.
  • 此机制提醒开发者关注潜在风险。


为何无需 #[account] 结构体?

[account] 定义数据结构,用于反序列化账户数据。例如:

#[account]
pub struct Counter {
    counter: u64,
}

本例仅读取余额(lamports),不涉及数据字段,因此无需结构体。类似以太坊读取地址余额,无需解析合约状态。


账户余额与免租

根据 Solana 账户租金,账户需维持最低 Lamports 余额以保持免租状态,否则将被运行时回收。

  • 全部余额并非可花费:余额包含租金储备。例如,1 SOL 的账户可能仅部分可转移。
  • 应用场景:在存款或银行程序中,需扣除免租金额以准确计算用户可用余额。

【笔记配套代码】 https://github.com/0xE1337/rareskills_evm_to_solana 【参考资料】 https://learnblockchain.cn/column/119 https://www.rareskills.io/solana-tutorial

点赞 0
收藏 0
分享
本文参与登链社区写作激励计划 ,好文好收益,欢迎正在阅读的你也加入。

0 条评论

请先 登录 后评论
0xE
0xE
0x59f6...a17e
17年进入币圈,Web3 开发者。刨根问底探链上真相,品味坎坷悟 Web3 人生。