1use std::{cell::Ref, slice::Iter};
2
3use hypertree::{get_helper, trace};
4use solana_program::{
5 account_info::{next_account_info, AccountInfo},
6 program_error::ProgramError,
7 pubkey::Pubkey,
8 system_program,
9};
10
11use crate::{
12 program::ManifestError,
13 require,
14 state::{GlobalFixed, MarketFixed},
15 validation::{EmptyAccount, MintAccountInfo, Program, Signer, TokenAccountInfo},
16};
17
18use super::{get_vault_address, ManifestAccountInfo, TokenProgram};
19
20#[cfg(feature = "certora")]
21use early_panic::early_panic;
22
23pub(crate) struct CreateMarketContext<'a, 'info> {
25 pub payer: Signer<'a, 'info>,
26 pub market: ManifestAccountInfo<'a, 'info, MarketFixed>,
27 pub base_mint: MintAccountInfo<'a, 'info>,
28 pub quote_mint: MintAccountInfo<'a, 'info>,
29 pub base_vault: EmptyAccount<'a, 'info>,
30 pub quote_vault: EmptyAccount<'a, 'info>,
31 pub system_program: Program<'a, 'info>,
32 pub token_program: TokenProgram<'a, 'info>,
33 pub token_program_22: TokenProgram<'a, 'info>,
34}
35
36impl<'a, 'info> CreateMarketContext<'a, 'info> {
37 pub fn load(accounts: &'a [AccountInfo<'info>]) -> Result<Self, ProgramError> {
38 let account_iter: &mut Iter<AccountInfo<'info>> = &mut accounts.iter();
39
40 let payer: Signer = Signer::new_payer(next_account_info(account_iter)?)?;
41 let market: ManifestAccountInfo<MarketFixed> =
42 ManifestAccountInfo::<MarketFixed>::new_init(next_account_info(account_iter)?)?;
43 let system_program: Program =
44 Program::new(next_account_info(account_iter)?, &system_program::id())?;
45 let base_mint: MintAccountInfo = MintAccountInfo::new(next_account_info(account_iter)?)?;
46 let quote_mint: MintAccountInfo = MintAccountInfo::new(next_account_info(account_iter)?)?;
47 let base_vault: EmptyAccount = EmptyAccount::new(next_account_info(account_iter)?)?;
48 let quote_vault: EmptyAccount = EmptyAccount::new(next_account_info(account_iter)?)?;
49
50 let (expected_base_vault, _base_vault_bump) =
51 get_vault_address(market.key, base_mint.info.key);
52 let (expected_quote_vault, _quote_vault_bump) =
53 get_vault_address(market.key, quote_mint.info.key);
54
55 require!(
56 expected_base_vault == *base_vault.info.key,
57 ManifestError::IncorrectAccount,
58 "Incorrect base vault account",
59 )?;
60 require!(
61 expected_quote_vault == *quote_vault.info.key,
62 ManifestError::IncorrectAccount,
63 "Incorrect quote vault account",
64 )?;
65 let token_program: TokenProgram = TokenProgram::new(next_account_info(account_iter)?)?;
66 let token_program_22: TokenProgram = TokenProgram::new(next_account_info(account_iter)?)?;
67
68 Ok(Self {
69 payer,
70 market,
71 base_vault,
72 quote_vault,
73 base_mint,
74 quote_mint,
75 token_program,
76 token_program_22,
77 system_program,
78 })
79 }
80}
81
82pub(crate) struct ClaimSeatContext<'a, 'info> {
84 pub payer: Signer<'a, 'info>,
85 pub market: ManifestAccountInfo<'a, 'info, MarketFixed>,
86 pub _system_program: Program<'a, 'info>,
87}
88
89impl<'a, 'info> ClaimSeatContext<'a, 'info> {
90 #[cfg_attr(all(feature = "certora", not(feature = "certora-test")), early_panic)]
91 pub fn load(accounts: &'a [AccountInfo<'info>]) -> Result<Self, ProgramError> {
92 let account_iter: &mut Iter<AccountInfo<'info>> = &mut accounts.iter();
93
94 let payer: Signer = Signer::new(next_account_info(account_iter)?)?;
95 let market: ManifestAccountInfo<MarketFixed> =
96 ManifestAccountInfo::<MarketFixed>::new(next_account_info(account_iter)?)?;
97 let _system_program: Program =
98 Program::new(next_account_info(account_iter)?, &system_program::id())?;
99 Ok(Self {
100 payer,
101 market,
102 _system_program,
103 })
104 }
105}
106
107pub(crate) struct ExpandMarketContext<'a, 'info> {
109 pub payer: Signer<'a, 'info>,
110 pub market: ManifestAccountInfo<'a, 'info, MarketFixed>,
111 pub _system_program: Program<'a, 'info>,
112}
113
114impl<'a, 'info> ExpandMarketContext<'a, 'info> {
115 pub fn load(accounts: &'a [AccountInfo<'info>]) -> Result<Self, ProgramError> {
116 let account_iter: &mut Iter<AccountInfo<'info>> = &mut accounts.iter();
117
118 let payer: Signer = Signer::new_payer(next_account_info(account_iter)?)?;
119 let market: ManifestAccountInfo<MarketFixed> =
120 ManifestAccountInfo::<MarketFixed>::new(next_account_info(account_iter)?)?;
121 let _system_program: Program =
122 Program::new(next_account_info(account_iter)?, &system_program::id())?;
123 Ok(Self {
124 payer,
125 market,
126 _system_program,
127 })
128 }
129}
130
131pub(crate) struct DepositContext<'a, 'info> {
133 pub payer: Signer<'a, 'info>,
134 pub market: ManifestAccountInfo<'a, 'info, MarketFixed>,
135 pub trader_token: TokenAccountInfo<'a, 'info>,
136 pub vault: TokenAccountInfo<'a, 'info>,
137 pub token_program: TokenProgram<'a, 'info>,
138 pub mint: MintAccountInfo<'a, 'info>,
139}
140
141impl<'a, 'info> DepositContext<'a, 'info> {
142 #[cfg_attr(all(feature = "certora", not(feature = "certora-test")), early_panic)]
143 pub fn load(accounts: &'a [AccountInfo<'info>]) -> Result<Self, ProgramError> {
144 let account_iter: &mut Iter<AccountInfo<'info>> = &mut accounts.iter();
145
146 let payer: Signer = Signer::new(next_account_info(account_iter)?)?;
147 let market: ManifestAccountInfo<MarketFixed> =
148 ManifestAccountInfo::<MarketFixed>::new(next_account_info(account_iter)?)?;
149
150 let market_fixed: Ref<MarketFixed> = market.get_fixed()?;
151 let base_mint: &Pubkey = market_fixed.get_base_mint();
152 let quote_mint: &Pubkey = market_fixed.get_quote_mint();
153
154 let token_account_info: &AccountInfo<'info> = next_account_info(account_iter)?;
155
156 let (mint, expected_vault_address) =
158 if &token_account_info.try_borrow_data()?[0..32] == base_mint.as_ref() {
159 (base_mint, market_fixed.get_base_vault())
160 } else if &token_account_info.try_borrow_data()?[0..32] == quote_mint.as_ref() {
161 (quote_mint, market_fixed.get_quote_vault())
162 } else {
163 return Err(ManifestError::InvalidWithdrawAccounts.into());
164 };
165
166 trace!("trader token account {:?}", token_account_info.key);
167 let trader_token: TokenAccountInfo =
168 TokenAccountInfo::new_with_owner(token_account_info, mint, payer.key)?;
169
170 trace!("vault token account {:?}", expected_vault_address);
171 let vault: TokenAccountInfo = TokenAccountInfo::new_with_owner_and_key(
172 next_account_info(account_iter)?,
173 mint,
174 &expected_vault_address,
175 &expected_vault_address,
176 )?;
177
178 let token_program: TokenProgram = TokenProgram::new(next_account_info(account_iter)?)?;
179 let mint: MintAccountInfo = MintAccountInfo::new(next_account_info(account_iter)?)?;
180
181 drop(market_fixed);
183 Ok(Self {
184 payer,
185 market,
186 trader_token,
187 vault,
188 token_program,
189 mint,
190 })
191 }
192}
193
194pub(crate) struct WithdrawContext<'a, 'info> {
196 pub payer: Signer<'a, 'info>,
197 pub market: ManifestAccountInfo<'a, 'info, MarketFixed>,
198 pub trader_token: TokenAccountInfo<'a, 'info>,
199 pub vault: TokenAccountInfo<'a, 'info>,
200 pub token_program: TokenProgram<'a, 'info>,
201 pub mint: MintAccountInfo<'a, 'info>,
202}
203
204impl<'a, 'info> WithdrawContext<'a, 'info> {
205 pub fn load(accounts: &'a [AccountInfo<'info>]) -> Result<Self, ProgramError> {
206 let account_iter: &mut Iter<AccountInfo<'info>> = &mut accounts.iter();
207
208 let payer: Signer = Signer::new(next_account_info(account_iter)?)?;
209 let market: ManifestAccountInfo<MarketFixed> =
210 ManifestAccountInfo::<MarketFixed>::new(next_account_info(account_iter)?)?;
211
212 let market_fixed: Ref<MarketFixed> = market.get_fixed()?;
213 let base_mint: &Pubkey = market_fixed.get_base_mint();
214 let quote_mint: &Pubkey = market_fixed.get_quote_mint();
215
216 let token_account_info: &AccountInfo<'info> = next_account_info(account_iter)?;
217
218 let (mint, expected_vault_address) =
219 if &token_account_info.try_borrow_data()?[0..32] == base_mint.as_ref() {
220 (base_mint, market_fixed.get_base_vault())
221 } else if &token_account_info.try_borrow_data()?[0..32] == quote_mint.as_ref() {
222 (quote_mint, market_fixed.get_quote_vault())
223 } else {
224 return Err(ManifestError::InvalidWithdrawAccounts.into());
225 };
226
227 let trader_token: TokenAccountInfo =
228 TokenAccountInfo::new_with_owner(token_account_info, mint, payer.key)?;
229 let vault: TokenAccountInfo = TokenAccountInfo::new_with_owner_and_key(
230 next_account_info(account_iter)?,
231 mint,
232 &expected_vault_address,
233 &expected_vault_address,
234 )?;
235
236 let token_program: TokenProgram = TokenProgram::new(next_account_info(account_iter)?)?;
237 let mint: MintAccountInfo = MintAccountInfo::new(next_account_info(account_iter)?)?;
238
239 drop(market_fixed);
241 Ok(Self {
242 payer,
243 market,
244 trader_token,
245 vault,
246 token_program,
247 mint,
248 })
249 }
250}
251
252pub(crate) struct SwapContext<'a, 'info> {
254 pub payer: Signer<'a, 'info>,
255 pub market: ManifestAccountInfo<'a, 'info, MarketFixed>,
256 pub trader_base: TokenAccountInfo<'a, 'info>,
257 pub trader_quote: TokenAccountInfo<'a, 'info>,
258 pub base_vault: TokenAccountInfo<'a, 'info>,
259 pub quote_vault: TokenAccountInfo<'a, 'info>,
260 pub token_program_base: TokenProgram<'a, 'info>,
261 pub token_program_quote: TokenProgram<'a, 'info>,
262 pub base_mint: Option<MintAccountInfo<'a, 'info>>,
263 pub quote_mint: Option<MintAccountInfo<'a, 'info>>,
264
265 pub global_trade_accounts_opts: [Option<GlobalTradeAccounts<'a, 'info>>; 2],
267}
268
269impl<'a, 'info> SwapContext<'a, 'info> {
270 #[cfg_attr(all(feature = "certora", not(feature = "certora-test")), early_panic)]
271 pub fn load(accounts: &'a [AccountInfo<'info>]) -> Result<Self, ProgramError> {
272 let account_iter: &mut Iter<AccountInfo<'info>> = &mut accounts.iter();
273
274 let payer: Signer = Signer::new(next_account_info(account_iter)?)?;
275 let market: ManifestAccountInfo<MarketFixed> =
276 ManifestAccountInfo::<MarketFixed>::new(next_account_info(account_iter)?)?;
277 let _system_program: Program =
279 Program::new(next_account_info(account_iter)?, &system_program::id())?;
280
281 let market_fixed: Ref<MarketFixed> = market.get_fixed()?;
282 let base_mint_key: Pubkey = *market_fixed.get_base_mint();
283 let quote_mint_key: Pubkey = *market_fixed.get_quote_mint();
284
285 let trader_base: TokenAccountInfo = TokenAccountInfo::new_with_owner(
286 next_account_info(account_iter)?,
287 &base_mint_key,
288 payer.key,
289 )?;
290 let trader_quote: TokenAccountInfo = TokenAccountInfo::new_with_owner(
291 next_account_info(account_iter)?,
292 "e_mint_key,
293 payer.key,
294 )?;
295 let base_vault_address: &Pubkey = market_fixed.get_base_vault();
296 let quote_vault_address: &Pubkey = market_fixed.get_quote_vault();
297
298 let base_vault: TokenAccountInfo = TokenAccountInfo::new_with_owner_and_key(
299 next_account_info(account_iter)?,
300 &base_mint_key,
301 &base_vault_address,
302 &base_vault_address,
303 )?;
304 let quote_vault: TokenAccountInfo = TokenAccountInfo::new_with_owner_and_key(
305 next_account_info(account_iter)?,
306 "e_mint_key,
307 "e_vault_address,
308 "e_vault_address,
309 )?;
310 drop(market_fixed);
311
312 let token_program_base: TokenProgram = TokenProgram::new(next_account_info(account_iter)?)?;
313 let mut base_mint: Option<MintAccountInfo> = None;
314
315 let mut current_account_info_or: Result<&AccountInfo<'info>, ProgramError> =
316 next_account_info(account_iter);
317
318 if current_account_info_or
320 .as_ref()
321 .is_ok_and(|f| *f.owner == spl_token::id() || *f.owner == spl_token_2022::id())
322 {
323 let current_account_info: &AccountInfo<'info> = current_account_info_or?;
324 base_mint = Some(MintAccountInfo::new(current_account_info)?);
325 current_account_info_or = next_account_info(account_iter);
326 }
327
328 let mut token_program_quote: TokenProgram = token_program_base.clone();
331 let mut quote_mint: Option<MintAccountInfo> = None;
332 let mut global_trade_accounts_opts: [Option<GlobalTradeAccounts<'a, 'info>>; 2] =
333 [None, None];
334
335 if current_account_info_or
337 .as_ref()
338 .is_ok_and(|f| *f.key == spl_token::id() || *f.key == spl_token_2022::id())
339 {
340 let current_account_info: &AccountInfo<'info> = current_account_info_or?;
341 token_program_quote = TokenProgram::new(current_account_info)?;
342 current_account_info_or = next_account_info(account_iter);
343 }
344 if current_account_info_or
346 .as_ref()
347 .is_ok_and(|f| *f.owner == spl_token::id() || *f.owner == spl_token_2022::id())
348 {
349 let current_account_info: &AccountInfo<'info> = current_account_info_or?;
350 quote_mint = Some(MintAccountInfo::new(current_account_info)?);
351 current_account_info_or = next_account_info(account_iter);
352 }
353
354 if current_account_info_or.is_ok() {
355 let current_account_info: &AccountInfo<'info> = current_account_info_or?;
356
357 if !current_account_info.data_is_empty() {
361 let global: ManifestAccountInfo<'a, 'info, GlobalFixed> =
362 ManifestAccountInfo::<GlobalFixed>::new(current_account_info)?;
363 let global_data: Ref<&mut [u8]> = global.data.borrow();
364 let global_fixed: &GlobalFixed = get_helper::<GlobalFixed>(&global_data, 0_u32);
365 let global_mint_key: &Pubkey = global_fixed.get_mint();
366 let expected_global_vault_address: &Pubkey = global_fixed.get_vault();
367
368 let global_vault: TokenAccountInfo<'a, 'info> =
369 TokenAccountInfo::new_with_owner_and_key(
370 next_account_info(account_iter)?,
371 global_mint_key,
372 &expected_global_vault_address,
373 &expected_global_vault_address,
374 )?;
375
376 let index: usize = if *global_mint_key == base_mint_key {
377 0
378 } else {
379 require!(
380 quote_mint_key == *global_mint_key,
381 ManifestError::MissingGlobal,
382 "Unexpected global accounts",
383 )?;
384 1
385 };
386
387 drop(global_data);
388 global_trade_accounts_opts[index] = Some(GlobalTradeAccounts {
389 mint_opt: if index == 0 {
390 base_mint.clone()
391 } else {
392 quote_mint.clone()
393 },
394 global,
395 global_vault_opt: Some(global_vault),
396 market_vault_opt: if index == 0 {
397 Some(base_vault.clone())
398 } else {
399 Some(quote_vault.clone())
400 },
401 token_program_opt: if index == 0 {
402 Some(token_program_base.clone())
403 } else {
404 Some(token_program_quote.clone())
405 },
406 gas_payer_opt: None,
407 gas_receiver_opt: Some(payer.clone()),
408 market: *market.info.key,
409 system_program: None,
410 });
411 }
412 }
413
414 Ok(Self {
415 payer,
416 market,
417 trader_base,
418 trader_quote,
419 base_vault,
420 quote_vault,
421 token_program_base,
422 token_program_quote,
423 base_mint,
424 quote_mint,
425 global_trade_accounts_opts,
426 })
427 }
428}
429
430pub struct GlobalTradeAccounts<'a, 'info> {
433 pub mint_opt: Option<MintAccountInfo<'a, 'info>>,
435 pub global: ManifestAccountInfo<'a, 'info, GlobalFixed>,
436
437 pub global_vault_opt: Option<TokenAccountInfo<'a, 'info>>,
440 pub market_vault_opt: Option<TokenAccountInfo<'a, 'info>>,
441 pub token_program_opt: Option<TokenProgram<'a, 'info>>,
442
443 pub system_program: Option<Program<'a, 'info>>,
444
445 pub gas_payer_opt: Option<Signer<'a, 'info>>,
448 pub gas_receiver_opt: Option<Signer<'a, 'info>>,
449 pub market: Pubkey,
450}
451
452pub(crate) struct BatchUpdateContext<'a, 'info> {
454 pub payer: Signer<'a, 'info>,
455 pub market: ManifestAccountInfo<'a, 'info, MarketFixed>,
456 pub _system_program: Program<'a, 'info>,
457
458 pub global_trade_accounts_opts: [Option<GlobalTradeAccounts<'a, 'info>>; 2],
460}
461
462impl<'a, 'info> BatchUpdateContext<'a, 'info> {
463 pub fn load(accounts: &'a [AccountInfo<'info>]) -> Result<Self, ProgramError> {
464 let account_iter: &mut Iter<AccountInfo<'info>> = &mut accounts.iter();
465
466 let payer: Signer = Signer::new(next_account_info(account_iter)?)?;
469 let market: ManifestAccountInfo<MarketFixed> =
470 ManifestAccountInfo::<MarketFixed>::new(next_account_info(account_iter)?)?;
471 let system_program: Program =
472 Program::new(next_account_info(account_iter)?, &system_program::id())?;
473 #[cfg(feature = "certora")]
475 let global_trade_accounts_opts: [Option<GlobalTradeAccounts<'a, 'info>>; 2] = [None, None];
476 #[cfg(not(feature = "certora"))]
477 let mut global_trade_accounts_opts: [Option<GlobalTradeAccounts<'a, 'info>>; 2] =
478 [None, None];
479
480 #[cfg(not(feature = "certora"))]
481 {
482 let market_fixed: Ref<MarketFixed> = market.get_fixed()?;
483 let base_mint: Pubkey = *market_fixed.get_base_mint();
484 let quote_mint: Pubkey = *market_fixed.get_quote_mint();
485 let base_vault: Pubkey = *market_fixed.get_base_vault();
486 let quote_vault: Pubkey = *market_fixed.get_quote_vault();
487 drop(market_fixed);
488
489 for _ in 0..2 {
490 let next_account_info_or: Result<&AccountInfo<'info>, ProgramError> =
491 next_account_info(account_iter);
492 if next_account_info_or.is_ok() {
493 let mint: MintAccountInfo<'a, 'info> =
494 MintAccountInfo::new(next_account_info_or?)?;
495 let (index, expected_market_vault_address) = if base_mint == *mint.info.key {
496 (0, &base_vault)
497 } else {
498 require!(
499 quote_mint == *mint.info.key,
500 ManifestError::MissingGlobal,
501 "Unexpected global mint",
502 )?;
503 (1, "e_vault)
504 };
505
506 let global_or: Result<
507 ManifestAccountInfo<'a, 'info, GlobalFixed>,
508 ProgramError,
509 > = ManifestAccountInfo::<GlobalFixed>::new(next_account_info(account_iter)?);
510
511 if global_or.is_err() {
515 let _global_vault: Result<&AccountInfo<'info>, ProgramError> =
516 next_account_info(account_iter);
517 let _market_vault: Result<&AccountInfo<'info>, ProgramError> =
518 next_account_info(account_iter);
519 let _token_program: Result<&AccountInfo<'info>, ProgramError> =
520 next_account_info(account_iter);
521 continue;
522 }
523 let global: ManifestAccountInfo<'a, 'info, GlobalFixed> = global_or.unwrap();
524 let global_data: Ref<&mut [u8]> = global.data.borrow();
525 let global_fixed: &GlobalFixed = get_helper::<GlobalFixed>(&global_data, 0_u32);
526 let expected_global_vault_address: &Pubkey = global_fixed.get_vault();
527
528 let global_vault: TokenAccountInfo<'a, 'info> =
529 TokenAccountInfo::new_with_owner_and_key(
530 next_account_info(account_iter)?,
531 mint.info.key,
532 &expected_global_vault_address,
533 &expected_global_vault_address,
534 )?;
535 drop(global_data);
536
537 let market_vault: TokenAccountInfo<'a, 'info> =
538 TokenAccountInfo::new_with_owner_and_key(
539 next_account_info(account_iter)?,
540 mint.info.key,
541 &expected_market_vault_address,
542 &expected_market_vault_address,
543 )?;
544 let token_program: TokenProgram<'a, 'info> =
545 TokenProgram::new(next_account_info(account_iter)?)?;
546
547 global_trade_accounts_opts[index] = Some(GlobalTradeAccounts {
548 mint_opt: Some(mint),
549 global,
550 global_vault_opt: Some(global_vault),
551 market_vault_opt: Some(market_vault),
552 token_program_opt: Some(token_program),
553 system_program: Some(system_program.clone()),
554 gas_payer_opt: Some(payer.clone()),
555 gas_receiver_opt: Some(payer.clone()),
556 market: *market.info.key,
557 })
558 };
559 }
560 }
561
562 Ok(Self {
563 payer,
564 market,
565 _system_program: system_program,
566 global_trade_accounts_opts,
567 })
568 }
569}
570
571pub(crate) struct GlobalCreateContext<'a, 'info> {
573 pub payer: Signer<'a, 'info>,
574 pub global: EmptyAccount<'a, 'info>,
575 pub system_program: Program<'a, 'info>,
576 pub global_mint: MintAccountInfo<'a, 'info>,
577 pub global_vault: EmptyAccount<'a, 'info>,
578 pub token_program: TokenProgram<'a, 'info>,
579}
580
581impl<'a, 'info> GlobalCreateContext<'a, 'info> {
582 pub fn load(accounts: &'a [AccountInfo<'info>]) -> Result<Self, ProgramError> {
583 let account_iter: &mut Iter<AccountInfo<'info>> = &mut accounts.iter();
584
585 let payer: Signer = Signer::new_payer(next_account_info(account_iter)?)?;
586 let global: EmptyAccount = EmptyAccount::new(next_account_info(account_iter)?)?;
587 let system_program: Program =
588 Program::new(next_account_info(account_iter)?, &system_program::id())?;
589 let global_mint: MintAccountInfo = MintAccountInfo::new(next_account_info(account_iter)?)?;
590 let global_vault: EmptyAccount = EmptyAccount::new(next_account_info(account_iter)?)?;
593 let token_program: TokenProgram = TokenProgram::new(next_account_info(account_iter)?)?;
594 Ok(Self {
595 payer,
596 global,
597 system_program,
598 global_mint,
599 global_vault,
600 token_program,
601 })
602 }
603}
604
605pub(crate) struct GlobalAddTraderContext<'a, 'info> {
607 pub payer: Signer<'a, 'info>,
608 pub global: ManifestAccountInfo<'a, 'info, GlobalFixed>,
609 pub _system_program: Program<'a, 'info>,
610}
611
612impl<'a, 'info> GlobalAddTraderContext<'a, 'info> {
613 pub fn load(accounts: &'a [AccountInfo<'info>]) -> Result<Self, ProgramError> {
614 let account_iter: &mut Iter<AccountInfo<'info>> = &mut accounts.iter();
615
616 let payer: Signer = Signer::new_payer(next_account_info(account_iter)?)?;
617 let global: ManifestAccountInfo<GlobalFixed> =
618 ManifestAccountInfo::<GlobalFixed>::new(next_account_info(account_iter)?)?;
619 let _system_program: Program =
620 Program::new(next_account_info(account_iter)?, &system_program::id())?;
621 Ok(Self {
622 payer,
623 global,
624 _system_program,
625 })
626 }
627}
628
629pub(crate) struct GlobalDepositContext<'a, 'info> {
631 pub payer: Signer<'a, 'info>,
632 pub global: ManifestAccountInfo<'a, 'info, GlobalFixed>,
633 pub mint: MintAccountInfo<'a, 'info>,
634 pub global_vault: TokenAccountInfo<'a, 'info>,
635 pub trader_token: TokenAccountInfo<'a, 'info>,
636 pub token_program: TokenProgram<'a, 'info>,
637}
638
639impl<'a, 'info> GlobalDepositContext<'a, 'info> {
640 pub fn load(accounts: &'a [AccountInfo<'info>]) -> Result<Self, ProgramError> {
641 let account_iter: &mut Iter<AccountInfo<'info>> = &mut accounts.iter();
642
643 let payer: Signer = Signer::new(next_account_info(account_iter)?)?;
644 let global: ManifestAccountInfo<GlobalFixed> =
645 ManifestAccountInfo::<GlobalFixed>::new(next_account_info(account_iter)?)?;
646
647 let mint: MintAccountInfo = MintAccountInfo::new(next_account_info(account_iter)?)?;
648
649 let global_data: Ref<&mut [u8]> = global.data.borrow();
650 let global_fixed: &GlobalFixed = get_helper::<GlobalFixed>(&global_data, 0_u32);
651 let expected_global_vault_address: &Pubkey = global_fixed.get_vault();
652
653 let global_vault: TokenAccountInfo = TokenAccountInfo::new_with_owner_and_key(
654 next_account_info(account_iter)?,
655 mint.info.key,
656 &expected_global_vault_address,
657 &expected_global_vault_address,
658 )?;
659 drop(global_data);
660
661 let token_account_info: &AccountInfo<'info> = next_account_info(account_iter)?;
662 let trader_token: TokenAccountInfo =
663 TokenAccountInfo::new_with_owner(token_account_info, mint.info.key, payer.key)?;
664 let token_program: TokenProgram = TokenProgram::new(next_account_info(account_iter)?)?;
665 Ok(Self {
666 payer,
667 global,
668 mint,
669 global_vault,
670 trader_token,
671 token_program,
672 })
673 }
674}
675
676pub(crate) struct GlobalWithdrawContext<'a, 'info> {
678 pub payer: Signer<'a, 'info>,
679 pub global: ManifestAccountInfo<'a, 'info, GlobalFixed>,
680 pub mint: MintAccountInfo<'a, 'info>,
681 pub global_vault: TokenAccountInfo<'a, 'info>,
682 pub trader_token: TokenAccountInfo<'a, 'info>,
683 pub token_program: TokenProgram<'a, 'info>,
684}
685
686impl<'a, 'info> GlobalWithdrawContext<'a, 'info> {
687 pub fn load(accounts: &'a [AccountInfo<'info>]) -> Result<Self, ProgramError> {
688 let account_iter: &mut Iter<AccountInfo<'info>> = &mut accounts.iter();
689
690 let payer: Signer = Signer::new(next_account_info(account_iter)?)?;
691 let global: ManifestAccountInfo<GlobalFixed> =
692 ManifestAccountInfo::<GlobalFixed>::new(next_account_info(account_iter)?)?;
693
694 let mint: MintAccountInfo = MintAccountInfo::new(next_account_info(account_iter)?)?;
695
696 let global_data: Ref<&mut [u8]> = global.data.borrow();
697 let global_fixed: &GlobalFixed = get_helper::<GlobalFixed>(&global_data, 0_u32);
698 let expected_global_vault_address: &Pubkey = global_fixed.get_vault();
699
700 let global_vault: TokenAccountInfo = TokenAccountInfo::new_with_owner_and_key(
701 next_account_info(account_iter)?,
702 mint.info.key,
703 &expected_global_vault_address,
704 &expected_global_vault_address,
705 )?;
706 drop(global_data);
707
708 let token_account_info: &AccountInfo<'info> = next_account_info(account_iter)?;
709 let trader_token: TokenAccountInfo =
710 TokenAccountInfo::new_with_owner(token_account_info, mint.info.key, payer.key)?;
711 let token_program: TokenProgram = TokenProgram::new(next_account_info(account_iter)?)?;
712 Ok(Self {
713 payer,
714 global,
715 mint,
716 global_vault,
717 trader_token,
718 token_program,
719 })
720 }
721}
722
723pub(crate) struct GlobalEvictContext<'a, 'info> {
725 pub payer: Signer<'a, 'info>,
726 pub global: ManifestAccountInfo<'a, 'info, GlobalFixed>,
727 pub mint: MintAccountInfo<'a, 'info>,
728 pub global_vault: TokenAccountInfo<'a, 'info>,
729 pub trader_token: TokenAccountInfo<'a, 'info>,
730 pub evictee_token: TokenAccountInfo<'a, 'info>,
731 pub token_program: TokenProgram<'a, 'info>,
732}
733
734impl<'a, 'info> GlobalEvictContext<'a, 'info> {
735 pub fn load(accounts: &'a [AccountInfo<'info>]) -> Result<Self, ProgramError> {
736 let account_iter: &mut Iter<AccountInfo<'info>> = &mut accounts.iter();
737
738 let payer: Signer = Signer::new_payer(next_account_info(account_iter)?)?;
739 let global: ManifestAccountInfo<GlobalFixed> =
740 ManifestAccountInfo::<GlobalFixed>::new(next_account_info(account_iter)?)?;
741
742 let mint: MintAccountInfo = MintAccountInfo::new(next_account_info(account_iter)?)?;
743
744 let global_data: Ref<&mut [u8]> = global.data.borrow();
745 let global_fixed: &GlobalFixed = get_helper::<GlobalFixed>(&global_data, 0_u32);
746 let expected_global_vault_address: &Pubkey = global_fixed.get_vault();
747
748 let global_vault: TokenAccountInfo = TokenAccountInfo::new_with_owner_and_key(
749 next_account_info(account_iter)?,
750 mint.info.key,
751 &expected_global_vault_address,
752 &expected_global_vault_address,
753 )?;
754 drop(global_data);
755
756 let token_account_info: &AccountInfo<'info> = next_account_info(account_iter)?;
757 let trader_token: TokenAccountInfo =
758 TokenAccountInfo::new_with_owner(token_account_info, mint.info.key, payer.key)?;
759 let token_account_info: &AccountInfo<'info> = next_account_info(account_iter)?;
760 let evictee_token: TokenAccountInfo =
761 TokenAccountInfo::new(token_account_info, mint.info.key)?;
762 let token_program: TokenProgram = TokenProgram::new(next_account_info(account_iter)?)?;
763 Ok(Self {
764 payer,
765 global,
766 mint,
767 global_vault,
768 trader_token,
769 evictee_token,
770 token_program,
771 })
772 }
773}
774
775pub(crate) struct GlobalCleanContext<'a, 'info> {
777 pub payer: Signer<'a, 'info>,
778 pub market: ManifestAccountInfo<'a, 'info, MarketFixed>,
779 pub system_program: Program<'a, 'info>,
780 pub global: ManifestAccountInfo<'a, 'info, GlobalFixed>,
781}
782
783impl<'a, 'info> GlobalCleanContext<'a, 'info> {
784 pub fn load(accounts: &'a [AccountInfo<'info>]) -> Result<Self, ProgramError> {
785 let account_iter: &mut Iter<AccountInfo<'info>> = &mut accounts.iter();
786
787 let payer: Signer = Signer::new_payer(next_account_info(account_iter)?)?;
788 let market: ManifestAccountInfo<MarketFixed> =
789 ManifestAccountInfo::<MarketFixed>::new(next_account_info(account_iter)?)?;
790 let system_program: Program =
791 Program::new(next_account_info(account_iter)?, &system_program::id())?;
792 let global: ManifestAccountInfo<GlobalFixed> =
793 ManifestAccountInfo::<GlobalFixed>::new(next_account_info(account_iter)?)?;
794
795 Ok(Self {
796 payer,
797 market,
798 system_program,
799 global,
800 })
801 }
802}