Donut
Donut

Reputation: 217

Solana: Create PDA account on chain

I am trying to write a Solana program which creates a PDA account for me on-chain. I can't get it to work and tbh, no idea what I am doing wrong :/

I have the following code in my Solana program:

        let account_info_iter = &mut accounts.iter();
        let initializer = next_account_info(account_info_iter)?;

        if !initializer.is_signer {
            return Err(ProgramError::MissingRequiredSignature);
        }

        let (pda, bump_seed) = Pubkey::find_program_address(&[b"admin_account"], program_id);
        let admin_account = next_account_info(account_info_iter)?;

        
        if admin_account.key != &pda {
            return Err(CustomError::InvalidAdminAccount.into());
        }

        // we are checking if the account is rent exempt. In case it is, the account is already initialized
        if **admin_account.try_borrow_lamports()? > 0 {
            msg!("This account is already initialised. skipping");
            return Ok(())
        }

        let lamports = Rent::default().minimum_balance(1);

        let ix = solana_program::system_instruction::create_account(
            initializer.key,
            admin_account.key,
            lamports,
            1,
            program_id,
        );

        // Sign and submit transaction
        invoke_signed(
            &ix,
            &[initializer.clone(), admin_account.clone()],
            &[&[b"admin_account"], &[&[bump_seed]]]
        )?;

And here my Python script:


    pda_account, nonce = PublicKey.find_program_address([b"admin_account"], PROGRAM_ID)
    
    init_ix = TransactionInstruction(
        data=bytes(1),
        keys=[
            AccountMeta(pubkey=ADMIN_KEYPAIR.public_key, is_signer=True, is_writable=False),
            AccountMeta(pubkey=pda_account, is_signer=False, is_writable=True),
        ],
        program_id=PROGRAM_ID,
    )

    transaction = Transaction()
    transaction.add(init_pantos_token_ix)

    utils.send_and_confirm_tx(CLIENT, transaction, ADMIN_KEYPAIR)

Whenever I execute the transaction I get the following error message:

Transaction simulation failed: Error processing Instruction 0: An account required by the instruction is missing

But what account is missing? I tried with the System Program but that gives me another error :/ Anyone any ideas?

Upvotes: 1

Views: 1431

Answers (1)

Jon C
Jon C

Reputation: 8402

You do need to pass in the system program at the top-level, and then it's optional to pass into invoke_signed. So your python script should do:

    init_ix = TransactionInstruction(
        data=bytes(1),
        keys=[
            AccountMeta(pubkey=ADMIN_KEYPAIR.public_key, is_signer=True, is_writable=True),
            AccountMeta(pubkey=pda_account, is_signer=False, is_writable=True),
            AccountMeta(pubkey=solana.system_program.SYS_PROGRAM_ID, is_signer=False, is_writable=False)
        ],
        program_id=PROGRAM_ID,
    )

Note that your ADMIN_KEYPAIR will also need to be writable in order to move lamports from it to the pda account. With just these changes on the client-side, it should work.

Upvotes: 1

Related Questions