pub fn create_account(
from_pubkey: &Pubkey,
to_pubkey: &Pubkey,
lamports: u64,
space: u64,
owner: &Pubkey,
) -> Instruction
Expand description
Create an account.
This function produces an Instruction
which must be submitted in a
Transaction
or invoked to take effect, containing a serialized
SystemInstruction::CreateAccount
.
Account creation typically involves three steps: allocate
space,
transfer
lamports for rent, assign
to its owning program. The
create_account
function does all three at once.
§Required signers
The from_pubkey
and to_pubkey
signers must sign the transaction.
§Examples
These examples use a single invocation of
SystemInstruction::CreateAccount
to create a new account, allocate some
space, transfer it the minimum lamports for rent exemption, and assign it to
the system program,
§Example: client-side RPC
This example submits the instruction from an RPC client.
The payer
and new_account
are signers.
use solana_rpc_client::rpc_client::RpcClient;
use solana_sdk::{
pubkey::Pubkey,
signature::{Keypair, Signer},
system_instruction,
system_program,
transaction::Transaction,
};
use anyhow::Result;
fn create_account(
client: &RpcClient,
payer: &Keypair,
new_account: &Keypair,
space: u64,
) -> Result<()> {
let rent = client.get_minimum_balance_for_rent_exemption(space.try_into()?)?;
let instr = system_instruction::create_account(
&payer.pubkey(),
&new_account.pubkey(),
rent,
space,
&system_program::ID,
);
let blockhash = client.get_latest_blockhash()?;
let tx = Transaction::new_signed_with_payer(
&[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 instruction from an on-chain Solana program. The
created account is a program derived address. 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_program::{
account_info::{next_account_info, AccountInfo},
entrypoint,
entrypoint::ProgramResult,
msg,
program::invoke_signed,
pubkey::Pubkey,
system_instruction,
system_program,
sysvar::rent::Rent,
sysvar::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: &Pubkey,
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!(system_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(
&system_instruction::create_account(
payer.key,
new_account_pda.key,
rent,
instr.space,
&system_program::ID
),
&[payer.clone(), new_account_pda.clone()],
&[&[payer.key.as_ref(), new_account_seed, &[new_account_bump_seed]]],
)?;
Ok(())
}