zo_abi/
lib.rs

1#![doc = include_str!("../README.md")]
2
3mod types;
4mod util;
5use anchor_lang::prelude::*;
6use solana_program::pubkey;
7
8pub mod dex;
9pub mod events;
10pub use crate::types::*;
11pub use crate::util::*;
12
13#[cfg(feature = "devnet")]
14declare_id!("Zo1ThtSHMh9tZGECwBDL81WJRL6s3QTHf733Tyko7KQ");
15
16#[cfg(not(feature = "devnet"))]
17declare_id!("Zo1ggzTUKMY5bYnDvT5mtVeZxzf2FaLTbKkmvGUhUQk");
18
19pub static ZO_DEX_PID: Pubkey = match cfg!(feature = "devnet") {
20    true => pubkey!("ZDxUi178LkcuwdxcEqsSo2E7KATH99LAAXN5LcSVMBC"),
21    false => pubkey!("ZDx8a8jBqGmJyxi1whFxxCo5vG6Q9t4hTzW2GSixMKK"),
22};
23
24pub static SERUM_DEX_PID: Pubkey = match cfg!(feature = "devnet") {
25    true => pubkey!("DESVgJVGajEgKGXhb6XmqDHGz3VjdgP7rEVESBgxmroY"),
26    false => pubkey!("9xQeWvG816bUx9EPjHmaT23yvVM2ZWbrrpZb9PusVFin"),
27};
28
29pub static ZO_STATE_ID: Pubkey = match cfg!(feature = "devnet") {
30    true => pubkey!("KwcWW7WvgSXLJcyjKZJBHLbfriErggzYHpjS9qjVD5F"),
31    false => pubkey!("71yykwxq1zQqy99PgRsgZJXi2HHK2UDx9G4va7pH6qRv"),
32};
33
34pub static ZO_HEIMDALL_ID: Pubkey = match cfg!(feature = "devnet") {
35    true => pubkey!("Aoi3SGj4zLiMQSHrJ4yEDFwMQnGjVQCeKSYD6ygi6WLr"),
36    false => pubkey!("Cyvjas5Hg6nb6RNsuCi8sK3kcjbWzTgdJcHxmSYS8mkY"),
37};
38
39#[program]
40mod zo_abi {
41    #![allow(dead_code)]
42    #![allow(unused_variables)]
43    #![allow(clippy::too_many_arguments)]
44
45    use super::*;
46
47    // ========== MARGIN ==========
48
49    pub(crate) fn create_margin(
50        cx: Context<CreateMargin>,
51        margin_nonce: u8,
52    ) -> Result<()> {
53        Ok(())
54    }
55
56    pub(crate) fn deposit(
57        cx: Context<Deposit>,
58        repay_only: bool,
59        amount: u64,
60    ) -> Result<()> {
61        Ok(())
62    }
63
64    pub(crate) fn withdraw(
65        cx: Context<Withdraw>,
66        allow_borrow: bool,
67        amount: u64,
68    ) -> Result<()> {
69        Ok(())
70    }
71
72    // ========== TRADING ==========
73
74    /// Creates a trader's open orders account for a given market
75    pub(crate) fn create_perp_open_orders(
76        cx: Context<CreatePerpOpenOrders>,
77    ) -> Result<()> {
78        Ok(())
79    }
80
81    /// Places a new order
82    pub(crate) fn place_perp_order(
83        cx: Context<PlacePerpOrder>,
84        is_long: bool,
85        limit_price: u64,
86        max_base_quantity: u64,
87        max_quote_quantity: u64,
88        order_type: OrderType,
89        limit: u16,
90        client_id: u64,
91    ) -> Result<()> {
92        Ok(())
93    }
94
95    /// Places a new order with max timestamp. If current on-chain timestamp exceeds
96    /// max timestamp, then order will not go through
97    pub(crate) fn place_perp_order_with_max_ts(
98        cx: Context<PlacePerpOrder>,
99        is_long: bool,
100        limit_price: u64,
101        max_base_quantity: u64,
102        max_quote_quantity: u64,
103        order_type: OrderType,
104        limit: u16,
105        client_id: u64,
106        max_ts: i64,
107    ) -> Result<()> {
108        Ok(())
109    }
110
111    /// Places a new order (lite version uses less compute, does not settle funds automatically)
112    /// Currently only available on devnet
113    pub(crate) fn place_perp_order_lite(
114        cx: Context<PlacePerpOrder>,
115        is_long: bool,
116        limit_price: u64,
117        max_base_quantity: u64,
118        max_quote_quantity: u64,
119        order_type: OrderType,
120        limit: u16,
121        client_id: u64,
122    ) -> Result<()> {
123        Ok(())
124    }
125
126    /// Cancels an order on the book, using either `order_id` and `is_long` or only `client_id`.
127    pub(crate) fn cancel_perp_order(
128        cx: Context<CancelPerpOrder>,
129        order_id: Option<u128>,
130        is_long: Option<bool>,
131        client_id: Option<u64>,
132    ) -> Result<()> {
133        Ok(())
134    }
135
136    /// Cancels all orders on the book
137    pub(crate) fn cancel_all_perp_orders(
138        cx: Context<CancelAllPerpOrders>,
139        limit: u16,
140    ) -> Result<()> {
141        Ok(())
142    }
143
144    /// Settles unrealized funding and realized pnl into the margin account
145    pub(crate) fn settle_funds(cx: Context<SettleFunds>) -> Result<()> {
146        Ok(())
147    }
148
149    /// Swaps two tokens on a single A/B market, where A is the base currency
150    /// and B is the quote currency. This is just a direct IOC trade that
151    /// instantly settles.
152    ///
153    /// When side is "bid", then swaps B for A. When side is "ask", then swaps
154    /// A for B.
155    pub(crate) fn swap(
156        cx: Context<Swap>,
157        buy: bool,
158        allow_borrow: bool, // whether the withdraw currency can go below 0
159        amount: u64,        // smol amount to swap *from*
160        min_rate: u64, // number of smol tokens received from a single big token given
161    ) -> Result<()> {
162        Ok(())
163    }
164
165    // ========== KEEPERS ==========
166
167    pub(crate) fn update_perp_funding(
168        cx: Context<UpdatePerpFunding>,
169    ) -> Result<()> {
170        Ok(())
171    }
172
173    pub(crate) fn cache_oracle(
174        cx: Context<CacheOracle>,
175        symbols: Vec<String>,
176        mock_prices: Option<Vec<Option<u64>>>,
177    ) -> Result<()> {
178        Ok(())
179    }
180
181    pub(crate) fn cache_interest_rates(
182        cx: Context<CacheInterestRates>,
183        start: u8,
184        end: u8,
185    ) -> Result<()> {
186        Ok(())
187    }
188
189    pub(crate) fn consume_events(
190        cx: Context<ConsumeEvents>,
191        limit: u16,
192    ) -> Result<()> {
193        Ok(())
194    }
195
196    pub(crate) fn crank_pnl(cx: Context<CrankPnl>) -> Result<()> {
197        Ok(())
198    }
199
200    // ========== LIQUIDATION ==========
201
202    /// Force cancels all orders of an account under liquidation
203    pub(crate) fn force_cancel_all_perp_orders(
204        cx: Context<ForceCancelAllPerpOrders>,
205        limit: u16,
206    ) -> Result<()> {
207        Ok(())
208    }
209
210    /// Liquidates a perp position by transferring it from the liqee to the liqor
211    pub(crate) fn liquidate_perp_position(
212        cx: Context<LiquidatePerpPosition>,
213        asset_transfer_lots: u64,
214    ) -> Result<()> {
215        Ok(())
216    }
217
218    /// Liquidates a spot position by transferring it from the liqee to the liqor
219    pub(crate) fn liquidate_spot_position(
220        cx: Context<LiquidateSpotPosition>,
221        asset_transfer_amount: i64,
222    ) -> Result<()> {
223        Ok(())
224    }
225
226    /// Transfer negative borrows from liqee to liqor, and subsidize through insurance fund
227    pub(crate) fn settle_bankruptcy(
228        cx: Context<SettleBankruptcy>,
229    ) -> Result<()> {
230        Ok(())
231    }
232
233    // ========== SPECIAL ==========
234
235    pub fn create_special_orders_account(
236        cx: Context<CreateSpecialOrdersAccount>,
237    ) -> Result<()> {
238        Ok(())
239    }
240
241    pub(crate) fn place_special_order(
242        cx: Context<PlaceSpecialOrder>,
243        is_long: bool,
244        special_order_type: SpecialOrderType,
245        trigger_price: u64,
246        limit_price: u64,
247        size: u64,
248    ) -> Result<()> {
249        Ok(())
250    }
251
252    pub(crate) fn cancel_special_order(
253        cx: Context<CancelSpecialOrder>,
254        id: u16,
255    ) -> Result<()> {
256        Ok(())
257    }
258
259    pub(crate) fn execute_special_order(
260        cx: Context<ExecuteSpecialOrder>,
261        id: u16,
262    ) -> Result<()> {
263        Ok(())
264    }
265}
266
267#[derive(Accounts)]
268struct SettleFunds<'info> {
269    pub authority: Signer<'info>,
270    pub state: AccountLoader<'info, State>,
271    #[account(mut)]
272    pub state_signer: UncheckedAccount<'info>,
273    #[account(mut)]
274    pub cache: AccountLoader<'info, Cache>,
275    #[account(mut)]
276    pub margin: AccountLoader<'info, Margin>,
277    #[account(mut)]
278    pub control: AccountLoader<'info, Control>,
279    #[account(mut)]
280    pub open_orders: UncheckedAccount<'info>,
281    #[account(mut)]
282    pub dex_market: UncheckedAccount<'info>,
283    pub dex_program: UncheckedAccount<'info>,
284}
285
286#[derive(Accounts)]
287struct CancelPerpOrder<'info> {
288    pub state: AccountLoader<'info, State>,
289    #[account(mut)]
290    pub cache: AccountLoader<'info, Cache>,
291    pub authority: Signer<'info>,
292    #[account(mut)]
293    pub margin: AccountLoader<'info, Margin>,
294    #[account(mut)]
295    pub control: AccountLoader<'info, Control>,
296    #[account(mut)]
297    pub open_orders: UncheckedAccount<'info>,
298    #[account(mut)]
299    pub dex_market: UncheckedAccount<'info>,
300    #[account(mut)]
301    pub market_bids: UncheckedAccount<'info>,
302    #[account(mut)]
303    pub market_asks: UncheckedAccount<'info>,
304    #[account(mut)]
305    pub event_q: UncheckedAccount<'info>,
306    pub dex_program: UncheckedAccount<'info>,
307}
308
309#[derive(Accounts)]
310struct CancelAllPerpOrders<'info> {
311    pub authority: Signer<'info>,
312    pub state: AccountLoader<'info, State>,
313    #[account(mut)]
314    pub cache: AccountLoader<'info, Cache>,
315    #[account(mut)]
316    pub state_signer: UncheckedAccount<'info>,
317    #[account(mut)]
318    pub margin: AccountLoader<'info, Margin>,
319    #[account(mut)]
320    pub control: AccountLoader<'info, Control>,
321    #[account(mut)]
322    pub open_orders: UncheckedAccount<'info>,
323    #[account(mut)]
324    pub dex_market: UncheckedAccount<'info>,
325    #[account(mut)]
326    pub req_q: UncheckedAccount<'info>,
327    #[account(mut)]
328    pub event_q: UncheckedAccount<'info>,
329    #[account(mut)]
330    pub market_bids: UncheckedAccount<'info>,
331    #[account(mut)]
332    pub market_asks: UncheckedAccount<'info>,
333    pub dex_program: UncheckedAccount<'info>,
334}
335
336#[derive(Accounts)]
337struct CreatePerpOpenOrders<'info> {
338    pub state: AccountLoader<'info, State>,
339    #[account(mut)]
340    pub state_signer: UncheckedAccount<'info>,
341    pub authority: Signer<'info>,
342    // if authority is a pda, use a non-pda as payer
343    #[account(mut)]
344    pub payer: Signer<'info>,
345    #[account(mut)]
346    pub margin: AccountLoader<'info, Margin>,
347    #[account(mut)]
348    pub control: AccountLoader<'info, Control>,
349    #[account(mut)]
350    pub open_orders: UncheckedAccount<'info>,
351    #[account(mut)]
352    pub dex_market: UncheckedAccount<'info>,
353    pub dex_program: UncheckedAccount<'info>,
354    pub rent: Sysvar<'info, Rent>,
355    pub system_program: Program<'info, System>,
356}
357
358#[derive(Accounts)]
359struct CreateMargin<'info> {
360    pub state: AccountInfo<'info>,
361    pub authority: Signer<'info>,
362    // if authority is a pda, use a non-pda as payer
363    #[account(mut)]
364    pub payer: Signer<'info>,
365    /// Must be an uninitialized Keypair with
366    /// `seeds = [authority.key.as_ref(), state.key().as_ref(), b\"marginv1\".as_ref()]`
367    #[account(mut)]
368    pub margin: AccountInfo<'info>,
369    /// The control account must be created as a pre-instruction, with the correct size, and with
370    /// the zo program as the owner. Current size is 8 + 4482
371    #[account(zero)]
372    pub control: AccountInfo<'info>,
373    pub rent: AccountInfo<'info>,
374    pub system_program: AccountInfo<'info>,
375}
376
377#[derive(Accounts)]
378struct Deposit<'info> {
379    pub state: AccountInfo<'info>,
380    /// ` seeds = [state.key().as_ref()] `
381    pub state_signer: AccountInfo<'info>,
382    #[account(mut)]
383    pub cache: AccountInfo<'info>,
384    pub authority: Signer<'info>,
385    #[account(mut)]
386    pub margin: AccountInfo<'info>,
387    #[account(mut)]
388    pub token_account: AccountInfo<'info>,
389    /// Vault pubkey can be found from the State account
390    #[account(mut)]
391    pub vault: AccountInfo<'info>,
392    pub token_program: AccountInfo<'info>,
393}
394
395#[derive(Accounts)]
396struct Withdraw<'info> {
397    #[account(mut)]
398    pub state: AccountInfo<'info>,
399    /// ` seeds = [state.key().as_ref()] `
400    #[account(mut)]
401    pub state_signer: AccountInfo<'info>,
402    #[account(mut)]
403    pub cache: AccountInfo<'info>,
404    pub authority: Signer<'info>,
405    #[account(mut)]
406    pub margin: AccountInfo<'info>,
407    #[account(mut)]
408    pub control: AccountInfo<'info>,
409    #[account(mut)]
410    pub token_account: AccountInfo<'info>,
411    /// Vault pubkey can be found from the State account
412    #[account(mut)]
413    pub vault: AccountInfo<'info>,
414    pub token_program: AccountInfo<'info>,
415    /// This should be `zo_abi::ZO_HEIMDALL_ID`. Alternatively,
416    /// you can generated the PDA with `seeds = [b\"heimdallv1\".as_ref()]`.
417    #[account(mut)]
418    pub heimdall: AccountInfo<'info>,
419}
420
421#[derive(Accounts)]
422struct UpdatePerpFunding<'info> {
423    pub state: AccountInfo<'info>,
424    #[account(mut)]
425    pub state_signer: AccountInfo<'info>,
426    #[account(mut)]
427    pub cache: AccountInfo<'info>,
428    #[account(mut)]
429    pub dex_market: AccountInfo<'info>,
430    #[account(mut)]
431    pub market_bids: AccountInfo<'info>,
432    #[account(mut)]
433    pub market_asks: AccountInfo<'info>,
434    #[account(address = ZO_DEX_PID)]
435    pub dex_program: AccountInfo<'info>,
436}
437
438/// Price info accounts are passed in remaining accounts array,
439/// followed by the relevant dex market accounts.
440#[derive(Accounts)]
441struct CacheOracle<'info> {
442    pub signer: Signer<'info>,
443    pub state: AccountInfo<'info>,
444    #[account(mut)]
445    pub cache: AccountInfo<'info>,
446    #[account(address = ZO_DEX_PID)]
447    pub dex_program: AccountInfo<'info>,
448}
449
450#[derive(Accounts)]
451struct CacheInterestRates<'info> {
452    pub signer: Signer<'info>,
453    pub state: AccountInfo<'info>,
454    #[account(mut)]
455    pub cache: AccountInfo<'info>,
456}
457
458#[derive(Accounts)]
459struct ConsumeEvents<'info> {
460    #[account(mut)]
461    pub state: AccountInfo<'info>,
462    #[account(mut)]
463    pub state_signer: AccountInfo<'info>,
464    pub dex_program: AccountInfo<'info>,
465    #[account(mut)]
466    pub market: AccountInfo<'info>,
467    #[account(mut)]
468    pub event_queue: AccountInfo<'info>,
469    // RA: [alice_control, bob_control, ..., alice_oo, bob_oo, ...]
470}
471
472#[derive(Accounts)]
473struct CrankPnl<'info> {
474    pub state: AccountInfo<'info>,
475    #[account(mut)]
476    pub state_signer: AccountInfo<'info>,
477    #[account(mut)]
478    pub cache: AccountInfo<'info>,
479    pub dex_program: AccountInfo<'info>,
480    #[account(mut)]
481    pub market: AccountInfo<'info>,
482    // RA: [alice_control, bob_control, ..., alice_oo, bob_oo, ..., alice_margin, bob_margin, ...]
483}
484
485#[derive(Accounts)]
486struct ForceCancelAllPerpOrders<'info> {
487    pub pruner: Signer<'info>,
488    pub state: AccountInfo<'info>,
489    #[account(mut)]
490    pub cache: AccountInfo<'info>,
491    #[account(mut)]
492    pub state_signer: AccountInfo<'info>,
493    #[account(mut)]
494    pub liqee_margin: AccountInfo<'info>,
495    #[account(mut)]
496    pub liqee_control: AccountInfo<'info>,
497    #[account(mut)]
498    pub liqee_oo: AccountInfo<'info>,
499    #[account(mut)]
500    pub dex_market: AccountInfo<'info>,
501    #[account(mut)]
502    pub req_q: AccountInfo<'info>,
503    #[account(mut)]
504    pub event_q: AccountInfo<'info>,
505    #[account(mut)]
506    pub market_bids: AccountInfo<'info>,
507    #[account(mut)]
508    pub market_asks: AccountInfo<'info>,
509    #[account(address = ZO_DEX_PID)]
510    pub dex_program: AccountInfo<'info>,
511}
512
513#[derive(Accounts)]
514struct LiquidatePerpPosition<'info> {
515    pub state: AccountInfo<'info>,
516    #[account(mut)]
517    pub cache: AccountInfo<'info>,
518    #[account(mut)]
519    pub state_signer: AccountInfo<'info>,
520    pub liqor: Signer<'info>,
521    #[account(mut)]
522    pub liqor_margin: AccountInfo<'info>,
523    #[account(mut)]
524    pub liqor_control: AccountInfo<'info>,
525    #[account(mut)]
526    pub liqor_oo: AccountInfo<'info>,
527    pub liqee: AccountInfo<'info>,
528    #[account(mut)]
529    pub liqee_margin: AccountInfo<'info>,
530    #[account(mut)]
531    pub liqee_control: AccountInfo<'info>,
532    #[account(mut)]
533    pub liqee_oo: AccountInfo<'info>,
534    #[account(mut)]
535    pub dex_market: AccountInfo<'info>,
536    #[account(mut)]
537    pub req_q: AccountInfo<'info>,
538    #[account(mut)]
539    pub event_q: AccountInfo<'info>,
540    #[account(mut)]
541    pub market_bids: AccountInfo<'info>,
542    #[account(mut)]
543    pub market_asks: AccountInfo<'info>,
544    #[account(address = ZO_DEX_PID)]
545    pub dex_program: AccountInfo<'info>,
546}
547
548#[derive(Accounts)]
549struct LiquidateSpotPosition<'info> {
550    pub state: AccountInfo<'info>,
551    #[account(mut)]
552    pub cache: AccountInfo<'info>,
553    pub liqor: Signer<'info>,
554    #[account(mut)]
555    pub liqor_margin: AccountInfo<'info>,
556    #[account(mut)]
557    pub liqor_control: AccountInfo<'info>,
558    #[account(mut)]
559    pub liqee_margin: AccountInfo<'info>,
560    #[account(mut)]
561    pub liqee_control: AccountInfo<'info>,
562    pub asset_mint: AccountInfo<'info>,
563    pub quote_mint: AccountInfo<'info>,
564}
565
566#[derive(Accounts)]
567struct PlacePerpOrder<'info> {
568    pub state: AccountInfo<'info>,
569    #[account(mut)]
570    pub state_signer: AccountInfo<'info>,
571    #[account(mut)]
572    pub cache: AccountInfo<'info>,
573    pub authority: Signer<'info>,
574    #[account(mut)]
575    pub margin: AccountInfo<'info>,
576    #[account(mut)]
577    pub control: AccountInfo<'info>,
578    #[account(mut)]
579    pub open_orders: AccountInfo<'info>,
580    #[account(mut)]
581    pub dex_market: AccountInfo<'info>,
582    #[account(mut)]
583    pub req_q: AccountInfo<'info>,
584    #[account(mut)]
585    pub event_q: AccountInfo<'info>,
586    #[account(mut)]
587    pub market_bids: AccountInfo<'info>,
588    #[account(mut)]
589    pub market_asks: AccountInfo<'info>,
590    #[account(address = ZO_DEX_PID)]
591    pub dex_program: AccountInfo<'info>,
592    pub rent: AccountInfo<'info>,
593}
594
595#[derive(Accounts)]
596struct SettleBankruptcy<'info> {
597    #[account(mut)]
598    pub state: AccountInfo<'info>,
599    #[account(mut)]
600    pub state_signer: AccountInfo<'info>,
601    #[account(mut)]
602    pub cache: AccountInfo<'info>,
603    pub liqor: Signer<'info>,
604    #[account(mut)]
605    pub liqor_margin: AccountInfo<'info>,
606    #[account(mut)]
607    pub liqor_control: AccountInfo<'info>,
608    #[account(mut)]
609    pub liqee_margin: AccountInfo<'info>,
610    #[account(mut)]
611    pub liqee_control: AccountInfo<'info>,
612    pub asset_mint: AccountInfo<'info>,
613}
614
615#[derive(Accounts)]
616struct Swap<'info> {
617    pub authority: Signer<'info>,
618    #[account(mut)]
619    pub state: AccountInfo<'info>,
620    pub state_signer: AccountInfo<'info>,
621    #[account(mut)]
622    pub cache: AccountInfo<'info>,
623    #[account(mut)]
624    pub margin: AccountInfo<'info>,
625    #[account(mut)]
626    pub control: AccountInfo<'info>,
627    /// For the dex, this is the _quote_ mint. However, for zo, quote
628    /// refers to the collateral at index 0, normally USDC.
629    pub quote_mint: AccountInfo<'info>,
630    #[account(mut)]
631    pub quote_vault: AccountInfo<'info>,
632    pub asset_mint: AccountInfo<'info>,
633    #[account(mut)]
634    pub asset_vault: AccountInfo<'info>,
635    #[account(mut)]
636    pub swap_fee_vault: AccountInfo<'info>,
637    #[account(mut)]
638    pub serum_open_orders: AccountInfo<'info>,
639    #[account(mut)]
640    pub serum_market: AccountInfo<'info>,
641    #[account(mut)]
642    pub serum_request_queue: AccountInfo<'info>,
643    #[account(mut)]
644    pub serum_event_queue: AccountInfo<'info>,
645    #[account(mut)]
646    pub serum_bids: AccountInfo<'info>,
647    #[account(mut)]
648    pub serum_asks: AccountInfo<'info>,
649    #[account(mut)]
650    pub serum_coin_vault: AccountInfo<'info>,
651    #[account(mut)]
652    pub serum_pc_vault: AccountInfo<'info>,
653    pub serum_vault_signer: AccountInfo<'info>,
654    #[account(address = SERUM_DEX_PID)]
655    pub srm_spot_program: AccountInfo<'info>,
656    pub token_program: AccountInfo<'info>,
657    pub rent: AccountInfo<'info>,
658}
659
660#[derive(Accounts)]
661pub struct CreateSpecialOrdersAccount<'info> {
662    pub state: AccountLoader<'info, State>,
663    pub authority: Signer<'info>,
664    #[account(mut)]
665    pub payer: Signer<'info>,
666    /// `seeds = [authority.key.as_ref(), state.key().as_ref(), b\"sordersv1\".as_ref()]`
667    #[account(mut)]
668    pub special_orders: AccountLoader<'info, SpecialOrders>,
669    pub rent: Sysvar<'info, Rent>,
670    pub system_program: Program<'info, System>,
671}
672
673#[derive(Accounts)]
674pub struct PlaceSpecialOrder<'info> {
675    pub state: AccountLoader<'info, State>,
676    pub authority: Signer<'info>,
677    /// `seeds = [authority.key.as_ref(), state.key().as_ref(), b\"sordersv1\".as_ref()]`
678    #[account(mut)]
679    pub special_orders: AccountLoader<'info, SpecialOrders>,
680    pub dex_market: AccountInfo<'info>,
681    pub system_program: Program<'info, System>,
682}
683
684#[derive(Accounts)]
685pub struct CancelSpecialOrder<'info> {
686    pub state: AccountLoader<'info, State>,
687    pub authority: Signer<'info>,
688    /// `seeds = [authority.key.as_ref(), state.key().as_ref(), b\"sordersv1\".as_ref()]`
689    #[account(mut)]
690    pub special_orders: AccountLoader<'info, SpecialOrders>,
691    pub dex_market: AccountInfo<'info>,
692}
693
694#[derive(Accounts)]
695pub struct ExecuteSpecialOrder<'info> {
696    pub state: AccountLoader<'info, State>,
697    #[account(mut)]
698    pub state_signer: UncheckedAccount<'info>,
699    #[account(mut)]
700    pub cache: AccountLoader<'info, Cache>,
701    #[account(mut)]
702    pub payer: Signer<'info>,
703    pub authority: AccountInfo<'info>,
704    #[account(mut)]
705    pub margin: AccountLoader<'info, Margin>,
706    #[account(mut)]
707    pub control: AccountLoader<'info, Control>,
708    /// `seeds = [authority.key.as_ref(), state.key().as_ref(), b\"sordersv1\".as_ref()]`
709    #[account(mut)]
710    pub special_orders: AccountLoader<'info, SpecialOrders>,
711    #[account(mut)]
712    pub open_orders: UncheckedAccount<'info>,
713    #[account(mut)]
714    pub dex_market: UncheckedAccount<'info>,
715    #[account(mut)]
716    pub req_q: UncheckedAccount<'info>,
717    #[account(mut)]
718    pub event_q: UncheckedAccount<'info>,
719    #[account(mut)]
720    pub market_bids: UncheckedAccount<'info>,
721    #[account(mut)]
722    pub market_asks: UncheckedAccount<'info>,
723    #[account(address = ZO_DEX_PID)]
724    pub dex_program: UncheckedAccount<'info>,
725    pub rent: Sysvar<'info, Rent>,
726}