123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285 |
- use {
- crate::processor::*,
- pinocchio::{
- account_info::AccountInfo,
- no_allocator, nostd_panic_handler, program_entrypoint,
- program_error::{ProgramError, ToStr},
- pubkey::Pubkey,
- ProgramResult,
- },
- spl_token_interface::error::TokenError,
- };
- program_entrypoint!(process_instruction);
- // Do not allocate memory.
- no_allocator!();
- // Use the no_std panic handler.
- nostd_panic_handler!();
- /// Log an error.
- #[cold]
- fn log_error(error: &ProgramError) {
- pinocchio::log::sol_log(error.to_str::<TokenError>());
- }
- /// 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);
- };
- let result = if *discriminator == 255 {
- // 255 - Batch
- #[cfg(feature = "logging")]
- pinocchio::msg!("Instruction: Batch");
- process_batch(accounts, remaining)
- } else {
- inner_process_instruction(accounts, instruction_data)
- };
- result.inspect_err(log_error)
- }
- /// 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),
- }
- }
|