macro_rules! entrypoint {
    ($process_instruction:ident) => { ... };
}
Expand description

Declare the program entry point and set up global handlers.

This macro emits the common boilerplate necessary to begin program execution, calling a provided function to process the program instruction supplied by the runtime, and reporting its result to the runtime.

It also sets up a global allocator and panic handler, using the custom_heap_default and custom_panic_default macros.

The argument is the name of a function with this type signature:

fn process_instruction(
    program_id: &Pubkey,      // Public key of the account the program was loaded into
    accounts: &[AccountInfo], // All accounts required to process the instruction
    instruction_data: &[u8],  // Serialized instruction-specific data
) -> ProgramResult;

Cargo features

This macro emits symbols and definitions that may only be defined once globally. As such, if linked to other Rust crates it will cause compiler errors. To avoid this, it is common for Safecoin programs to define an optional Cargo feature called no-entrypoint, and use it to conditionally disable the entrypoint macro invocation, as well as the process_instruction function. See a typical pattern for this in the example below.

The code emitted by this macro can be customized by adding cargo features to your own crate (the one that calls this macro) and enabling them:

  • If the custom-heap feature is defined then the macro will not set up the global allocator, allowing entrypoint to be used with your own allocator. See documentation for the custom_heap_default macro for details of customizing the global allocator.

  • If the custom-panic feature is defined then the macro will not define a panic handler, allowing entrypoint to be used with your own panic handler. See documentation for the custom_panic_default macro for details of customizing the panic handler.

Examples

Defining an entry point and making it conditional on the no-entrypoint feature. Although the entrypoint module is written inline in this example, it is common to put it into its own file.

#[cfg(not(feature = "no-entrypoint"))]
pub mod entrypoint {

    use solana_program::{
        account_info::AccountInfo,
        entrypoint,
        entrypoint::ProgramResult,
        msg,
        pubkey::Pubkey,
    };

    entrypoint!(process_instruction);

    pub fn process_instruction(
        program_id: &Pubkey,
        accounts: &[AccountInfo],
        instruction_data: &[u8],
    ) -> ProgramResult {
        msg!("Hello world");

        Ok(())
    }

}