manifest/
logs.rs

1use bytemuck::{Pod, Zeroable};
2use hypertree::PodBool;
3use shank::ShankAccount;
4use solana_program::{program_error::ProgramError, pubkey::Pubkey};
5
6use crate::{
7    quantities::{BaseAtoms, GlobalAtoms, QuoteAtoms, QuoteAtomsPerBaseAtom},
8    state::OrderType,
9};
10
11/// Serialize and log an event
12///
13/// Note that this is done instead of a self-CPI, which would be more reliable
14/// as explained here
15/// <https://github.com/coral-xyz/anchor/blob/59ee310cfa18524e7449db73604db21b0e04780c/lang/attribute/event/src/lib.rs#L104>
16/// because the goal of this program is to minimize the number of input
17/// accounts, so including the signer for the self CPI is not worth it.
18/// Also, be compatible with anchor parsing clients.
19
20#[cfg(not(feature = "certora"))]
21#[inline(never)] // ensure fresh stack frame
22pub fn emit_stack<T: bytemuck::Pod + Discriminant>(e: T) -> Result<(), ProgramError> {
23    // stack buffer, stack frames are 4kb
24    let mut buffer: [u8; 3000] = [0u8; 3000];
25    buffer[..8].copy_from_slice(&T::discriminant());
26    *bytemuck::from_bytes_mut::<T>(&mut buffer[8..8 + std::mem::size_of::<T>()]) = e;
27
28    solana_program::log::sol_log_data(&[&buffer[..(std::mem::size_of::<T>() + 8)]]);
29    Ok(())
30}
31
32// Do not emit logs for formal verification.
33#[cfg(feature = "certora")]
34pub fn emit_stack<T: bytemuck::Pod + Discriminant>(_e: T) -> Result<(), ProgramError> {
35    Ok(())
36}
37
38#[repr(C)]
39#[derive(Clone, Copy, Zeroable, Pod, ShankAccount)]
40pub struct CreateMarketLog {
41    pub market: Pubkey,
42    pub creator: Pubkey,
43    pub base_mint: Pubkey,
44    pub quote_mint: Pubkey,
45}
46
47#[repr(C)]
48#[derive(Clone, Copy, Zeroable, Pod, ShankAccount)]
49pub struct ClaimSeatLog {
50    pub market: Pubkey,
51    pub trader: Pubkey,
52}
53
54#[repr(C)]
55#[derive(Clone, Copy, Zeroable, Pod, ShankAccount)]
56pub struct DepositLog {
57    pub market: Pubkey,
58    pub trader: Pubkey,
59    pub mint: Pubkey,
60    pub amount_atoms: u64,
61}
62
63#[repr(C)]
64#[derive(Clone, Copy, Zeroable, Pod, ShankAccount)]
65pub struct WithdrawLog {
66    pub market: Pubkey,
67    pub trader: Pubkey,
68    pub mint: Pubkey,
69    pub amount_atoms: u64,
70}
71
72#[repr(C)]
73#[derive(Clone, Copy, Zeroable, Pod, ShankAccount)]
74pub struct FillLog {
75    pub market: Pubkey,
76    pub maker: Pubkey,
77    pub taker: Pubkey,
78    pub base_mint: Pubkey,
79    pub quote_mint: Pubkey,
80    pub price: QuoteAtomsPerBaseAtom,
81    pub base_atoms: BaseAtoms,
82    pub quote_atoms: QuoteAtoms,
83    pub maker_sequence_number: u64,
84    pub taker_sequence_number: u64,
85    pub taker_is_buy: PodBool,
86    pub is_maker_global: PodBool,
87    pub _padding: [u8; 14],
88}
89
90#[repr(C)]
91#[derive(Clone, Copy, Zeroable, Pod, ShankAccount)]
92pub struct PlaceOrderLog {
93    pub market: Pubkey,
94    pub trader: Pubkey,
95    pub price: QuoteAtomsPerBaseAtom,
96    pub base_atoms: BaseAtoms,
97    pub order_sequence_number: u64,
98    pub order_index: u32,
99    pub last_valid_slot: u32,
100    pub order_type: OrderType,
101    pub is_bid: PodBool,
102    pub _padding: [u8; 6],
103}
104
105#[repr(C)]
106#[derive(Clone, Copy, Zeroable, Pod, ShankAccount)]
107pub struct PlaceOrderLogV2 {
108    pub market: Pubkey,
109    pub trader: Pubkey,
110    pub payer: Pubkey,
111    pub price: QuoteAtomsPerBaseAtom,
112    pub base_atoms: BaseAtoms,
113    pub order_sequence_number: u64,
114    pub order_index: u32,
115    pub last_valid_slot: u32,
116    pub order_type: OrderType,
117    pub is_bid: PodBool,
118    pub _padding: [u8; 6],
119}
120
121#[repr(C)]
122#[derive(Clone, Copy, Zeroable, Pod, ShankAccount)]
123pub struct CancelOrderLog {
124    pub market: Pubkey,
125    pub trader: Pubkey,
126    pub order_sequence_number: u64,
127}
128
129#[repr(C)]
130#[derive(Clone, Copy, Zeroable, Pod, ShankAccount)]
131pub struct GlobalCreateLog {
132    pub global: Pubkey,
133    pub creator: Pubkey,
134}
135
136#[repr(C)]
137#[derive(Clone, Copy, Zeroable, Pod, ShankAccount)]
138pub struct GlobalAddTraderLog {
139    pub global: Pubkey,
140    pub trader: Pubkey,
141}
142
143#[repr(C)]
144#[derive(Clone, Copy, Zeroable, Pod, ShankAccount)]
145pub struct GlobalClaimSeatLog {
146    pub global: Pubkey,
147    pub market: Pubkey,
148    pub trader: Pubkey,
149}
150
151#[repr(C)]
152#[derive(Clone, Copy, Zeroable, Pod, ShankAccount)]
153pub struct GlobalDepositLog {
154    pub global: Pubkey,
155    pub trader: Pubkey,
156    pub global_atoms: GlobalAtoms,
157}
158
159#[repr(C)]
160#[derive(Clone, Copy, Zeroable, Pod, ShankAccount)]
161pub struct GlobalWithdrawLog {
162    pub global: Pubkey,
163    pub trader: Pubkey,
164    pub global_atoms: GlobalAtoms,
165}
166
167#[repr(C)]
168#[derive(Clone, Copy, Zeroable, Pod, ShankAccount)]
169pub struct GlobalEvictLog {
170    pub evictor: Pubkey,
171    pub evictee: Pubkey,
172    pub evictor_atoms: GlobalAtoms,
173    pub evictee_atoms: GlobalAtoms,
174}
175
176#[repr(C)]
177#[derive(Clone, Copy, Zeroable, Pod, ShankAccount)]
178pub struct GlobalCleanupLog {
179    pub cleaner: Pubkey,
180    pub maker: Pubkey,
181    pub amount_desired: GlobalAtoms,
182    pub amount_deposited: GlobalAtoms,
183}
184
185pub trait Discriminant {
186    fn discriminant() -> [u8; 8];
187}
188
189macro_rules! discriminant {
190    ($type_name:ident, $value:ident, $test_name:ident) => {
191        impl Discriminant for $type_name {
192            fn discriminant() -> [u8; 8] {
193                $value
194            }
195        }
196
197        #[test]
198        fn $test_name() {
199            let mut buffer: [u8; 8] = [0u8; 8];
200            let discriminant: u64 = crate::utils::get_discriminant::<$type_name>().unwrap();
201            buffer[..8].copy_from_slice(&u64::to_le_bytes(discriminant));
202            assert_eq!(buffer, $type_name::discriminant());
203        }
204    };
205}
206
207const CREATE_MARKET_LOG_DISCRIMINANT: [u8; 8] = [33, 31, 11, 6, 133, 143, 39, 71];
208const CLAIM_SEAT_LOG_DISCRIMINANT: [u8; 8] = [129, 77, 152, 210, 218, 144, 163, 56];
209const DEPOSIT_LOG_DISCRIMINANT: [u8; 8] = [23, 214, 24, 34, 52, 104, 109, 188];
210const WITHDRAW_LOG_DISCRIMINANT: [u8; 8] = [112, 218, 111, 63, 18, 95, 136, 35];
211const FILL_LOG_DISCRIMINANT: [u8; 8] = [58, 230, 242, 3, 75, 113, 4, 169];
212const PLACE_ORDER_LOG_DISCRIMINANT: [u8; 8] = [157, 118, 247, 213, 47, 19, 164, 120];
213const PLACE_ORDER_LOG_V2_DISCRIMINANT: [u8; 8] = [189, 97, 159, 235, 136, 5, 1, 141];
214const CANCEL_ORDER_LOG_DISCRIMINANT: [u8; 8] = [22, 65, 71, 33, 244, 235, 255, 215];
215const GLOBAL_CREATE_LOG_DISCRIMINANT: [u8; 8] = [188, 25, 199, 77, 26, 15, 142, 193];
216const GLOBAL_ADD_TRADER_LOG_DISCRIMINANT: [u8; 8] = [129, 246, 90, 94, 87, 186, 242, 7];
217const GLOBAL_CLAIM_SEAT_LOG_DISCRIMINANT: [u8; 8] = [164, 46, 227, 175, 3, 143, 73, 86];
218const GLOBAL_DEPOSIT_LOG_DISCRIMINANT: [u8; 8] = [16, 26, 72, 1, 145, 232, 182, 71];
219const GLOBAL_WITHDRAW_LOG_DISCRIMINANT: [u8; 8] = [206, 118, 67, 64, 124, 109, 157, 201];
220const GLOBAL_EVICT_LOG_DISCRIMINANT: [u8; 8] = [250, 180, 155, 38, 98, 223, 82, 223];
221const GLOBAL_CLEANUP_LOG_DISCRIMINANT: [u8; 8] = [193, 249, 115, 186, 42, 126, 196, 82];
222
223discriminant!(
224    CreateMarketLog,
225    CREATE_MARKET_LOG_DISCRIMINANT,
226    test_create_market_log
227);
228discriminant!(
229    ClaimSeatLog,
230    CLAIM_SEAT_LOG_DISCRIMINANT,
231    test_claim_seat_log
232);
233discriminant!(DepositLog, DEPOSIT_LOG_DISCRIMINANT, test_deposit_log);
234discriminant!(WithdrawLog, WITHDRAW_LOG_DISCRIMINANT, test_withdraw_log);
235discriminant!(FillLog, FILL_LOG_DISCRIMINANT, test_fill_log);
236discriminant!(
237    PlaceOrderLog,
238    PLACE_ORDER_LOG_DISCRIMINANT,
239    test_place_order
240);
241discriminant!(
242    PlaceOrderLogV2,
243    PLACE_ORDER_LOG_V2_DISCRIMINANT,
244    test_place_order_v2
245);
246discriminant!(
247    CancelOrderLog,
248    CANCEL_ORDER_LOG_DISCRIMINANT,
249    test_cancel_order
250);
251discriminant!(
252    GlobalCreateLog,
253    GLOBAL_CREATE_LOG_DISCRIMINANT,
254    test_global_create_log
255);
256discriminant!(
257    GlobalAddTraderLog,
258    GLOBAL_ADD_TRADER_LOG_DISCRIMINANT,
259    test_global_add_trader_log
260);
261discriminant!(
262    GlobalClaimSeatLog,
263    GLOBAL_CLAIM_SEAT_LOG_DISCRIMINANT,
264    test_global_claim_seat_log
265);
266discriminant!(
267    GlobalDepositLog,
268    GLOBAL_DEPOSIT_LOG_DISCRIMINANT,
269    test_global_deposit_log
270);
271discriminant!(
272    GlobalWithdrawLog,
273    GLOBAL_WITHDRAW_LOG_DISCRIMINANT,
274    test_global_withdraw_log
275);
276discriminant!(
277    GlobalEvictLog,
278    GLOBAL_EVICT_LOG_DISCRIMINANT,
279    test_global_evict_log
280);
281discriminant!(
282    GlobalCleanupLog,
283    GLOBAL_CLEANUP_LOG_DISCRIMINANT,
284    test_global_cleanup_log
285);