1

I probably am doing something really stupid but this basic thing doesn't seem to work for me for this scenario. I checked the other questions similar to this one but they are either different scenarios or their answers didn't help me.

I have these instruction accounts:

#[derive(Accounts)]
pub struct CreateProfile<'info> {
    pub state: Account<'info, State>,

    #[account(
        init,
        payer = user, 
        space = 60,
        seeds = [state.to_account_info().key.as_ref(), user.key.as_ref()],
        bump,
    )]
    pub user_profile: Account<'info, UserProfile>,

    #[account(mut)]
    pub user: Signer<'info>,
    pub system_program: Program<'info, System>,
}

The actual create_profile() function is empty, i.e. Ok(()). When running a test against it, it fails with:

Program Fg6PaFpoGXkYsidMpWTK6W2BeZ7FEfcYkg476zPFsLnS invoke [1]
Program log: Instruction: CreateProfile
HCrVyydLF9CgiqeQNxq9dyxUswJF7KkYGurFcj2E7gfh's signer privilege escalated
Program Fg6PaFpoGXkYsidMpWTK6W2BeZ7FEfcYkg476zPFsLnS consumed 7512 of 200000 compute units
Program Fg6PaFpoGXkYsidMpWTK6W2BeZ7FEfcYkg476zPFsLnS failed: Cross-program invocation with unauthorized signer or writable account

The only CPI call is the one Anchor does to create the account, due to init constraint. I know that to create an account, you'll need two signers: the payer and the new account itself. I am not quite sure what happens when the latter is a PDA.

This is the code that is testing it:

// omitted: state initialised in an earlier transaction

const userA = Keypair.generate();

// omitted: airdop for userA

const [pdaA] = await PublicKey.findProgramAddress(
  [state.publicKey.toBytes(), userA.publicKey.toBytes()],
  program.programId
);

await program.methods
  .create_profile()
  .accounts({
    state: state.publicKey,
    user_profile: pdaA,
    user: userA.publicKey,
  })
  .signers([userA])
  .rpc({ skipPreflight: true });

From the code above, it doesn't look like I am sending in the wrong seeds neither.

1
  • I even changed the seed to be just a static text in both the program and unit test but no dice.
    – sohrab
    Commented Aug 7, 2022 at 1:04

1 Answer 1

2

The signer privilege escalated error tells us that your instruction is making a CPI but the signer it receives is not what it expects.

In this particular instance what's happening is that a CPI is being made to the System Program to create your user_profile account. Every account signs its own creation so that tells us that the signer we're concerned with in this case is user_profile. The user_profile you generate on your client side does not match what the anchor program generates and expects.

Do this instead:

#[derive(Accounts)]
pub struct CreateProfile<'info> {
    ...
    #[account(
        init,
        payer = user, 
        space = 60,
        seeds = [state.key().as_ref(), user.key().as_ref()],
        bump,
    )]
    pub user_profile: Account<'info, UserProfile>,
    ...
}

and in your client:

const [pdaA, _] = await PublicKey.findProgramAddress(
  [state.publicKey.toBuffer(), userA.publicKey.toBuffer()],
  program.programId
);

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.