1

I'm trying to store SOL in a PDA which can be taken out by an "owner" wallet and I've found there is two ways to initalize the PDA account for this:

    #[account(
        init,
        payer=owner,
        space=0,
        seeds = ["seed_prefix", ...],
        bump
    )]
    pub pda_account: AccountInfo<'info>,

or

    #[account(
        mut,
        seeds = ["seed_prefix", ...],
        bump
    )]
    pub pda_account: AccountInfo<'info>,

For the first one anchor does most the work via init by setting owner and paying rent. For the second method you can send 0 byte rent exemption to the account. What's interesting is I can't seem to do a SOL transfer with the first method using invoke_signed but I can with the second method. I resorted to using **pda_account.try_borrow_mut_lamports()? -= ... but that doesn't show up in solana transaction explorers as SOL transfers. With the first method the owner is the program and for the latter method the owner is default program (Is it possible this could be abused with seed collision?).

This is what I'm currently trying to do (Ive used the native solana_program transfer functions and they do the same thing):


    msg!("account owner: {:?}", pda_account.owner);

    // The seeds to the PDA account:
    let seeds = &["seed_prefix", ..., &[bump]];

    // Also tried program as signer but got error
    // let signer_seeds = &[&[&PROGRAM_SIGNER.as_ref() &[program_as_signer_bump]]]
    let signer_seeds = &[&seeds[..]];
    let tranfer_ctx = CpiContext::new_with_signer(
        ctx.accounts.system_program.to_account_info(), 
        Transfer {
            from: pda_account.to_account_info(),
            to: owner.to_account_info(),
        }, 
        signer_seeds
    );
    transfer(tranfer_ctx, amount)?;

When I use the PDA seeds as signer I get:

    'Program log: account owner: PROGRAM_ID',
    'Program 11111111111111111111111111111111 invoke [2]',
    'Program 11111111111111111111111111111111 failed: instruction spent from the balance of an account it does not own',
    'Program PROGRAM_ID consumed 31450 of 200000 compute units',
    'Program PROGRAM_ID failed: instruction spent from the balance of an account it does not own'

Even though the account owner says its the program id.

When I use the program as signer seeds I get the error

Cross-program invocation with unauthorized signer or writable account

1
  • I know Solana cookbook says use try_borrow_mut_lamports for PDAs but the explorers do a terrible job of reflecting those kind of lamport changes.
    – jac0xb.sol
    Oct 10, 2022 at 14:23

1 Answer 1

2

If the account has no data, you don't need to initialize it. Your program should be able to sign to transfer sol in and out of that account without it being initialized or having its program id changed.

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.