2

Can someone point out what I'm doing wrong? I'm trying to transfer SOL from a PDA to the to_account but for some reason when I call it, fails with the following error message: Error processing Instruction 0: invalid program argument . According the solna cookbook (https://solanacookbook.com/references/accounts.html#how-to-sign-with-a-pda) it suppose to work, but I'm really not sure what I'm doing wrong. Thanks.

use solana_program::{
    account_info::next_account_info, account_info::AccountInfo, entrypoint,
    entrypoint::ProgramResult, program::invoke_signed, pubkey::Pubkey, system_instruction,
};
use solana_program::rent::Rent;
use solana_program::sysvar::Sysvar;

entrypoint!(process_instruction);

fn process_instruction(
    _program_id: &Pubkey,
    accounts: &[AccountInfo],
    _instruction_data: &[u8],
) -> ProgramResult {
    let account_info_iter = &mut accounts.iter();

    let _initializer = next_account_info(account_info_iter)?;
    let pda = next_account_info(account_info_iter)?;
    let to_account = next_account_info(account_info_iter)?;
    let system_program = next_account_info(account_info_iter)?;

    invoke_signed(
        &system_instruction::transfer(
            &pda.key,
            &to_account.key,
            100_000_000, // 0.1 SOL
        ),
        &[
            pda.clone(),
            to_account.clone(),
            system_program.clone(),
        ],
        &[&[b"wallet".as_ref(), &[255]]],
    )?;

    Ok(())
}

On the client side looks something like this:

const transaction = new Transaction().add(
  new TransactionInstruction({
    keys: [
      {pubkey: signer.publicKey, isSigner: true, isWritable: false},
      {pubkey: programDerivedAddress, isSigner: false, isWritable: true},
      {pubkey: toAddress, isSigner: false, isWritable: true},
      {pubkey: SystemProgram.programId, isSigner: false, isWritable: false}
    ],
    data: Buffer.from(new Uint8Array([])),
    programId: programId,
  })
);

await sendAndConfirmTransaction(
    connection,
    transaction,
    [signer],
);
1
  • The error can also be on how you build the instruction on the client, can you show us that piece of code?
    – nf0x
    Commented Jul 15, 2022 at 15:57

2 Answers 2

3

Solved my problem by using the try_borrow_mut_lamports function instead of the invoke_signed and &system_instruction::transfer.

fn process_instruction(
    _program_id: &Pubkey,
    accounts: &[AccountInfo],
    _instruction_data: &[u8],
) -> ProgramResult {
    let account_info_iter = &mut accounts.iter();

    let _initializer = next_account_info(account_info_iter)?;
    let pda = next_account_info(account_info_iter)?;
    let to_account = next_account_info(account_info_iter)?;
    let system_program = next_account_info(account_info_iter)?;

    **client_program_derived_account.try_borrow_mut_lamports()? -= 100_000_000;
    **to_account.try_borrow_mut_lamports()? += 100_000_000;

    Ok(())
}

But would be nice to know why invoke_signed and &system_instruction::transfer doesn't work in my case.

3
  • 2
    took a look at the actual code that handles system_instruction::transfer and where that error comes from github.com/solana-labs/solana/blob/… looks like there's a check to make sure the from(pda account in your rust code) doesn't have any data. it looks like this check was introduced for protecting nonce accounts according to these prs/commits github.com/solana-labs/solana/pull/7645 github.com/solana-labs/solana/pull/7645/commits/…
    – Ricky Chen
    Commented Jul 16, 2022 at 17:18
  • are you initializing the pda somewhere?
    – Ricky Chen
    Commented Jul 16, 2022 at 17:19
  • 1
    also in your invoked_signed there's no guarantee that the bump seed for the pda is going to be 255. pdas are found using the provided seeds ("wallet") and a bump seed that results in a publickey address that falls off the curve. the calculation will start at 255 but it could potentially be 254, 253, ... etc. whichever is the first the cause the publickey address to call off the curve. (mult bump_seeds can be valid but usually the highest one is used aka the "canonical" bump seed) solanacookbook.com/core-concepts/pdas.html#facts
    – Ricky Chen
    Commented Jul 16, 2022 at 17:25
0

assuming the rest of your rust code matches the solanacookbook example, I think you need to add the instruction_data: &[u8] parameter to execute_transaction() even if you're not going to do anything with it.

1
  • You are right, even when I added the instruction_data to my function, I got the same error.
    – David
    Commented Jul 15, 2022 at 17:29

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.