Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

declare_program! macro panics when program has no direct instructions but uses shared contexts #3274

Open
biryukovmaxim opened this issue Sep 25, 2024 · 1 comment
Labels
bug Something isn't working lang

Comments

@biryukovmaxim
Copy link
Contributor

biryukovmaxim commented Sep 25, 2024

Description

The declare_program! macro is panicking with the error "Instruction must exist" when used with a program that has no direct instructions but uses shared contexts across multiple instructions.

Steps to Reproduce

  1. Create a Solana program using Anchor with the following structure:
use anchor_lang::prelude::*;

declare_id!("7VMBwUQPsKb1G41qusehNJZ5vYQrFNg8pdw2ViaApm4Y");

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

    pub fn initialize_state(_ctx: Context<Initialize>) -> Result<()> {
        Ok(())
    }

    // Note: This instruction is removed in the problematic scenario
    // pub fn empty(_ctx: Context<InnerContext>) -> Result<()> {
    //     Ok(())
    // }
}

#[derive(Accounts)]
pub struct Initialize<'info> {
    /// CHECK:
    pub some_acc: AccountInfo<'info>,
    pub inner_ctx: InnerContext<'info>,
}

#[derive(Accounts)]
pub struct InnerContext<'info> {
    /// CHECK:
    pub inner_acc: AccountInfo<'info>,
}
  1. Use the declare_program! macro in another crate:
declare_program!(composite);
  1. Attempt to build the project.

Expected Behavior

The declare_program! macro should successfully generate the necessary code for interacting with the program, recognizing the shared context structure.

Actual Behavior

The macro panics with the following error:

error: proc macro panicked
 --> programs/test-project-idl/src/lib.rs:5:1
  |
5 | declare_program!(composite);
  | ^^^^^^^^^^^^^^^^^^^^^^^^^^^
  |
  = help: message: Instruction must exist

Context

In real-world scenarios, it's common to use contexts with a subset of accounts and share them between many instructions. This allows for more modular and reusable code. However, this can lead to situations where a context is not used directly in any instructions within a specific program module.

Possible Cause

The declare_program! macro is checking for the existence of instructions that directly use the defined contexts, rather than recognizing the shared context structure.
the root of the problem is here

Additional Information

  • Anchor version: 0.30.0, 0.30.1

Proposed Solution

The declare_program! macro should be updated to recognize and handle programs that use shared contexts without direct instructions. It should generate the necessary code based on the context structures, even when they're not directly used in instructions within the current program module.

Workaround

Currently, adding a dummy instruction that uses the shared context allows the macro to work:

pub fn empty(_ctx: Context<InnerContext>) -> Result<()> {
    Ok(())
}

However, this is not ideal for production code.

@acheroncrypto acheroncrypto added bug Something isn't working lang labels Sep 25, 2024
@acheroncrypto
Copy link
Collaborator

Thanks for creating the issue and giving a comprehensive explanation of the problem. Your assessment is correct, and this has been on my todo list for a while, but I haven't been able to get to it just yet.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working lang
Projects
None yet
Development

No branches or pull requests

2 participants