CPIs sem signatários PDA

Resumo

Use invoke para CPIs onde todos os signatários necessários já assinaram a transação original. Não é necessária assinatura PDA. Os privilégios de signatário e escrita estendem-se do chamador para o chamado.

CPIs sem signatários PDA

Quando uma CPI não requer signatários PDA, a função invoke é usada. A função invoke chama a função invoke_signed com um array signers_seeds vazio. O array de signatários vazio indica que não são necessários PDAs para assinatura.

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

Os exemplos abaixo fazem uma CPI usando Anchor e Rust nativo. Inclui uma única instrução que transfere SOL de uma conta para outra.

Anchor

Os exemplos seguintes mostram duas abordagens para implementar CPIs num programa Anchor. Os exemplos são funcionalmente equivalentes, mas demonstram diferentes níveis de abstração.

  • Exemplo 1: Usa CpiContext e função auxiliar do Anchor.
  • Exemplo 2: Usa a função system_instruction::transfer da crate solana_program.
  • Exemplo 3: Constrói a instrução CPI manualmente. Esta abordagem é útil quando não existe uma crate para ajudar a construir a instrução que deseja invocar.
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

O exemplo seguinte mostra como fazer uma CPI a partir de um programa escrito em Rust nativo. Inclui uma única instrução que transfere SOL de uma conta para outra. (O ficheiro de teste usa LiteSVM para testar o programa.)

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?

Índice

Editar Página

Gerenciado por

© 2026 Fundação Solana.
Todos os direitos reservados.
Conecte-se
  • Blog