Skip to main content

transfer

Function transfer 

Source
pub fn transfer(
    from_address: &Address,
    to_address: &Address,
    lamports: u64,
) -> Instruction
Available on crate features bincode or wincode only.
Expand description

Transfer lamports from an account owned by the system program.

This function produces an Instruction which must be submitted in a Transaction or invoked to take effect, containing a serialized SystemInstruction::Transfer.

§Required signers

The from_address signer must sign the transaction.

§Examples

These examples allocate space for an account, transfer it the minimum balance for rent exemption, and assign the account to a program.

§Example: client-side RPC

This example submits the instructions from an RPC client. It assigns the account to a provided program account. The payer and new_account are signers.

use solana_rpc_client::rpc_client::RpcClient;
use solana_address::Address;
use solana_keypair::Keypair;
use solana_signer::Signer;
use solana_system_interface::instruction;
use solana_transaction::Transaction;
use anyhow::Result;

fn create_account(
    client: &RpcClient,
    payer: &Keypair,
    new_account: &Keypair,
    owning_program: &Address,
    space: u64,
) -> Result<()> {
    let rent = client.get_minimum_balance_for_rent_exemption(space.try_into()?)?;

    let transfer_instr = instruction::transfer(
        &payer.pubkey(),
        &new_account.pubkey(),
        rent,
    );

    let allocate_instr = instruction::allocate(
        &new_account.pubkey(),
        space,
    );

    let assign_instr = instruction::assign(
        &new_account.pubkey(),
        owning_program,
    );

    let blockhash = client.get_latest_blockhash()?;
    let tx = Transaction::new_signed_with_payer(
        &[transfer_instr, allocate_instr, assign_instr],
        Some(&payer.pubkey()),
        &[payer, new_account],
        blockhash,
    );

    let _sig = client.send_and_confirm_transaction(&tx)?;

    Ok(())
}

§Example: on-chain program

This example submits the instructions from an on-chain Solana program. The created account is a program derived address, funded by payer, and assigned to the running program. The payer and new_account_pda are signers, with new_account_pda being signed for virtually by the program itself via invoke_signed, payer being signed for by the client that submitted the transaction.

use solana_account_info::{next_account_info, AccountInfo};
use solana_cpi::invoke_signed;
use solana_program_entrypoint::entrypoint;
use solana_program_error::ProgramResult;
use solana_address::Address;
use solana_system_interface::{instruction, program};
use solana_sysvar::{rent::Rent, Sysvar};

#[derive(BorshSerialize, BorshDeserialize, Debug)]
pub struct CreateAccountInstruction {
    /// The PDA seed used to distinguish the new account from other PDAs
    pub new_account_seed: [u8; 16],
    /// The PDA bump seed
    pub new_account_bump_seed: u8,
    /// The amount of space to allocate for `new_account_pda`
    pub space: u64,
}

entrypoint!(process_instruction);

fn process_instruction(
    program_id: &Address,
    accounts: &[AccountInfo],
    instruction_data: &[u8],
) -> ProgramResult {
    let instr = CreateAccountInstruction::deserialize(&mut &instruction_data[..])?;

    let account_info_iter = &mut accounts.iter();

    let payer = next_account_info(account_info_iter)?;
    let new_account_pda = next_account_info(account_info_iter)?;
    let system_account = next_account_info(account_info_iter)?;

    assert!(payer.is_signer);
    assert!(payer.is_writable);
    // Note that `new_account_pda` is not a signer yet.
    // This program will sign for it via `invoke_signed`.
    assert!(!new_account_pda.is_signer);
    assert!(new_account_pda.is_writable);
    assert!(program::check_id(system_account.key));

    let new_account_seed = &instr.new_account_seed;
    let new_account_bump_seed = instr.new_account_bump_seed;

    let rent = Rent::get()?
        .minimum_balance(instr.space.try_into().expect("overflow"));

    invoke_signed(
        &instruction::create_account(
            payer.key,
            new_account_pda.key,
            rent,
            instr.space,
            &program::ID
        ),
        &[payer.clone(), new_account_pda.clone()],
        &[&[
            payer.key.as_ref(),
            new_account_seed,
            &[new_account_bump_seed],
        ]],
    )?;

    Ok(())
}