I tried creating a PDA for my escrow program but I keep running into the error above. I ensured the seeds used in my testing code FindProgramAddress and the rust file are the same, but I still get this error. Does anyone know why? Should I be using uft8 encode for the seeds? My code is as such:

#[instruction(application_idx: u64, bump: u8)]
pub struct InitNewExchange<'info> {
    //Derived PDAs (Must specify seed and bump for PDA) 
        init, //Initializing a new account
        payer = user_sending,
        space = Exchange::LEN,
        seeds = [b"exchange",  
    application_exchange: Account<'info, Exchange>,

        init, //Initializing a new account
        payer = user_sending,
        seeds = [b"wallet", 
        token::mint =  mint_of_token_being_sent,
        token::authority = application_exchange,
    //Should not be signer or writable
    escrow_wallet_exchange: Account<'info, TokenAccount>,

    //User Accounts
    user_sending: Signer<'info>,
    ///CHECK: Not dangerous
    user_receiving: AccountInfo<'info>,
    mint_of_token_being_sent: Account<'info, Mint>,

    //Token wallet that escrow wallet has alredy approved
        constraint = wallet_to_withdraw_from.owner == user_sending.key(),
        constraint = wallet_to_withdraw_from.mint == mint_of_token_being_sent.key(),
    wallet_to_withdraw_from: Account<'info, TokenAccount>,

    //App level accounts
    system_program: Program<'info, System>,
    token_program: Program<'info, Token>,
    rent: Sysvar<'info, Rent>,

and my test code:

let pda: PDAParams;

  //FUNCTIONS to prepare cross program invocation
  const getPDAparams = async(
    connection: anchor.web3.Connection, 
    sender?: anchor.web3.PublicKey,
    receiver?: anchor.web3.PublicKey,
    token?: anchor.web3.PublicKey): Promise<PDAParams> => {
    //Get timestamp for transaction
    const uid = new anchor.BN(parseInt((Date.now() / 1000).toString()));
    const uidbuffer = uid.toBuffer("le", 8);

    //Takes in seeds and program ID
    //Return a public key of PDA and checks that the pubkey is on the ed25519 curve
    let [exchangePubKey,] = await anchor.web3.PublicKey.findProgramAddress(

    let [walletPubKey,] = await anchor.web3.PublicKey.findProgramAddress(

    return {
      escrowWalletKey: walletPubKey,
      exchangeKey: exchangePubKey,
      idx: uid,

it("Initialize a payment by sender1", async() => {
        const amount = new anchor.BN(20000000);

        //Initialize mint and fund the account
        const tx1 = await program.methods
        .initNewExchange(pda.idx, amount)
            applicationExchange: pda.exchangeKey,
            escrowWalletExchange: pda.escrowWalletKey,
            userSending: sender.publicKey,
            userReceiving: receiver.publicKey,
            //Account data type of mint
            mintOfTokenBeingSent: mintAddress,
            //Wallet of sender for that particular token
            walletToWithdrawFrom: senderWallet,
            systemProgram: anchor.web3.SystemProgram.programId,
            tokenProgram: spl.TOKEN_PROGRAM_ID,
            rent: anchor.web3.SYSVAR_RENT_PUBKEY,

        console.log("Initialized a new exchange instance! 20 tokens being paid");

Any help is greatly appreciated!

  • The problem is with your cpi call so you'll need to post the code that makes the cpi
    – Buzzec
    Sep 8, 2022 at 20:34
  • Needs more detail, the full program logs and the function code are both necessary to answer with more than a loose response that this usually means you're not signing with the correct seed
    – Henry E
    Sep 19, 2022 at 9:22

1 Answer 1


The error

Cross-program invocation with unauthorized signer or writable account

is usually caused by one of two things

  • you have not set the account to mut
  • you haven't used the correct seeds for the account

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.