manifest/program/processor/
global_clean.rs1use std::cell::RefMut;
2
3use borsh::{BorshDeserialize, BorshSerialize};
4use hypertree::{get_helper, trace, DataIndex, RBNode};
5use solana_program::{account_info::AccountInfo, entrypoint::ProgramResult, pubkey::Pubkey};
6
7use crate::{
8 program::{batch_update::MarketDataTreeNodeType, get_mut_dynamic_account},
9 quantities::{GlobalAtoms, WrapperU64},
10 require,
11 state::{utils::get_now_slot, GlobalRefMut, MarketRefMut, RestingOrder, MARKET_BLOCK_SIZE},
12 validation::loaders::{GlobalCleanContext, GlobalTradeAccounts},
13};
14
15#[derive(BorshDeserialize, BorshSerialize)]
16pub struct GlobalCleanParams {
17 pub order_index: DataIndex,
18}
19
20impl GlobalCleanParams {
21 pub fn new(order_index: DataIndex) -> Self {
22 GlobalCleanParams { order_index }
23 }
24}
25
26pub(crate) fn process_global_clean(
27 _program_id: &Pubkey,
28 accounts: &[AccountInfo],
29 data: &[u8],
30) -> ProgramResult {
31 trace!("process_global_clean accs={accounts:?}");
32 let global_clean_context: GlobalCleanContext = GlobalCleanContext::load(accounts)?;
33
34 let GlobalCleanContext {
35 payer,
36 market,
37 global,
38 system_program,
39 } = global_clean_context;
40
41 let global_trade_accounts: GlobalTradeAccounts = GlobalTradeAccounts {
42 mint_opt: None,
43 global: global.clone(),
44 global_vault_opt: None,
45 market_vault_opt: None,
46 token_program_opt: None,
47 system_program: Some(system_program),
48 market: *market.key,
49 gas_payer_opt: None,
50 gas_receiver_opt: Some(payer),
51 };
52
53 let GlobalCleanParams { order_index } = GlobalCleanParams::try_from_slice(data)?;
54
55 let market_data: &mut RefMut<&mut [u8]> = &mut market.try_borrow_mut_data()?;
56 let mut market_dynamic_account: MarketRefMut = get_mut_dynamic_account(market_data);
57
58 let global_data: &mut RefMut<&mut [u8]> = &mut global.try_borrow_mut_data()?;
59 let global_dynamic_account: GlobalRefMut = get_mut_dynamic_account(global_data);
60
61 let resting_order: &RestingOrder = {
64 require!(
66 order_index % (MARKET_BLOCK_SIZE as DataIndex) == 0,
67 crate::program::ManifestError::WrongIndexHintParams,
68 "Invalid order index {}",
69 order_index,
70 )?;
71 let resting_order_node: &RBNode<RestingOrder> =
72 get_helper::<RBNode<RestingOrder>>(&market_dynamic_account.dynamic, order_index);
73 require!(
74 resting_order_node.get_payload_type() == MarketDataTreeNodeType::RestingOrder as u8,
75 crate::program::ManifestError::WrongIndexHintParams,
76 "Invalid order index {}",
77 order_index,
78 )?;
79
80 let resting_order: &RestingOrder = resting_order_node.get_value();
81 let expected_global_mint: &Pubkey = if resting_order.get_is_bid() {
82 market_dynamic_account.get_quote_mint()
83 } else {
84 market_dynamic_account.get_base_mint()
85 };
86 let global_mint: &Pubkey = global_dynamic_account.fixed.get_mint();
87
88 require!(
90 *expected_global_mint == *global_mint,
91 crate::program::ManifestError::InvalidClean,
92 "Wrong global provided",
93 )?;
94
95 resting_order
99 };
100 let maker_index: DataIndex = resting_order.get_trader_index();
101 let maker: &Pubkey = market_dynamic_account.get_trader_key_by_index(maker_index);
102
103 let is_expired: bool = resting_order.is_expired(get_now_slot());
105 let maker_global_balance: GlobalAtoms = global_dynamic_account.get_balance_atoms(maker);
107 let required_global_atoms: u64 = if resting_order.get_is_bid() {
108 resting_order
109 .get_num_base_atoms()
110 .checked_mul(resting_order.get_price(), false)
111 .unwrap()
112 .as_u64()
113 } else {
114 resting_order.get_num_base_atoms().as_u64()
115 };
116
117 require!(
118 is_expired || maker_global_balance.as_u64() < required_global_atoms,
119 crate::program::ManifestError::InvalidClean,
120 "Ineligible clean order index {}",
121 order_index,
122 )?;
123
124 let global_trade_accounts: [Option<GlobalTradeAccounts>; 2] = if resting_order.get_is_bid() {
126 [None, Some(global_trade_accounts)]
127 } else {
128 [Some(global_trade_accounts), None]
129 };
130
131 market_dynamic_account.cancel_order_by_index(order_index, &global_trade_accounts)?;
135
136 Ok(())
141}