entrypoint.rs 8.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269
  1. use pinocchio::{
  2. account_info::AccountInfo, default_panic_handler, no_allocator, program_entrypoint,
  3. program_error::ProgramError, pubkey::Pubkey, ProgramResult,
  4. };
  5. use crate::processor::*;
  6. program_entrypoint!(process_instruction);
  7. // Do not allocate memory.
  8. no_allocator!();
  9. // Use the default panic handler.
  10. default_panic_handler!();
  11. /// Process an instruction.
  12. ///
  13. /// In the first stage, the entrypoint checks the discriminator of the instruction data
  14. /// to determine whether the instruction is a "batch" instruction or a "regular" instruction.
  15. /// This avoids nesting of "batch" instructions, since it is not sound to have a "batch"
  16. /// instruction inside another "batch" instruction.
  17. #[inline(always)]
  18. pub fn process_instruction(
  19. _program_id: &Pubkey,
  20. accounts: &[AccountInfo],
  21. instruction_data: &[u8],
  22. ) -> ProgramResult {
  23. let [discriminator, remaining @ ..] = instruction_data else {
  24. return Err(ProgramError::InvalidInstructionData);
  25. };
  26. if *discriminator == 255 {
  27. // 255 - Batch
  28. #[cfg(feature = "logging")]
  29. pinocchio::msg!("Instruction: Batch");
  30. return process_batch(accounts, remaining);
  31. }
  32. inner_process_instruction(accounts, instruction_data)
  33. }
  34. /// Process a "regular" instruction.
  35. ///
  36. /// The processor of the token program is divided into two parts to reduce the overhead
  37. /// of having a large `match` statement. The first part of the processor handles the
  38. /// most common instructions, while the second part handles the remaining instructions.
  39. ///
  40. /// The rationale is to reduce the overhead of making multiple comparisons for popular
  41. /// instructions.
  42. ///
  43. /// Instructions on the first part of the inner processor:
  44. ///
  45. /// - `0`: `InitializeMint`
  46. /// - `1`: `InitializeAccount`
  47. /// - `3`: `Transfer`
  48. /// - `7`: `MintTo`
  49. /// - `9`: `CloseAccount`
  50. /// - `16`: `InitializeAccount2`
  51. /// - `18`: `InitializeAccount3`
  52. /// - `20`: `InitializeMint2`
  53. #[inline(always)]
  54. pub(crate) fn inner_process_instruction(
  55. accounts: &[AccountInfo],
  56. instruction_data: &[u8],
  57. ) -> ProgramResult {
  58. let [discriminator, instruction_data @ ..] = instruction_data else {
  59. return Err(ProgramError::InvalidInstructionData);
  60. };
  61. match *discriminator {
  62. // 0 - InitializeMint
  63. 0 => {
  64. #[cfg(feature = "logging")]
  65. pinocchio::msg!("Instruction: InitializeMint");
  66. process_initialize_mint(accounts, instruction_data)
  67. }
  68. // 1 - InitializeAccount
  69. 1 => {
  70. #[cfg(feature = "logging")]
  71. pinocchio::msg!("Instruction: InitializeAccount");
  72. process_initialize_account(accounts)
  73. }
  74. // 3 - Transfer
  75. 3 => {
  76. #[cfg(feature = "logging")]
  77. pinocchio::msg!("Instruction: Transfer");
  78. process_transfer(accounts, instruction_data)
  79. }
  80. // 7 - MintTo
  81. 7 => {
  82. #[cfg(feature = "logging")]
  83. pinocchio::msg!("Instruction: MintTo");
  84. process_mint_to(accounts, instruction_data)
  85. }
  86. // 9 - CloseAccount
  87. 9 => {
  88. #[cfg(feature = "logging")]
  89. pinocchio::msg!("Instruction: CloseAccount");
  90. process_close_account(accounts)
  91. }
  92. // 16 - InitializeAccount2
  93. 16 => {
  94. #[cfg(feature = "logging")]
  95. pinocchio::msg!("Instruction: InitializeAccount2");
  96. process_initialize_account2(accounts, instruction_data)
  97. }
  98. // 18 - InitializeAccount3
  99. 18 => {
  100. #[cfg(feature = "logging")]
  101. pinocchio::msg!("Instruction: InitializeAccount3");
  102. process_initialize_account3(accounts, instruction_data)
  103. }
  104. // 20 - InitializeMint2
  105. 20 => {
  106. #[cfg(feature = "logging")]
  107. pinocchio::msg!("Instruction: InitializeMint2");
  108. process_initialize_mint2(accounts, instruction_data)
  109. }
  110. d => inner_process_remaining_instruction(accounts, instruction_data, d),
  111. }
  112. }
  113. /// Process a remaining "regular" instruction.
  114. ///
  115. /// This function is called by the [`inner_process_instruction`] function if the discriminator
  116. /// does not match any of the common instructions. This function is used to reduce the
  117. /// overhead of having a large `match` statement in the [`inner_process_instruction`] function.
  118. fn inner_process_remaining_instruction(
  119. accounts: &[AccountInfo],
  120. instruction_data: &[u8],
  121. discriminator: u8,
  122. ) -> ProgramResult {
  123. match discriminator {
  124. // 2 - InitializeMultisig
  125. 2 => {
  126. #[cfg(feature = "logging")]
  127. pinocchio::msg!("Instruction: InitializeMultisig");
  128. process_initialize_multisig(accounts, instruction_data)
  129. }
  130. // 4 - Approve
  131. 4 => {
  132. #[cfg(feature = "logging")]
  133. pinocchio::msg!("Instruction: Approve");
  134. process_approve(accounts, instruction_data)
  135. }
  136. // 5 - Revoke
  137. 5 => {
  138. #[cfg(feature = "logging")]
  139. pinocchio::msg!("Instruction: Revoke");
  140. process_revoke(accounts, instruction_data)
  141. }
  142. // 6 - SetAuthority
  143. 6 => {
  144. #[cfg(feature = "logging")]
  145. pinocchio::msg!("Instruction: SetAuthority");
  146. process_set_authority(accounts, instruction_data)
  147. }
  148. // 8 - Burn
  149. 8 => {
  150. #[cfg(feature = "logging")]
  151. pinocchio::msg!("Instruction: Burn");
  152. process_burn(accounts, instruction_data)
  153. }
  154. // 10 - FreezeAccount
  155. 10 => {
  156. #[cfg(feature = "logging")]
  157. pinocchio::msg!("Instruction: FreezeAccount");
  158. process_freeze_account(accounts)
  159. }
  160. // 11 - ThawAccount
  161. 11 => {
  162. #[cfg(feature = "logging")]
  163. pinocchio::msg!("Instruction: ThawAccount");
  164. process_thaw_account(accounts)
  165. }
  166. // 12 - TransferChecked
  167. 12 => {
  168. #[cfg(feature = "logging")]
  169. pinocchio::msg!("Instruction: TransferChecked");
  170. process_transfer_checked(accounts, instruction_data)
  171. }
  172. // 13 - ApproveChecked
  173. 13 => {
  174. #[cfg(feature = "logging")]
  175. pinocchio::msg!("Instruction: ApproveChecked");
  176. process_approve_checked(accounts, instruction_data)
  177. }
  178. // 14 - MintToChecked
  179. 14 => {
  180. #[cfg(feature = "logging")]
  181. pinocchio::msg!("Instruction: MintToChecked");
  182. process_mint_to_checked(accounts, instruction_data)
  183. }
  184. // 15 - BurnChecked
  185. 15 => {
  186. #[cfg(feature = "logging")]
  187. pinocchio::msg!("Instruction: BurnChecked");
  188. process_burn_checked(accounts, instruction_data)
  189. }
  190. // 17 - SyncNative
  191. 17 => {
  192. #[cfg(feature = "logging")]
  193. pinocchio::msg!("Instruction: SyncNative");
  194. process_sync_native(accounts)
  195. }
  196. // 19 - InitializeMultisig2
  197. 19 => {
  198. #[cfg(feature = "logging")]
  199. pinocchio::msg!("Instruction: InitializeMultisig2");
  200. process_initialize_multisig2(accounts, instruction_data)
  201. }
  202. // 21 - GetAccountDataSize
  203. 21 => {
  204. #[cfg(feature = "logging")]
  205. pinocchio::msg!("Instruction: GetAccountDataSize");
  206. process_get_account_data_size(accounts)
  207. }
  208. // 22 - InitializeImmutableOwner
  209. 22 => {
  210. #[cfg(feature = "logging")]
  211. pinocchio::msg!("Instruction: InitializeImmutableOwner");
  212. process_initialize_immutable_owner(accounts)
  213. }
  214. // 23 - AmountToUiAmount
  215. 23 => {
  216. #[cfg(feature = "logging")]
  217. pinocchio::msg!("Instruction: AmountToUiAmount");
  218. process_amount_to_ui_amount(accounts, instruction_data)
  219. }
  220. // 24 - UiAmountToAmount
  221. 24 => {
  222. #[cfg(feature = "logging")]
  223. pinocchio::msg!("Instruction: UiAmountToAmount");
  224. process_ui_amount_to_amount(accounts, instruction_data)
  225. }
  226. // 38 - WithdrawExcessLamports
  227. 38 => {
  228. #[cfg(feature = "logging")]
  229. pinocchio::msg!("Instruction: WithdrawExcessLamports");
  230. process_withdraw_excess_lamports(accounts)
  231. }
  232. _ => Err(ProgramError::InvalidInstructionData),
  233. }
  234. }