hopper_native/
entrypoint.rs1use core::mem::MaybeUninit;
9
10use crate::account_view::AccountView;
11use crate::address::Address;
12
13#[inline(always)]
22pub unsafe fn process_entrypoint<const MAX: usize>(
23 input: *mut u8,
24 process_instruction: fn(&Address, &[AccountView], &[u8]) -> crate::ProgramResult,
25) -> u64 {
26 const UNINIT: MaybeUninit<AccountView> = MaybeUninit::uninit();
27 let mut accounts = [UNINIT; 254]; let (program_id, count, instruction_data) =
30 unsafe { crate::raw_input::deserialize_accounts::<254>(input, &mut accounts) };
31
32 let effective_count = count.min(MAX);
34 let account_slice = unsafe {
35 core::slice::from_raw_parts(accounts.as_ptr() as *const AccountView, effective_count)
36 };
37
38 match process_instruction(&program_id, account_slice, instruction_data) {
39 Ok(()) => crate::SUCCESS,
40 Err(error) => error.into(),
41 }
42}
43
44#[macro_export]
65macro_rules! hopper_program_entrypoint {
66 ( $process_instruction:expr ) => {
67 $crate::hopper_program_entrypoint!($process_instruction, { $crate::MAX_TX_ACCOUNTS });
68 };
69 ( $process_instruction:expr, $maximum:expr ) => {
70 #[no_mangle]
74 pub unsafe extern "C" fn entrypoint(input: *mut u8) -> u64 {
75 const UNINIT: core::mem::MaybeUninit<$crate::AccountView> =
76 core::mem::MaybeUninit::<$crate::AccountView>::uninit();
77 let mut accounts = [UNINIT; $maximum];
78
79 let (program_id, count, instruction_data) = unsafe {
80 $crate::raw_input::deserialize_accounts::<$maximum>(input, &mut accounts)
81 };
82
83 match $process_instruction(
84 &program_id,
85 unsafe { core::slice::from_raw_parts(accounts.as_ptr() as _, count) },
86 instruction_data,
87 ) {
88 Ok(()) => $crate::SUCCESS,
89 Err(error) => error.into(),
90 }
91 }
92 };
93}
94
95#[macro_export]
97macro_rules! program_entrypoint {
98 ( $process_instruction:expr ) => {
99 $crate::hopper_program_entrypoint!($process_instruction);
100 };
101 ( $process_instruction:expr, $maximum:expr ) => {
102 $crate::hopper_program_entrypoint!($process_instruction, $maximum);
103 };
104}
105
106#[macro_export]
131macro_rules! hopper_fast_entrypoint {
132 ( $process_instruction:expr ) => {
133 $crate::hopper_fast_entrypoint!($process_instruction, { $crate::MAX_TX_ACCOUNTS });
134 };
135 ( $process_instruction:expr, $maximum:expr ) => {
136 #[no_mangle]
142 pub unsafe extern "C" fn entrypoint(input: *mut u8, ix_data: *const u8) -> u64 {
143 const UNINIT: core::mem::MaybeUninit<$crate::AccountView> =
144 core::mem::MaybeUninit::<$crate::AccountView>::uninit();
145 let mut accounts = [UNINIT; $maximum];
146
147 let ix_len = unsafe { *(ix_data.sub(8) as *const u64) as usize };
149 let instruction_data: &'static [u8] =
150 unsafe { core::slice::from_raw_parts(ix_data, ix_len) };
151
152 let program_id =
154 unsafe { core::ptr::read(ix_data.add(ix_len) as *const $crate::Address) };
155
156 let (program_id, count, instruction_data) = unsafe {
157 $crate::raw_input::deserialize_accounts_fast::<$maximum>(
158 input,
159 &mut accounts,
160 instruction_data,
161 program_id,
162 )
163 };
164
165 match $process_instruction(
166 &program_id,
167 unsafe { core::slice::from_raw_parts(accounts.as_ptr() as _, count) },
168 instruction_data,
169 ) {
170 Ok(()) => $crate::SUCCESS,
171 Err(error) => error.into(),
172 }
173 }
174 };
175}
176
177#[macro_export]
179macro_rules! fast_entrypoint {
180 ( $process_instruction:expr ) => {
181 $crate::hopper_fast_entrypoint!($process_instruction);
182 };
183 ( $process_instruction:expr, $maximum:expr ) => {
184 $crate::hopper_fast_entrypoint!($process_instruction, $maximum);
185 };
186}
187
188#[macro_export]
190macro_rules! hopper_lazy_entrypoint {
191 ( $process:expr ) => {
192 #[no_mangle]
196 pub unsafe extern "C" fn entrypoint(input: *mut u8) -> u64 {
197 let mut ctx = unsafe { $crate::lazy::lazy_deserialize(input) };
198 match $process(&mut ctx) {
199 Ok(()) => $crate::SUCCESS,
200 Err(error) => error.into(),
201 }
202 }
203 };
204}
205
206#[macro_export]
208macro_rules! lazy_entrypoint {
209 ( $process:expr ) => {
210 $crate::hopper_lazy_entrypoint!($process);
211 };
212}
213
214#[macro_export]
220macro_rules! no_allocator {
221 () => {
222 #[cfg(target_os = "solana")]
223 mod __hopper_allocator {
224 struct NoAlloc;
225
226 unsafe impl core::alloc::GlobalAlloc for NoAlloc {
227 unsafe fn alloc(&self, _layout: core::alloc::Layout) -> *mut u8 {
228 core::arch::asm!("mov r0, 1", "exit", options(noreturn));
232 }
233 unsafe fn dealloc(&self, _ptr: *mut u8, _layout: core::alloc::Layout) {}
234 }
235
236 #[global_allocator]
237 static ALLOCATOR: NoAlloc = NoAlloc;
238 }
239 };
240}
241
242#[macro_export]
248macro_rules! nostd_panic_handler {
249 () => {
250 #[cfg(target_os = "solana")]
251 #[panic_handler]
252 fn panic(_info: &core::panic::PanicInfo) -> ! {
253 unsafe { core::arch::asm!("mov r0, 1", "exit", options(noreturn)) };
255 }
256 };
257}