CPI tanpa penanda tangan PDA

Ringkasan

Gunakan invoke untuk CPI di mana semua penanda tangan yang diperlukan telah menandatangani transaksi asli. Tidak diperlukan penandatanganan PDA. Hak istimewa penanda tangan dan writable diperluas dari pemanggil ke yang dipanggil.

CPI tanpa penanda tangan PDA

Ketika CPI tidak memerlukan penanda tangan PDA, fungsi invoke digunakan. Fungsi invoke memanggil fungsi invoke_signed dengan array signers_seeds kosong. Array penanda tangan kosong menunjukkan bahwa tidak ada PDA yang diperlukan untuk penandatanganan.

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

Contoh di bawah ini membuat CPI menggunakan Anchor dan Native Rust. Ini mencakup satu instruksi yang mentransfer SOL dari satu akun ke akun lain.

Anchor

Contoh berikut menunjukkan dua pendekatan untuk mengimplementasikan CPI dalam program Anchor. Contoh-contoh ini secara fungsional setara, tetapi mendemonstrasikan tingkat abstraksi yang berbeda.

  • Contoh 1: Menggunakan CpiContext dan fungsi helper Anchor.
  • Contoh 2: Menggunakan fungsi system_instruction::transfer dari crate solana_program.
  • Contoh 3: Membangun instruksi CPI secara manual. Pendekatan ini berguna ketika tidak ada crate yang membantu membangun instruksi yang ingin Anda invoke.
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

Contoh berikut menunjukkan cara membuat CPI dari program yang ditulis dalam Native Rust. Ini mencakup satu instruksi yang mentransfer SOL dari satu akun ke akun lain. (File test menggunakan LiteSVM untuk menguji program.)

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?

Daftar Isi

Edit Halaman

Dikelola oleh

© 2026 Yayasan Solana.
Semua hak dilindungi.
Terhubung