CPIs χωρίς υπογράφοντες PDA

Περίληψη

Χρησιμοποιήστε το invoke για CPIs όπου όλοι οι απαιτούμενοι υπογράφοντες έχουν ήδη υπογράψει την αρχική συναλλαγή. Δεν χρειάζεται υπογραφή PDA. Τα δικαιώματα υπογραφής και εγγραφής επεκτείνονται από τον καλούντα στον καλούμενο.

CPIs χωρίς υπογράφοντες PDA

Όταν ένα CPI δεν απαιτεί υπογράφοντες PDA, χρησιμοποιείται η συνάρτηση invoke. Η συνάρτηση invoke καλεί τη συνάρτηση invoke_signed με έναν κενό πίνακα signers_seeds. Ο κενός πίνακας υπογραφόντων υποδεικνύει ότι δεν απαιτούνται PDAs για υπογραφή.

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

Τα παρακάτω παραδείγματα πραγματοποιούν ένα CPI χρησιμοποιώντας Anchor και Native Rust. Περιλαμβάνει μία μόνο εντολή που μεταφέρει SOL από έναν λογαριασμό σε έναν άλλο.

Anchor

Τα ακόλουθα παραδείγματα δείχνουν δύο προσεγγίσεις για την υλοποίηση CPIs σε ένα πρόγραμμα Anchor. Τα παραδείγματα είναι λειτουργικά ισοδύναμα, αλλά επιδεικνύουν διαφορετικά επίπεδα αφαίρεσης.

  • Παράδειγμα 1: Χρησιμοποιεί το CpiContext του Anchor και βοηθητική συνάρτηση.
  • Παράδειγμα 2: Χρησιμοποιεί τη συνάρτηση system_instruction::transfer από το crate solana_program.
  • Παράδειγμα 3: Κατασκευάζει την εντολή CPI χειροκίνητα. Αυτή η προσέγγιση είναι χρήσιμη όταν δεν υπάρχει crate για να βοηθήσει στην κατασκευή της εντολής που θέλετε να καλέσετε.
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

Το ακόλουθο παράδειγμα δείχνει πώς να πραγματοποιήσετε ένα CPI από ένα πρόγραμμα γραμμένο σε Native Rust. Περιλαμβάνει μία μόνο εντολή που μεταφέρει SOL από έναν λογαριασμό σε έναν άλλο. (Το αρχείο δοκιμών χρησιμοποιεί το LiteSVM για να δοκιμάσει το πρόγραμμα.)

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?

Πίνακας Περιεχομένων

Επεξεργασία Σελίδας

Διαχειρίζεται από

© 2026 Ίδρυμα Solana.
Με επιφύλαξη παντός δικαιώματος.
Συνδεθείτε