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.
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
CpiContextdan fungsi helper Anchor. - Contoh 2: Menggunakan fungsi
system_instruction::transferdari cratesolana_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 entrypointentrypoint!(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 datalet instruction = ProgramInstruction::unpack(instruction_data)?;// Process instructionmatch instruction {ProgramInstruction::SolTransfer { amount } => {// Parse accountslet [sender_info, recipient_info, system_program_info] = accounts else {return Err(ProgramError::NotEnoughAccountKeys);};// Verify the sender is a signerif !sender_info.is_signer {return Err(ProgramError::MissingRequiredSignature);}// Create and invoke the transfer instructionlet 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?