2

I am developing a set of services for a cryptocurrency exchange on Solana and I've encountered an issue when trying to create a PDA (Program Derived Address) account within my smart contract.

Here's the structure and function in question:

impl SeedsData {
    pub fn new(seed: [u8; 8], bump_seed: u8) -> Self {
        SeedsData {
            seed,
            bump_seed: [bump_seed],
        }
    }

    #[inline(always)]
    pub fn get_seed(&self) -> &[u8] {
        let mut length = 0;
        while length < self.seed.len() && self.seed[length] > 0 {
            length += 1;
        }
        &self.seed[0..length]
    }
}

pub fn new_account<'a>(
    program_id: &Pubkey,
    base_acc: &AccountInfo<'a>,
    funding_acc: &AccountInfo<'a>,
    new_acc: &AccountInfo<'a>,
    create_acc_size: usize,
    lamports: u64,
    seeds_data: &SeedsData,
) -> u32 {
    let seed : &[u8] = &seeds_data.get_seed();
    let seeds : &[&[u8]] = &[seed, base_acc.key.as_ref(), &seeds_data.bump_seed];
    let expected_pda = Pubkey::create_program_address(seeds, program_id).unwrap();
    if new_acc.key != &expected_pda {
        return 1;
    }
    if !(new_acc.lamports() == 0 || new_acc.data.borrow().is_empty()){
        return 2;
    }
    invoke_signed(
        &system_instruction::create_account(
            &funding_acc.key,
            &new_acc.key,
            lamports,
            create_acc_size as u64,
            &program_id,
        ),
        &[new_acc.clone(), funding_acc.clone(), base_acc.clone()],
        &[seeds, &[funding_acc.key.as_ref()]]
    ).unwrap();
    return 0;

The goal is to create a PDA new_acc (not writable, not signer) account and pay commission for the creation from funding_acc (isWritable, isSigner), which definitely has sufficient funds.

My suspicion is that I might be incorrectly passing parameters here:

&[new_acc.clone(), funding_acc.clone(), base_acc.clone()],
&[seeds, &[funding_acc.key.as_ref()]]

If I were to use funding_acc to generate the seed and passed only its seeds, everything works fine. In other words, the basic example where a PDA is created based on the same account that pays the fee works. However, it fails when I try to pay the fee as if "on behalf of the base account".

In the current configuration, I receive the following error:

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

Any insights on what might be going wrong or how to correctly pass the parameters for this scenario would be greatly appreciated...

What I've tried:

  • Adjusted Account and Seed Order in invoke_signed:

    • Tried various orders of accounts [new_acc.clone(), funding_acc.clone(), base_acc.clone()] and the corresponding seeds to align with the smart contract's expectations.
  • Reviewed Seed Usage for PDA:

    • Ensured that the seeds used for PDA generation ([seed, base_acc.key.as_ref(), &seeds_data.bump_seed]) matched those in invoke_signed.
  • Verified new_acc State:

    • Checked that new_acc was not initialized prior to invoke_signed call.
  • Experimented with Seed Array Configurations:

    • Modified the structure of seed arrays in invoke_signed, separating and combining different seed elements.
  • Explored Various Account Orders:

    • Rearranged the account order in invoke_signed to test different configurations.

1 Answer 1

2

Based on the error, there is an account missing. Did you pass the system account in at the top level for creating the new account?

You need to pass in the system account, not the seed account for the the third account in your invoke_signed accounts array, and the payer should come before the new account. &[new_acc.clone(), funding_acc.clone(), base_acc.clone()] -> &[ funding_acc.clone(),new_acc.clone(), system_program.clone()] Add system_program AccountInfo to your parameters.

You don't need to pass in anything in the signer_sees for your funding account, since it is a signer for the top level instruction. &[seeds, &[funding_acc.key.as_ref()]] -> &[seeds]

1
  • Thank you very much for your help! Your suggestion to include the system account (system_program) in the transaction and adjust the order of the accounts was exactly what I needed. After making these changes, the transaction was successful. Your advice was invaluable, and I greatly appreciate your assistance! Jan 19 at 14:26

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.