pub fn assign(pubkey: &Pubkey, owner: &Pubkey) -> Instruction
Expand description
Assign ownership of an account from the system program.
This function produces an Instruction
which must be submitted in a
Transaction
or invoked to take effect, containing a serialized
SystemInstruction::Assign
.
§Required signers
The pubkey
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_sdk::{
pubkey::Pubkey,
signature::{Keypair, Signer},
system_instruction,
transaction::Transaction,
};
use anyhow::Result;
fn create_account(
client: &RpcClient,
payer: &Keypair,
new_account: &Keypair,
owning_program: &Pubkey,
space: u64,
) -> Result<()> {
let rent = client.get_minimum_balance_for_rent_exemption(space.try_into()?)?;
let transfer_instr = system_instruction::transfer(
&payer.pubkey(),
&new_account.pubkey(),
rent,
);
let allocate_instr = system_instruction::allocate(
&new_account.pubkey(),
space,
);
let assign_instr = system_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_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::transfer(
payer.key,
new_account_pda.key,
rent,
),
&[payer.clone(), new_account_pda.clone()],
&[&[payer.key.as_ref(), new_account_seed, &[new_account_bump_seed]]],
)?;
invoke_signed(
&system_instruction::allocate(
new_account_pda.key,
instr.space,
),
&[new_account_pda.clone()],
&[&[payer.key.as_ref(), new_account_seed, &[new_account_bump_seed]]],
)?;
invoke_signed(
&system_instruction::assign(
new_account_pda.key,
&program_id,
),
&[new_account_pda.clone()],
&[&[payer.key.as_ref(), new_account_seed, &[new_account_bump_seed]]],
)?;
Ok(())
}