| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269 |
- use pinocchio::{
- account_info::AccountInfo, default_panic_handler, no_allocator, program_entrypoint,
- program_error::ProgramError, pubkey::Pubkey, ProgramResult,
- };
- use crate::processor::*;
- program_entrypoint!(process_instruction);
- // Do not allocate memory.
- no_allocator!();
- // Use the default panic handler.
- default_panic_handler!();
- /// Process an instruction.
- ///
- /// In the first stage, the entrypoint checks the discriminator of the instruction data
- /// to determine whether the instruction is a "batch" instruction or a "regular" instruction.
- /// This avoids nesting of "batch" instructions, since it is not sound to have a "batch"
- /// instruction inside another "batch" instruction.
- #[inline(always)]
- pub fn process_instruction(
- _program_id: &Pubkey,
- accounts: &[AccountInfo],
- instruction_data: &[u8],
- ) -> ProgramResult {
- let [discriminator, remaining @ ..] = instruction_data else {
- return Err(ProgramError::InvalidInstructionData);
- };
- if *discriminator == 255 {
- // 255 - Batch
- #[cfg(feature = "logging")]
- pinocchio::msg!("Instruction: Batch");
- return process_batch(accounts, remaining);
- }
- inner_process_instruction(accounts, instruction_data)
- }
- /// Process a "regular" instruction.
- ///
- /// The processor of the token program is divided into two parts to reduce the overhead
- /// of having a large `match` statement. The first part of the processor handles the
- /// most common instructions, while the second part handles the remaining instructions.
- ///
- /// The rationale is to reduce the overhead of making multiple comparisons for popular
- /// instructions.
- ///
- /// Instructions on the first part of the inner processor:
- ///
- /// - `0`: `InitializeMint`
- /// - `1`: `InitializeAccount`
- /// - `3`: `Transfer`
- /// - `7`: `MintTo`
- /// - `9`: `CloseAccount`
- /// - `16`: `InitializeAccount2`
- /// - `18`: `InitializeAccount3`
- /// - `20`: `InitializeMint2`
- #[inline(always)]
- pub(crate) fn inner_process_instruction(
- accounts: &[AccountInfo],
- instruction_data: &[u8],
- ) -> ProgramResult {
- let [discriminator, instruction_data @ ..] = instruction_data else {
- return Err(ProgramError::InvalidInstructionData);
- };
- match *discriminator {
- // 0 - InitializeMint
- 0 => {
- #[cfg(feature = "logging")]
- pinocchio::msg!("Instruction: InitializeMint");
- process_initialize_mint(accounts, instruction_data)
- }
- // 1 - InitializeAccount
- 1 => {
- #[cfg(feature = "logging")]
- pinocchio::msg!("Instruction: InitializeAccount");
- process_initialize_account(accounts)
- }
- // 3 - Transfer
- 3 => {
- #[cfg(feature = "logging")]
- pinocchio::msg!("Instruction: Transfer");
- process_transfer(accounts, instruction_data)
- }
- // 7 - MintTo
- 7 => {
- #[cfg(feature = "logging")]
- pinocchio::msg!("Instruction: MintTo");
- process_mint_to(accounts, instruction_data)
- }
- // 9 - CloseAccount
- 9 => {
- #[cfg(feature = "logging")]
- pinocchio::msg!("Instruction: CloseAccount");
- process_close_account(accounts)
- }
- // 16 - InitializeAccount2
- 16 => {
- #[cfg(feature = "logging")]
- pinocchio::msg!("Instruction: InitializeAccount2");
- process_initialize_account2(accounts, instruction_data)
- }
- // 18 - InitializeAccount3
- 18 => {
- #[cfg(feature = "logging")]
- pinocchio::msg!("Instruction: InitializeAccount3");
- process_initialize_account3(accounts, instruction_data)
- }
- // 20 - InitializeMint2
- 20 => {
- #[cfg(feature = "logging")]
- pinocchio::msg!("Instruction: InitializeMint2");
- process_initialize_mint2(accounts, instruction_data)
- }
- d => inner_process_remaining_instruction(accounts, instruction_data, d),
- }
- }
- /// Process a remaining "regular" instruction.
- ///
- /// This function is called by the [`inner_process_instruction`] function if the discriminator
- /// does not match any of the common instructions. This function is used to reduce the
- /// overhead of having a large `match` statement in the [`inner_process_instruction`] function.
- fn inner_process_remaining_instruction(
- accounts: &[AccountInfo],
- instruction_data: &[u8],
- discriminator: u8,
- ) -> ProgramResult {
- match discriminator {
- // 2 - InitializeMultisig
- 2 => {
- #[cfg(feature = "logging")]
- pinocchio::msg!("Instruction: InitializeMultisig");
- process_initialize_multisig(accounts, instruction_data)
- }
- // 4 - Approve
- 4 => {
- #[cfg(feature = "logging")]
- pinocchio::msg!("Instruction: Approve");
- process_approve(accounts, instruction_data)
- }
- // 5 - Revoke
- 5 => {
- #[cfg(feature = "logging")]
- pinocchio::msg!("Instruction: Revoke");
- process_revoke(accounts, instruction_data)
- }
- // 6 - SetAuthority
- 6 => {
- #[cfg(feature = "logging")]
- pinocchio::msg!("Instruction: SetAuthority");
- process_set_authority(accounts, instruction_data)
- }
- // 8 - Burn
- 8 => {
- #[cfg(feature = "logging")]
- pinocchio::msg!("Instruction: Burn");
- process_burn(accounts, instruction_data)
- }
- // 10 - FreezeAccount
- 10 => {
- #[cfg(feature = "logging")]
- pinocchio::msg!("Instruction: FreezeAccount");
- process_freeze_account(accounts)
- }
- // 11 - ThawAccount
- 11 => {
- #[cfg(feature = "logging")]
- pinocchio::msg!("Instruction: ThawAccount");
- process_thaw_account(accounts)
- }
- // 12 - TransferChecked
- 12 => {
- #[cfg(feature = "logging")]
- pinocchio::msg!("Instruction: TransferChecked");
- process_transfer_checked(accounts, instruction_data)
- }
- // 13 - ApproveChecked
- 13 => {
- #[cfg(feature = "logging")]
- pinocchio::msg!("Instruction: ApproveChecked");
- process_approve_checked(accounts, instruction_data)
- }
- // 14 - MintToChecked
- 14 => {
- #[cfg(feature = "logging")]
- pinocchio::msg!("Instruction: MintToChecked");
- process_mint_to_checked(accounts, instruction_data)
- }
- // 15 - BurnChecked
- 15 => {
- #[cfg(feature = "logging")]
- pinocchio::msg!("Instruction: BurnChecked");
- process_burn_checked(accounts, instruction_data)
- }
- // 17 - SyncNative
- 17 => {
- #[cfg(feature = "logging")]
- pinocchio::msg!("Instruction: SyncNative");
- process_sync_native(accounts)
- }
- // 19 - InitializeMultisig2
- 19 => {
- #[cfg(feature = "logging")]
- pinocchio::msg!("Instruction: InitializeMultisig2");
- process_initialize_multisig2(accounts, instruction_data)
- }
- // 21 - GetAccountDataSize
- 21 => {
- #[cfg(feature = "logging")]
- pinocchio::msg!("Instruction: GetAccountDataSize");
- process_get_account_data_size(accounts)
- }
- // 22 - InitializeImmutableOwner
- 22 => {
- #[cfg(feature = "logging")]
- pinocchio::msg!("Instruction: InitializeImmutableOwner");
- process_initialize_immutable_owner(accounts)
- }
- // 23 - AmountToUiAmount
- 23 => {
- #[cfg(feature = "logging")]
- pinocchio::msg!("Instruction: AmountToUiAmount");
- process_amount_to_ui_amount(accounts, instruction_data)
- }
- // 24 - UiAmountToAmount
- 24 => {
- #[cfg(feature = "logging")]
- pinocchio::msg!("Instruction: UiAmountToAmount");
- process_ui_amount_to_amount(accounts, instruction_data)
- }
- // 38 - WithdrawExcessLamports
- 38 => {
- #[cfg(feature = "logging")]
- pinocchio::msg!("Instruction: WithdrawExcessLamports");
- process_withdraw_excess_lamports(accounts)
- }
- _ => Err(ProgramError::InvalidInstructionData),
- }
- }
|