In the code reproduced below from this link we have client code creating and sending instruction to create a new account:

describe("Create a system account", async () => {

    const connection = new Connection(`http://localhost:8899`, 'confirmed');
    const payer = createKeypairFromFile(require('os').homedir() + '/.config/solana/id.json');
    const program = createKeypairFromFile('./program/target/so/program-keypair.json');
    it("Create the account", async () => {

        const newKeypair = Keypair.generate();

        let ix = new TransactionInstruction({
            keys: [
                {pubkey: payer.publicKey, isSigner: true, isWritable: true},
                {pubkey: newKeypair.publicKey, isSigner: true, isWritable: true},
                {pubkey: SystemProgram.programId, isSigner: false, isWritable: false}
            programId: program.publicKey,
            data: Buffer.alloc(0),

        await sendAndConfirmTransaction(
            new Transaction().add(ix),
            [payer, newKeypair]

here the new account to be created is represented by the public key newKeypair.publicKey.

The Solana program that process the instruction, which can be found via this link looks thus:

fn process_instruction(
    _program_id: &Pubkey,
    accounts: &[AccountInfo],
    _instruction_data: &[u8],
) -> ProgramResult {

    let accounts_iter = &mut accounts.iter();
    let payer = next_account_info(accounts_iter)?;
    let new_account = next_account_info(accounts_iter)?;
    let system_program = next_account_info(accounts_iter)?;
    msg!("Program invoked. Creating a system account...");
    msg!("  New public key will be: {}", &new_account.key.to_string());
            &payer.key,             // From pubkey
            &new_account.key,       // To pubkey
            1 * LAMPORTS_PER_SOL,   // Lamports (1 SOL)
            0,                      // Space
            &system_program::ID,    // Owner
            payer.clone(), new_account.clone(), system_program.clone()  // Accounts involved

    msg!("Account created succesfully.");

I understand when calling Solana programs we pass in, the accounts that the run time should retrieve that will be needed for executing the instructions. In the case above, where we are including an account that does not exist (the instruction we are passing in, is actually for it to be created) how then does the Solana program load a non-existing account?

Specifically this line:

let new_account = next_account_info(accounts_iter)?;

Why does not not error since the program does not exist until the &system_instruction::create_account call is invoked?

1 Answer 1


If I understood your question correctly, you are asking how newKeypair is used to create an account where you are referring to newKeypair as a non-existing account. Here you got it wrong, newKeypair is not an account it is just a public and secret key pair that is generated randomly and the instruction creates a new account whose owner(Assigned Program ID) is System Program and newKeypair's public key is used to set the newly created account's public key. Same instruction is also available in Solana Web3 SDK you can check this.

  • I was actually referring to new_account in the Solana program side. If the account does not exist, how come the run time was able to find and load it. I now have the answer to this. And that is, the Solana runtime can load any account (since technically the account is basically a public key) the only difference is that, account can either have been initialised or not. An account that has not being initialised (or said in another way, an account that has not being created yet) will have its lamport set to 0
    – dade
    Commented Sep 11, 2022 at 9:12

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.