Anchor测试交易模拟失败:指令要求的账户丢失

Anchor test Transaction simulation failed: An account required by the instruction is missing

我正在尝试创建一个让用户捐款的简单程序。该程序由 Anchor 引导。不幸的是,它在通过 CPI 创建 PDA 帐户的第一步失败了。详细信息请见下方:

锚点测试失败:

    PublicKey {
  _bn: <BN: 265af4367675fa484c7148bf59dd7392a0a290cee149a6912c35a01495da14df>
} PublicKey {
  _bn: <BN: ee4f6de6f56f9606ca2af702908a5655ede672356998a6139802e3cdde9325f3>
}
Transaction simulation failed: Error processing Instruction 0: An account required by the instruction is missing 
    Program Fg6PaFpoGXkYsidMpWTK6W2BeZ7FEfcYkg476zPFsLnS invoke [1]
    Program log: Instruction: SendDonation
    Instruction references an unknown account 11111111111111111111111111111111
    Program Fg6PaFpoGXkYsidMpWTK6W2BeZ7FEfcYkg476zPFsLnS consumed 5599 of 1400000 compute units
    Program Fg6PaFpoGXkYsidMpWTK6W2BeZ7FEfcYkg476zPFsLnS failed: An account required by the instruction is missing
    1) Should send donation

这里是lib.rs

use anchor_lang::prelude::*;

declare_id!("Fg6PaFpoGXkYsidMpWTK6W2BeZ7FEfcYkg476zPFsLnS");

#[program]
pub mod crypto_donut {
    use super::*;
    use anchor_lang::solana_program::entrypoint::ProgramResult;
    use anchor_lang::solana_program::program::invoke;
    use anchor_lang::solana_program::system_instruction::transfer;

    pub fn initialize(ctx: Context<Initialize>) -> ProgramResult {
        let base_account = &mut ctx.accounts.base_account;
        base_account.owner = ctx.accounts.user.to_account_info().key();
        Ok(())
    }

    pub fn send_donation(ctx: Context<Donation>, amount: u64) -> ProgramResult {
        let base_account = &mut ctx.accounts.base_account;
        base_account.donators.push(ctx.accounts.user.key());

        let instruction = transfer(ctx.accounts.user.key, &base_account.key(), amount);

        invoke(
            &instruction,
            &[
                ctx.accounts.user.to_account_info(),
                base_account.to_account_info(),
            ],
        )
        .unwrap();

        Ok(())
    }
}

#[derive(Accounts)]
pub struct Initialize<'info> {
    #[account(init, payer = user, space = 64 + 1024)]
    pub base_account: Account<'info, BaseAccount>,

    #[account(mut)]
    pub user: Signer<'info>,
    pub system_program: Program<'info, System>,
}

#[account]
pub struct BaseAccount {
    pub donators: Vec<Pubkey>,
    pub owner: Pubkey,
}

#[derive(Accounts)]
pub struct Donation<'info> {
    #[account(mut)]
    pub base_account: Account<'info, BaseAccount>,
    pub user: Signer<'info>,
}

这里是失败的测试:

  it("Should send donation", async () => {
      const donator = anchor.web3.Keypair.generate();

      console.log(donator.publicKey, baseAccount.publicKey);

      await provider.connection.confirmTransaction(
          await provider.connection.requestAirdrop(donator.publicKey, 10000000000),
          "confirmed"
        );

        const tx = await program.rpc.sendDonation(new anchor.BN(100), {
          accounts: {
              baseAccount: baseAccount.publicKey,
              user: donator.publicKey,
          },
          signers: [donator],
        });

        const balance = await program.account.baseAccount.getAccountInfo(donator.publicKey);
      console.log(balance);
        expect(balance.lamports.toString()).equal("100");
      });
});

我做错了什么?

大声笑,我忘记了 #[account(mut)] 之前 pub user: Signer<'info> :))

#[derive(Accounts)]
pub struct Donation<'info> {
    #[account(mut)]
    pub base_account: Account<'info, BaseAccount>,
    #[account(mut)]
    pub user: Signer<'info>,
    pub system_program: Program<'info, System>,
}

system_program也是。感谢 Stepan 的评论