CPI's zonder PDA-ondertekenaars

Samenvatting

Gebruik invoke voor CPI's waarbij alle vereiste ondertekenaars de oorspronkelijke transactie al hebben ondertekend. Er is geen PDA-ondertekening nodig. Ondertekenaar- en schrijfrechten worden uitgebreid van de aanroeper naar de aangeroepene.

CPI's zonder PDA-ondertekenaars

Wanneer een CPI geen PDA-ondertekenaars vereist, wordt de invoke functie gebruikt. De invoke functie roept de invoke_signed functie aan met een lege signers_seeds array. De lege ondertekenaars-array geeft aan dat er geen PDA's vereist zijn voor ondertekening.

Invoke function
pub fn invoke(instruction: &Instruction, account_infos: &[AccountInfo]) -> ProgramResult {
invoke_signed(instruction, account_infos, &[])
}

De onderstaande voorbeelden maken een CPI met Anchor en Native Rust. Het bevat een enkele instructie die SOL overdraagt van het ene account naar het andere.

Anchor

De volgende voorbeelden tonen twee benaderingen voor het implementeren van CPI's in een Anchor programma. De voorbeelden zijn functioneel equivalent, maar demonstreren verschillende abstractieniveaus.

  • Voorbeeld 1: Gebruikt Anchor's CpiContext en helperfunctie.
  • Voorbeeld 2: Gebruikt de system_instruction::transfer functie uit de solana_program crate.
  • Voorbeeld 3: Construeert de CPI-instructie handmatig. Deze benadering is nuttig wanneer er geen crate bestaat om de instructie te helpen bouwen die je wilt aanroepen.
use anchor_lang::prelude::*;
use anchor_lang::system_program::{transfer, Transfer};
declare_id!("9AvUNHjxscdkiKQ8tUn12QCMXtcnbR9BVGq3ULNzFMRi");
#[program]
pub mod cpi {
use super::*;
pub fn sol_transfer(ctx: Context<SolTransfer>, amount: u64) -> Result<()> {
let from_pubkey = ctx.accounts.sender.to_account_info();
let to_pubkey = ctx.accounts.recipient.to_account_info();
let program_id = ctx.accounts.system_program.to_account_info();
let cpi_context = CpiContext::new(
program_id,
Transfer {
from: from_pubkey,
to: to_pubkey,
},
);
transfer(cpi_context, amount)?;
Ok(())
}
}
#[derive(Accounts)]
pub struct SolTransfer<'info> {
#[account(mut)]
sender: Signer<'info>,
#[account(mut)]
recipient: SystemAccount<'info>,
system_program: Program<'info, System>,
}

Rust

Het volgende voorbeeld toont hoe een CPI te maken vanuit een programma geschreven in Native Rust. Het bevat een enkele instructie die SOL overdraagt van het ene account naar het andere. (Het testbestand gebruikt LiteSVM om het programma te testen.)

use borsh::BorshDeserialize;
use solana_program::{
account_info::AccountInfo,
entrypoint,
entrypoint::ProgramResult,
program::invoke,
program_error::ProgramError,
pubkey::Pubkey,
system_instruction,
};
// Declare program entrypoint
entrypoint!(process_instruction);
// Define program instructions
#[derive(BorshDeserialize)]
enum ProgramInstruction {
SolTransfer { amount: u64 },
}
impl ProgramInstruction {
fn unpack(input: &[u8]) -> Result<Self, ProgramError> {
Self::try_from_slice(input).map_err(|_| ProgramError::InvalidInstructionData)
}
}
pub fn process_instruction(
_program_id: &Pubkey,
accounts: &[AccountInfo],
instruction_data: &[u8],
) -> ProgramResult {
// Deserialize instruction data
let instruction = ProgramInstruction::unpack(instruction_data)?;
// Process instruction
match instruction {
ProgramInstruction::SolTransfer { amount } => {
// Parse accounts
let [sender_info, recipient_info, system_program_info] = accounts else {
return Err(ProgramError::NotEnoughAccountKeys);
};
// Verify the sender is a signer
if !sender_info.is_signer {
return Err(ProgramError::MissingRequiredSignature);
}
// Create and invoke the transfer instruction
let transfer_ix = system_instruction::transfer(
sender_info.key,
recipient_info.key,
amount,
);
invoke(
&transfer_ix,
&[
sender_info.clone(),
recipient_info.clone(),
system_program_info.clone(),
],
)?;
Ok(())
}
}
}

Is this page helpful?

Inhoudsopgave

Pagina Bewerken

Beheerd door

© 2026 Solana Foundation.
Alle rechten voorbehouden.
Blijf Verbonden