1

i'm getting the error in the title mentioned above and none of the solutions online seem to fix my error. This is the error msg in its entirety: Error: failed to send transaction: Transaction simulation failed: Error processing Instruction 0: Cross-program invocation with unauthorized signer or writable account

and the relevant slices of code:

#[derive(Accounts)]
pub struct InitializeMargin<'info> {
    #[account(
        init,
        seeds = [b"margin-account", main_account.key().as_ref(), authority.key.as_ref()],
        bump,
        payer = authority,
        space = 8 + size_of::<MarginAccount>()
    )]
    pub margin_account: AccountLoader<'info, MarginAccount>,
    pub main_account: AccountLoader<'info, MainAccount>,
    #[account(mut)]
    pub authority: Signer<'info>,
    pub system_program: Program<'info, System>,
    pub rent: Sysvar<'info, Rent>,
}

The seeds passed look correct to me

    async getMarginAccountPda(mainAccountPubkey: PublicKey, marginOwner: PublicKey): Promise<Pda> {
        const [address, bump] = await PublicKey.findProgramAddress(
            [Buffer.from('margin-account'), mainAccountPubkey.toBuffer(), marginOwner.toBuffer()],
            this.program.programId
        );
        return { address, bump };
    }

I don't think i need to add a .signers([]) to the below since authority is type Signer

        const marginAccountPda = await this.getMarginAccountPda(mainAccount, this.wallet.publicKey);
        const marginInfo = await this.provider.connection.getAccountInfo(marginAccount.publicKey);
        if (marginInfo) {
            throw Error('MarginAccount ' + marginAccount.publicKey.toBase58() + ' already exists!');
        }
        console.log("mainaccount, marginaccount, authority", mainAccount.toBase58(), marginAccount.publicKey.toBase58(), this.wallet.publicKey.toBase58())
        const sig = await this.program.methods.initializeMargin(marginAccountPda.bump).accounts({
            mainAccount: mainAccount,
            marginAccount: marginAccount.publicKey,
            authority: this.wallet.publicKey,
            systemProgram: SystemProgram.programId,
            rent: SYSVAR_RENT_PUBKEY,
        })
        .rpc();

1 Answer 1

2

With the way you're currently defining margin_account's seeds in your anchor program, your frontend derivation should be thus:

async getMarginAccountPda(mainAccountPubkey: PublicKey, marginOwner: PublicKey): Promise<Pda> {
    const [address, bump] = await PublicKey.findProgramAddress(
        anchor.utils.bytes.utf8.encode("margin-account"), mainAccountPubkey.toBuffer(), marginOwner.toBuffer()],
        this.program.programId
    );
    return { address, bump };
}

The change is in how margin_account is handled in FindProgramAddress.

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.