Search code examples
solanaanchor-solana

Solana anchor Error processing Instruction 0: Cross-program invocation with unauthorized signer or writable account


I am struggling to make a simple solana anchor code example to work. All I am trying to do is to initialize a piece of data with only my wallet being allowed to do it. Here is my Solana anchor code:

impl<'info> Validate<'info> for InitData<'info> {
  fn validate(&self) -> Result<()> {
      assert_keys_eq!(self.manager, Pubkey::from_str("2jEfqL1wFEHFjtbKEDoRottSBsij3v1j19aZueqrnj7v").unwrap());
      Ok(())
  }
}
#[program]
mod coinflip_bet {
  use super::*;
  #[access_control(ctx.accounts.validate())]
  pub fn init_data(ctx: Context<InitData>) -> Result<()> {
    Ok(())
  }
}
#[derive(Accounts)]
pub struct InitData<'info> {
    #[account(
        init,
        payer = manager,
        space = 8 + 1,
        seeds = [b"data-account", manager.key().as_ref()],
        bump
    )]
    pub data_account: Account<'info, DummyData>,
    #[account(mut)]
    pub manager: Signer<'info>,
    pub system_program: Program<'info, System>,
}
#[account]
pub struct DummyData {
    pub dummy: u8,
}

Here is my client code:

require('dotenv').config();
const PROGRAM_ID = process.env.PROGRAM_ID ?? '';
async function run() {
  const connection = new Connection('http://127.0.0.1:8899');
  const wallet = NodeWallet.local();
  const programId = new PublicKey(PROGRAM_ID);
  const [dataAccount,] = await PublicKey.findProgramAddress(
    [Buffer.from("data-account"), wallet.publicKey.toBuffer()],
    SystemProgram.programId
  );
  const provider = new anchor.AnchorProvider(
    connection,
    wallet,
    anchor.AnchorProvider.defaultOptions()
  );
  //doesn't compile without this type checker skip
  //@ts-ignore
  const program = new anchor.Program(IDL, programId, provider);
  await program.methods.initData()
  .accounts(
    {
      dataAccount: dataAccount,
      manager: wallet.publicKey,
      systemProgram: SystemProgram.programId,
    }
  )
  .signers(
    [wallet.payer]
  )
  .rpc();
}
run().then(
  () => process.exit(),
  err => {
    console.error(err);
    process.exit(-1);
  },
);

I'm on localhost:8899, launching this with 'solana-test-validator', 'anchor build', 'anchor deploy', 'ts-node src/init-data-account.ts' I get this error:

SendTransactionError: failed to send transaction: Transaction simulation failed: Error processing Instruction 0: Cross-program invocation with unauthorized signer or writable account

logs: [
    'Program 6YQukxVDKejG79RNSddyeEy6YQRVNkXSi4f5HuEyVMd6 invoke [1]',
    'Program log: Instruction: InitData',
    "7g32AFUNrTqyyuj1zbve6ui1aUzqzEvzpBc2tdNmqBjo's signer privilege escalated",
    'Program 6YQukxVDKejG79RNSddyeEy6YQRVNkXSi4f5HuEyVMd6 consumed 6670 of 200000 compute units',
    'Program 6YQukxVDKejG79RNSddyeEy6YQRVNkXSi4f5HuEyVMd6 failed: Cross-program invocation with unauthorized signer or writable account'
  ],

Can you please help me get rid off this error?

Update: I updated my accounts struct:

#[derive(Accounts)]
pub struct InitData<'info> {
    #[account(
        init,
        payer = manager,
        space = 8 + 1,
        seeds = [b"data-account", handler.key().as_ref()],
        bump
    )]
    pub data_account: Account<'info, Escrow>,
    /// CHECK:
    #[account(mut)]
    pub handler: AccountInfo<'info>,
    #[account(mut)]
    pub manager: Signer<'info>,
    pub system_program: Program<'info, System>,
}

And I still have this error:

Cross-program invocation with unauthorized signer or writable account

Solution

  • The problem is this code:

    const [dataAccount,] = await PublicKey.findProgramAddress(
      [Buffer.from("data-account"), wallet.publicKey.toBuffer()],
      SystemProgram.programId
    );
    

    It should be the id of the program instead of system program