system_instruction::create_account 创建新账户时 Solana CPI(运行时)调用失败(带锚框架的链上程序)
Solana CPI (runtime) invoke fails when creating a new account by system_instruction::create_account (on-chain program with anchor framework)
我正在尝试创建一个让用户铸造 SPL 令牌的简单程序。
该程序由 Anchor 引导。不幸的是,它在通过 CPI 创建 PDA 帐户的第一步失败了。详情请见下方:
----处理器-----
我试图简化链上程序的处理器,使用 Solana 系统程序创建一个简单的 PDA 帐户。处理器只有一个CPI。
----说明-----
我还尝试通过只输入 4 个帐户来简化指令(请参见屏幕截图或随附的我的代码):
在打字稿测试代码中,它也很简单。
我只是导出一个 PDA,然后将这个 PDA 和其余 3 个帐户传递到指令中。 (两个约束1.分配签名者2.为PDA帐户设置mut)
-----错误-----
但我仍然得到错误
Transaction simulation failed: Error processing Instruction 0: An account required by the instruction is missing
Program 6KA5onmgQN7gsBZ5whPCTVL4EQcRob6vw7TYYNvik8xb invoke [1]
Program log: Instruction: Mintnft
Program log: First line in MintNFT processor
Instruction references an unknown account 11111111111111111111111111111111
Program 6KA5onmgQN7gsBZ5whPCTVL4EQcRob6vw7TYYNvik8xb consumed 15319 of 200000 compute units
Program 6KA5onmgQN7gsBZ5whPCTVL4EQcRob6vw7TYYNvik8xb failed: An account required by the instruction is missing
1) is minted
2 passing (2s)
1 failing
1) anchor_programs
is minted:
Error: failed to send transaction: Transaction simulation failed: Error processing Instruction 0: An account required by the instruction is missing
at Connection.sendEncodedTransaction (node_modules/@solana/web3.js/src/connection.ts:3961:13)
at processTicksAndRejections (internal/process/task_queues.js:97:5)
at Connection.sendRawTransaction (node_modules/@solana/web3.js/src/connection.ts:3918:20)
at sendAndConfirmRawTransaction (node_modules/@solana/web3.js/src/util/send-and-confirm-raw-transaction.ts:27:21)
at Provider.send (node_modules/@project-serum/anchor/src/provider.ts:118:18)
at Object.rpc [as mintnft] (node_modules/@project-serum/anchor/src/program/namespace/rpc.ts:25:23)
似乎我没有将正确的帐户传递到调用主体中,但我花了一整天的时间检查但仍然不确定是否还有其他丢失的帐户(或 AccountInfo)。
如果有人能给我提示,我将不胜感激。
您可以在屏幕截图格式中看到我的代码摘要。
.src/lib.rs
use anchor_lang::prelude::*;
use anchor_spl::token::Mint;
use solana_program::program::invoke;
use solana_program::system_instruction;
declare_id!("ArT6Hwus2hMwmNeNeJ2zGcQnvZsbrhz8vTbBdq35AdgG");
#[program]
pub mod anchor_programs {
use super::*;
pub fn initialize(ctx: Context<Initialize>, price: u64) -> ProgramResult {
ctx.accounts.nft_creator.price = price;
ctx.accounts.nft_creator.collection = vec![];
Ok(())
}
pub fn mintnft(ctx: Context<MintNFT>) -> ProgramResult {
msg!("First line in MintNFT processor");
let (mint_pda, _bump) = Pubkey::find_program_address( // Calc PDA address from passed in nft_creater_program_id
&[b"nft_creator"],
&ctx.accounts.nft_creater_program.key()
);
if mint_pda != ctx.accounts.mint_pda_acc.key() { // Confirm if passed in PDA address is the same
return Err(ProgramError::Custom(123))
}
let create_acc_ix = system_instruction::create_account( // Try create account using system_instruction
&ctx.accounts.minter.key(),
&ctx.accounts.mint_pda_acc.key(),
ctx.accounts.rent.minimum_balance(Mint::LEN),
Mint::LEN as u64,
&spl_token::ID,
);
invoke(&create_acc_ix, &[ // Use invoke to call cross program invocation
ctx.accounts.minter.clone(),
ctx.accounts.mint_pda_acc.clone(),
])?;
Ok(())
}
}
#[derive(Accounts)]
pub struct Initialize<'info> {
#[account(init, payer=initializer, space=500)]
pub nft_creator: Account<'info, NftCreator>,
#[account(mut, signer)]
pub initializer: AccountInfo<'info>,
pub system_program: AccountInfo<'info>,
pub rent: Sysvar<'info, Rent>
}
#[derive(Accounts)]
pub struct MintNFT<'info> {
#[account(mut, signer)]
pub minter: AccountInfo<'info>,
pub nft_creater_program: AccountInfo<'info>,
#[account(mut)]
pub mint_pda_acc: AccountInfo<'info>,
pub rent: Sysvar<'info, Rent>
}
#[account]
pub struct NftCreator {
collection: Vec<Pubkey>,
price: u64
}
./tests/anchor_programs.ts
...
it('is minted', async () => {
let [mint_pda, _bump] = await anchor.web3.PublicKey.findProgramAddress( // Use findProgram Address to generate PDA
[Buffer.from(anchor.utils.bytes.utf8.encode("nft_creator"))],
program.programId
)
const tx = await program.rpc.mintnft({ // Call program mintnft instruction
accounts: { /**@ACCOUNTS */
// tokenProgram: TOKEN_PROGRAM_ID,
minter: initializerMainAccount.publicKey, // 1. minter as the initializer
// nftCreater: nftCreatorAcc.publicKey,
nftCreaterProgram: program.programId, // 2. this program id
mintPdaAcc: mint_pda, // 3. The mint_pda just generated
// mintPdaAcc: mint_pda.publicKey,
rent: anchor.web3.SYSVAR_RENT_PUBKEY, // 4. sysVar
},
signers: [initializerMainAccount]
});
console.log("Your transaction signature", tx);
});
});
或参考github repo
中的完整锚点项目代码
我意识到了这个问题:
- 我没有将 system_program 传递给指令。
pub system_program: Program<'info, System>
- 需要用invoke_signed也让pda签
invoke_signed(
&create_acc_ix,
&[
self.minter.clone(),
self.mint_pda_acc.clone(),
],
&[&[ &mint_seed.as_ref(), &[*bump_seed] ]]
)?;
我正在尝试创建一个让用户铸造 SPL 令牌的简单程序。 该程序由 Anchor 引导。不幸的是,它在通过 CPI 创建 PDA 帐户的第一步失败了。详情请见下方:
----处理器-----
我试图简化链上程序的处理器,使用 Solana 系统程序创建一个简单的 PDA 帐户。处理器只有一个CPI。
----说明-----
我还尝试通过只输入 4 个帐户来简化指令(请参见屏幕截图或随附的我的代码): 在打字稿测试代码中,它也很简单。 我只是导出一个 PDA,然后将这个 PDA 和其余 3 个帐户传递到指令中。 (两个约束1.分配签名者2.为PDA帐户设置mut)
-----错误-----
但我仍然得到错误
Transaction simulation failed: Error processing Instruction 0: An account required by the instruction is missing
Program 6KA5onmgQN7gsBZ5whPCTVL4EQcRob6vw7TYYNvik8xb invoke [1]
Program log: Instruction: Mintnft
Program log: First line in MintNFT processor
Instruction references an unknown account 11111111111111111111111111111111
Program 6KA5onmgQN7gsBZ5whPCTVL4EQcRob6vw7TYYNvik8xb consumed 15319 of 200000 compute units
Program 6KA5onmgQN7gsBZ5whPCTVL4EQcRob6vw7TYYNvik8xb failed: An account required by the instruction is missing
1) is minted
2 passing (2s)
1 failing
1) anchor_programs
is minted:
Error: failed to send transaction: Transaction simulation failed: Error processing Instruction 0: An account required by the instruction is missing
at Connection.sendEncodedTransaction (node_modules/@solana/web3.js/src/connection.ts:3961:13)
at processTicksAndRejections (internal/process/task_queues.js:97:5)
at Connection.sendRawTransaction (node_modules/@solana/web3.js/src/connection.ts:3918:20)
at sendAndConfirmRawTransaction (node_modules/@solana/web3.js/src/util/send-and-confirm-raw-transaction.ts:27:21)
at Provider.send (node_modules/@project-serum/anchor/src/provider.ts:118:18)
at Object.rpc [as mintnft] (node_modules/@project-serum/anchor/src/program/namespace/rpc.ts:25:23)
似乎我没有将正确的帐户传递到调用主体中,但我花了一整天的时间检查但仍然不确定是否还有其他丢失的帐户(或 AccountInfo)。 如果有人能给我提示,我将不胜感激。 您可以在屏幕截图格式中看到我的代码摘要。
.src/lib.rs
use anchor_lang::prelude::*;
use anchor_spl::token::Mint;
use solana_program::program::invoke;
use solana_program::system_instruction;
declare_id!("ArT6Hwus2hMwmNeNeJ2zGcQnvZsbrhz8vTbBdq35AdgG");
#[program]
pub mod anchor_programs {
use super::*;
pub fn initialize(ctx: Context<Initialize>, price: u64) -> ProgramResult {
ctx.accounts.nft_creator.price = price;
ctx.accounts.nft_creator.collection = vec![];
Ok(())
}
pub fn mintnft(ctx: Context<MintNFT>) -> ProgramResult {
msg!("First line in MintNFT processor");
let (mint_pda, _bump) = Pubkey::find_program_address( // Calc PDA address from passed in nft_creater_program_id
&[b"nft_creator"],
&ctx.accounts.nft_creater_program.key()
);
if mint_pda != ctx.accounts.mint_pda_acc.key() { // Confirm if passed in PDA address is the same
return Err(ProgramError::Custom(123))
}
let create_acc_ix = system_instruction::create_account( // Try create account using system_instruction
&ctx.accounts.minter.key(),
&ctx.accounts.mint_pda_acc.key(),
ctx.accounts.rent.minimum_balance(Mint::LEN),
Mint::LEN as u64,
&spl_token::ID,
);
invoke(&create_acc_ix, &[ // Use invoke to call cross program invocation
ctx.accounts.minter.clone(),
ctx.accounts.mint_pda_acc.clone(),
])?;
Ok(())
}
}
#[derive(Accounts)]
pub struct Initialize<'info> {
#[account(init, payer=initializer, space=500)]
pub nft_creator: Account<'info, NftCreator>,
#[account(mut, signer)]
pub initializer: AccountInfo<'info>,
pub system_program: AccountInfo<'info>,
pub rent: Sysvar<'info, Rent>
}
#[derive(Accounts)]
pub struct MintNFT<'info> {
#[account(mut, signer)]
pub minter: AccountInfo<'info>,
pub nft_creater_program: AccountInfo<'info>,
#[account(mut)]
pub mint_pda_acc: AccountInfo<'info>,
pub rent: Sysvar<'info, Rent>
}
#[account]
pub struct NftCreator {
collection: Vec<Pubkey>,
price: u64
}
./tests/anchor_programs.ts
...
it('is minted', async () => {
let [mint_pda, _bump] = await anchor.web3.PublicKey.findProgramAddress( // Use findProgram Address to generate PDA
[Buffer.from(anchor.utils.bytes.utf8.encode("nft_creator"))],
program.programId
)
const tx = await program.rpc.mintnft({ // Call program mintnft instruction
accounts: { /**@ACCOUNTS */
// tokenProgram: TOKEN_PROGRAM_ID,
minter: initializerMainAccount.publicKey, // 1. minter as the initializer
// nftCreater: nftCreatorAcc.publicKey,
nftCreaterProgram: program.programId, // 2. this program id
mintPdaAcc: mint_pda, // 3. The mint_pda just generated
// mintPdaAcc: mint_pda.publicKey,
rent: anchor.web3.SYSVAR_RENT_PUBKEY, // 4. sysVar
},
signers: [initializerMainAccount]
});
console.log("Your transaction signature", tx);
});
});
或参考github repo
中的完整锚点项目代码我意识到了这个问题:
- 我没有将 system_program 传递给指令。
pub system_program: Program<'info, System>
- 需要用invoke_signed也让pda签
invoke_signed(
&create_acc_ix,
&[
self.minter.clone(),
self.mint_pda_acc.clone(),
],
&[&[ &mint_seed.as_ref(), &[*bump_seed] ]]
)?;