在 Solana Anchor 框架中初始化 PDA 的正确方法

Posted

技术标签:

【中文标题】在 Solana Anchor 框架中初始化 PDA 的正确方法【英文标题】:Proper way to initialize PDAs within the Solana Anchor framework 【发布时间】:2022-01-05 07:55:35 【问题描述】:

我正在尝试使用使用 PDA 的 Rust/Anchor 编写一个简单的 Solana 程序,但是当我尝试调用它时出现 CPI 错误,即使没有发生 CPI(可能是 PDA 帐户初始化?)。

这是程序代码:

use anchor_lang::prelude::*;

declare_id!("51v31qHaEQniLoYuvvtXByZcfiyvog3R2EKC39EPD52p");

#[program]
pub mod solana_sandbox 
  use super::*;
  pub fn initialize(ctx: Context<Initialize>, bump: u8) -> ProgramResult 
    ctx.accounts.sandbox_account.bump = bump;
    Ok(())
  


#[derive(Accounts)]
#[instruction(bump: u8)]
pub struct Initialize<'info> 
  #[account(mut)]
  pub signer: Signer<'info>,
  #[account(
    init,
    seeds = [b"seed".as_ref()],
    bump,
    payer = signer,
  )]
  pub sandbox_account: Account<'info, SandboxAccount>,
  pub system_program: Program<'info, System>,


#[account]
#[derive(Default)]
pub struct SandboxAccount 
  pub bump: u8,

这是客户端代码:

  const [sandboxPda, sandboxBump] = await PublicKey.findProgramAddress([Buffer.from('seed')], SystemProgram.programId);

  await program.rpc.initialize(
    sandboxBump,
    
      accounts: 
        signer: keypair.publicKey,
        sandboxAccount: sandboxPda,
        systemProgram: anchor.web3.SystemProgram.programId,
      ,
      signers: [keypair],
      instructions: []
    );

当我运行上述内容时,我得到以下信息:

Transaction simulation failed: Error processing Instruction 0: Cross-program invocation with unauthorized signer or writable account 
    Program 51v31qHaEQniLoYuvvtXByZcfiyvog3R2EKC39EPD52p invoke [1]
    8ZiyjNgnFFPyw39NyMQE5FGETTjyUhSHUVQG3oKAFZiU's signer privilege escalated
    Program 51v31qHaEQniLoYuvvtXByZcfiyvog3R2EKC39EPD52p consumed 200000 of 200000 compute units
    Program 51v31qHaEQniLoYuvvtXByZcfiyvog3R2EKC39EPD52p failed: Cross-program invocation with unauthorized signer or writable account

8ZiyjNgnFFPyw39NyMQE5FGETTjyUhSHUVQG3oKAFZiU是我传入的PDA地址,我用的是anchor-cli 0.18.0

【问题讨论】:

【参考方案1】:

原来我是使用系统程序 ID 来在我的客户端代码中派生 PDA,而不是使用我的实际程序 ID。

应该是:

  const [sandboxPda, sandboxBump] = await PublicKey.findProgramAddress([Buffer.from('seed')], <PROGRAM_ID>);

【讨论】:

以上是关于在 Solana Anchor 框架中初始化 PDA 的正确方法的主要内容,如果未能解决你的问题,请参考以下文章

Solana中利用Anchor自动解析TokenAccount

Solana Anchor:程序如何检查用户提供的已批准令牌配额?

Solana Anchor:如何为/读取关联帐户制作#[account(seeds)]?

使用 Anchor 时系统程序账号需要传入啥?

Solana中的托管合约

如何在 Serum Anchor 中签署代币交易