0

I'm working on a Solana program using the Anchor framework. The program implements a simple counter that can be incremented or decremented by a user. The program compiles and deploys successfully, but when I call the increaseCounter or decreaseCounter functions from the frontend, I encounter the following error:

Transaction simulation failed: Error processing Instruction with unauthorized signer or writable account

Source Code: Github

#[program]
pub mod counter {
    use super::*;

    pub fn increase_counter(mut ctx: Context<ManageCounter>, step: u64) -> Result<()> {
        if ctx.accounts.counter.to_account_info().data_is_empty() {
            initialize_counter(&mut ctx)?;
        }

        let counter = &mut ctx.accounts.counter;

        msg!("Increasing counter by {}...", step);
        counter.count += step;
        msg!("Counter successfully increased. New value: {}", counter.count);

        Ok(())
    }

    pub fn decrease_counter(mut ctx: Context<ManageCounter>, step: u64) -> Result<()> {
        if ctx.accounts.counter.to_account_info().data_is_empty() {
            initialize_counter(&mut ctx)?;
        }

        let counter = &mut ctx.accounts.counter;

        if counter.count >= step {
            msg!("Decreasing counter by {}...", step);
            counter.count -= step;
            msg!("Counter successfully decreased. New value: {}", counter.count);
        } else {
            msg!("Cannot decrease counter below 0. Current value: {}", counter.count);
            return Err(ProgramError::InvalidArgument.into());
        }

        Ok(())
    }
}

fn initialize_counter(ctx: &mut Context<ManageCounter>) -> Result<()> {
    let counter = &mut ctx.accounts.counter;

    msg!("Initializing counter with value 0...");
    counter.authority = *ctx.accounts.authority.key;
    counter.count = 0;
    msg!("Counter initialized.");

    Ok(())
}

#[derive(Accounts)]
pub struct ManageCounter<'info> {
    #[account(
        init_if_needed,
        seeds = [b"counter", authority.key().as_ref()],
        bump,
        payer = authority,
        space = 8 + std::mem::size_of::<Counter>(),
    )]
    pub counter: Account<'info, Counter>,
    #[account(mut)]
    pub authority: Signer<'info>,
    pub system_program: Program<'info, System>,
}

#[account]
pub struct Counter {
    pub authority: Pubkey,
    pub count: u64,
}

In the frontend, I use the following React code to interact with the Solana program:

  const increaseCounter = async () => {
    if (!program) return;
    try {
      const [counterPda] = PublicKey.findProgramAddressSync(
        [Buffer.from('counter'), wallet.publicKey.toBuffer()],
        programID
      );
      await program.methods
        .increaseCounter(new BN(1))
        .accounts({
          counter: counterPda,
          authority: wallet.publicKey,
          system_program: SystemProgram.programId,
        })
        .rpc();
      getCounter(program);
    } catch (err) {
      console.error('Error increasing counter:', err);
    }
  };
5
  • can you post a signature of a failed transaction please ? will check which signature is missing... and does it fail when you initialize the PDA, or when you try to increase/decrease only ?
    – Effe2
    Commented Oct 14 at 10:09
  • The error occurs when creating the PDA for the first time (i.e. when using init_if_needed). I can't share it because I couldn't get a transaction signature. { "signature": "", "transactionMessage": "Transaction simulation failed: Error processing Instruction 2: Cross-program invocation with unauthorized signer or writable account", "transactionLogs": [ "Program ComputeBudget111111111111111111111111111111 invoke [1]", "Progr ... " Instruction: IncreaseCounter", "2pXCEyxopRZNhABaqQ3JefqPoeEycaUJuEFaDH4iLFwd's writable privilege escalated", Commented Oct 14 at 11:29
  • ok, you can get a signature if you put skipPreflight = true in config for sending the transaction. 2pXCEyx => which account is it ? is it your id.json ? user ? pda ?
    – Effe2
    Commented Oct 14 at 13:46
  • i didn't know that thx, tx signature: 2ZnJWjqo38i3f7YtLP44LmPRqAtC9U1F9DvAbL8YUBpd9KxQpfsBifZF4DSJQqg9JRFoiHWW5d7Z5a8c9DdF6FNf explorer.solana.com/tx/… 2pXCEyxopRZNhABaqQ3JefqPoeEycaUJuEFaDH4iLFwd this pda calculated by client const [counterPda] = PublicKey.findProgramAddressSync( [Buffer.from('counter'), wallet.publicKey.toBuffer()], programID ); Commented Oct 15 at 7:39
  • add an answer, too long for a comment ;)
    – Effe2
    Commented Oct 15 at 20:37

2 Answers 2

0

just an idea: it looks like the tx fails when the account is created (CPI to system program), my idea is that your account is not sent as writable in your accounts array in the instruction. Could you check your IDL, you will find the instruction, and the related accounts. You have 2 params for each account: is signer, and is mutable (i don't remember the name exactly, but you will find it easily). Check if is mutable = true or false. if it's false, try to change it to true, and run again your script without modifying anything.

Also, i never used init_if_needed, might be related. What happen if you try with "init" only ? (if it works, it's only once, but it's to check if it's related to init_if_needed). May be with init_if_needed you need to manually add "mut" in the account (it doesn't look like it, but we never know...) ? My idea is that without "mut" attribute for the PDA account in the instruction's struct, the account is not flagged as writable in the IDL.

3
  • I encountered issues with writable and signer parameters, and also tried using init instead of init_if_needed, but the same error persisted.Yes the issue might be related to the IDL because each time I build, the type gets included in the generated types, and I receive an error in the frontend: "Cannot read properties of undefined (reading 'kind')." I need to add the type manually to the account each time. Also, need to change pubkey to publicKey. Below, I’ve included a GitHub link where you can find the frontend program and IDL file. github.com/0xfiraterdem/counter Commented Oct 16 at 8:18
  • The issue was caused by the IDL file generated during the build with Anchor CLI not being in the correct format. I don't know the reason for this; I've updated all the packages to their latest versions, but the problem still persists. However, when I built it through beta.solpg.io/tutorials/hello-anchor and used the IDL generated there, the program worked without any issues. Commented Oct 16 at 11:01
  • nice! good job!
    – Effe2
    Commented Oct 16 at 13:15
0

As the error suggests, make sure that you are using the correct signer when sending the tx.

By default, the .rpc method uses the local Solana ~/.config/solana/id.json wallet to sign for transaction.

Check that it is similar to the wallet signer you are using.

If different, you can first convert the method call into a transaction and sign it

await program.methods
    .increaseCounter(new BN(1))
    .accounts({
        counter: counterPda,
        authority: wallet.publicKey,
        system_program: SystemProgram.programId,
    })
    .transaction();

await signTransaction(tx);
3
  • I'm using Phantom Wallet for signing transactions on the client side, not the local wallet (~/.config/solana/id.json). The setup is meant to create a unique PDA for each user. When a user interacts with the program to increase or decrease the counter, it checks if their PDA exists and creates it if necessary. The program owner and the user’s wallets are different, so that might explain the issue. Commented Oct 14 at 8:18
  • updated my answer
    – Jimii
    Commented Oct 14 at 8:26
  • Message: Transaction simulation failed: Error processing Instruction 2: Cross-program invocation with unauthorized signer or writable account. Logs: [ "Program ComputeBudget111111111111111111111111111111 invoke [1]", "Program ComputeBudget111111111111111111111111111111 success", "Program ComputeBudget111111111111111111111111111111 invoke [1]", i got this error Commented Oct 16 at 8:06

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.