<aside> 💡

anchor中的account哪些在ctx中要被声明mut?比如是ata_a给ata_b转账,那么ata_b要声明为mut么? 如果是account A给account B转SOL,account A和account B需要时mut么?

</aside>

在 Anchor 中,#[account(mut)] 的使用决定了哪些账户在指令执行期间需要被标记为可写(is_writable = true)。是否需要声明 mut 取决于账户在交易中是否会被修改,而这通常由具体的程序逻辑和底层 Solana 运行时规则决定。以下我会针对你提到的两种情况(ATA 转账和 SOL 转账)逐一分析,并总结 Anchor 中 mut 的使用规则。


情况 1:ATA_A 给 ATA_B 转账

假设你的程序通过 SPL Token 程序从 ata_a(源代币账户)向 ata_b(目标代币账户)转移代币,典型场景如下:

rust

use anchor_lang::prelude::*;
use anchor_spl::token::{self, Token, TokenAccount, Transfer};

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

    pub fn transfer_tokens(ctx: Context<TransferTokens>, amount: u64) -> Result<()> {
        let cpi_accounts = Transfer {
            from: ctx.accounts.ata_a.to_account_info(),
            to: ctx.accounts.ata_b.to_account_info(),
            authority: ctx.accounts.authority.to_account_info(),
        };
        let cpi_ctx = CpiContext::new(
            ctx.accounts.token_program.to_account_info(),
            cpi_accounts,
        );
        token::transfer(cpi_ctx, amount)?;
        Ok(())
    }
}

#[derive(Accounts)]
pub struct TransferTokens<'info> {
    #[account(mut)]
    pub ata_a: Account<'info, TokenAccount>, // 源代币账户

    #[account(mut)]
    pub ata_b: Account<'info, TokenAccount>, // 目标代币账户

    pub authority: Signer<'info>, // ata_a 的授权者(可能是用户或 PDA)

    pub token_program: Program<'info, Token>,
}

哪些账户需要声明为 mut?

  1. ata_a(源代币账户)
  2. ata_b(目标代币账户)
  3. authority
  4. token_program

小结

在 ATA_A 给 ATA_B 转账的场景中:


情况 2:Account A 给 Account B 转 SOL

假设你的程序通过 system_instruction::transfer 从 account_a(源账户)向 account_b(目标账户)转移 SOL,典型场景如下:

rust