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 的评论
我正在尝试创建一个让用户捐款的简单程序。该程序由 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 的评论