2

My intent here is to have account that can store data to be used by program. I will be passing this account in every call I make to my onchain program. And if I try to call allocate from onchain, then it's results in <pda-address>'s writable permission escalated

It seems that having an PDA is good idea for this as only my program will be able to make use of it. But I am not sure how do I do it exactly. This is what I tried so far

  • derive an PDA in front-end side
  • Pass it as other normal account
  • Program treat first AccountInfo received as PDA and use it to store data

Error with above approach:

  • I need to allocate space to store data in PDA. But since PDA do not have Secret Key and for that reason no KeyPair, I can't call calls like allocateSpace.

What am I missing here? I am new to solana so I might have missed even a simplest thing.

Client side

const deposit_instruction = new solana.TransactionInstruction({
        keys: [
            { pubkey: system_account, isSigner: false, isWriteable: false },
            { pubkey: payer.publicKey, isSigner: true, isWritable: true },
            { pubkey: pdaAccount, isSigner: false, isWriteable: false },
            { pubkey: sender.publicKey, isSigner: true, isWriteable: true },
            { pubkey: receiver, isSigner: false, isWriteable: false },
        ],
        programId: programId,
        data: argument_ser,
    });

    return await callEntryPoint(deposit_instruction, [sender, payer]);

Onchain program

 let instruction = system_instruction::allocate(pda_account.key, 100u64);

        invoke_signed(
            &instruction,
            &[pda_account.clone(), system_account.clone()],
            &[&[SEED], &[&[bump]]],
        )?;
TylerH
  • 20,799
  • 66
  • 75
  • 101
Sudip Ghimire
  • 677
  • 6
  • 15

3 Answers3

1

Coming back to this question (might be helpful for future readers),

There was nothing wrong in the way I structured flow. The problem was that I misspelled isWriteable it is supposed to be isWritable

It took me whole day to figure that out

Sudip Ghimire
  • 677
  • 6
  • 15
0

Use PublicKey.findProgramAddress to get a program key and bump value. Send that to the instruction in your program. Then within your program invoke the system_instruction::create_account to create the PDA with storage (up to 10k).

Frank C.
  • 7,758
  • 4
  • 35
  • 45
  • Thank you for help Frank. Question tho. Can't I `create_account` PDA from js? and also why shall I need to pass bump value? – Sudip Ghimire Mar 27 '22 at 12:55
  • you need the bump value if you are creating the account in your program. – Frank C. Mar 29 '22 at 12:07
  • Ohh thank you. But when I call `system_instruction::allocate` and pass SEED & Bump value in seed and `pda_account`, `system_account` in account_infos, it says: `'s permission escalated`. What I might be missing? – Sudip Ghimire Mar 29 '22 at 13:34
0
  1. Make sure you derived that PDA from your on-chain program.

  2. In the on-chain program use invoked_signed instead of invoked to system_program.

Since that's PDA derived from your program, only your program can sign that PDA.

batphonghan
  • 487
  • 3
  • 10