1

I have an Anchor program where one of the instruction calls another like so:

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

    pub fn foo(
        ctx: Context<Foo>,
    ) -> Result<()> {
        instructions::bar(ctx)
    }

    pub fn bar(
        ctx: Context<Bar>,
    ) -> Result<()> {
        Ok(())
    }
}

However, I want the signer of the foo instruction to be the signer of the transaction, and the signer of the bar transaction when called by foo to be a PDA.

I can't use CpiContext::new_with_signer because it's not a cross program invocation, I can't instantiate a signer that wasn't passed to to the #[derive(Accounts)] struct and I can't pass it because only the program can sign with this key.

Is there a way to do CPIs to the same program? Can I instantiate a Signer?

1 Answer 1

2

You can do self-reentrancy in a Solana program, but perhaps there are some gotchas when using it with Anchor: https://docs.solana.com/developing/programming-model/calling-between-programs#reentrancy

This does count as a CPI since you're issuing another instruction to your same program.

However, it seems like you might be better served by refactoring your logic to call into some helper function, ie:

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

    pub fn foo(
        ctx: Context<Foo>,
    ) -> Result<()> {
        do_bar(ctx)
    }

    pub fn bar(
        ctx: Context<Bar>,
    ) -> Result<()> {
        do_bar(ctx)
    }
}

fn do_bar() -> Result<()> {
    Ok(())
}
1
  • Looking into Orca's whirlpool codebase, this is exactly what they do. Thanks! Commented Dec 21, 2022 at 17:48

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.