1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
use crate::{
error::AoError,
orderbook::OrderBookState,
state::{AccountTag, EventQueueHeader, MarketState, EVENT_QUEUE_HEADER_LEN},
utils::{check_account_key, check_account_owner, check_signer},
};
use borsh::{BorshDeserialize, BorshSerialize};
use solana_program::{
account_info::{next_account_info, AccountInfo},
entrypoint::ProgramResult,
msg,
program_error::ProgramError,
pubkey::Pubkey,
};
#[derive(BorshDeserialize, BorshSerialize)]
pub struct Params {}
struct Accounts<'a, 'b: 'a> {
market: &'a AccountInfo<'b>,
event_queue: &'a AccountInfo<'b>,
bids: &'a AccountInfo<'b>,
asks: &'a AccountInfo<'b>,
authority: &'a AccountInfo<'b>,
lamports_target_account: &'a AccountInfo<'b>,
}
impl<'a, 'b: 'a> Accounts<'a, 'b> {
pub fn parse(
program_id: &Pubkey,
accounts: &'a [AccountInfo<'b>],
) -> Result<Self, ProgramError> {
let accounts_iter = &mut accounts.iter();
let a = Self {
market: next_account_info(accounts_iter)?,
event_queue: next_account_info(accounts_iter)?,
bids: next_account_info(accounts_iter)?,
asks: next_account_info(accounts_iter)?,
authority: next_account_info(accounts_iter)?,
lamports_target_account: next_account_info(accounts_iter)?,
};
check_account_owner(a.market, program_id)?;
check_signer(a.authority)?;
Ok(a)
}
}
pub(crate) fn process(program_id: &Pubkey, accounts: &[AccountInfo]) -> ProgramResult {
let accounts = Accounts::parse(program_id, accounts)?;
let mut market_state = {
let mut market_data: &[u8] = &accounts.market.data.borrow();
MarketState::deserialize(&mut market_data)
.unwrap()
.check()?
};
check_account_key(accounts.event_queue, &market_state.event_queue)
.map_err(|_| AoError::WrongEventQueueAccount)?;
check_account_key(accounts.bids, &market_state.bids).map_err(|_| AoError::WrongBidsAccount)?;
check_account_key(accounts.asks, &market_state.asks).map_err(|_| AoError::WrongAsksAccount)?;
check_account_key(accounts.authority, &market_state.caller_authority)
.map_err(|_| AoError::WrongCallerAuthority)?;
let orderbook_state = OrderBookState::new_safe(
accounts.bids,
accounts.asks,
market_state.callback_info_len as usize,
market_state.callback_id_len as usize,
)
.unwrap();
if !orderbook_state.is_empty() {
msg!("The orderbook must be empty");
return Err(ProgramError::from(AoError::MarketStillActive));
}
let header = {
let mut event_queue_data: &[u8] =
&accounts.event_queue.data.borrow()[0..EVENT_QUEUE_HEADER_LEN];
EventQueueHeader::deserialize(&mut event_queue_data).unwrap()
};
if header.count != 0 {
msg!("The event queue needs to be empty");
return Err(ProgramError::from(AoError::MarketStillActive));
}
market_state.tag = AccountTag::Uninitialized;
let mut market_state_data: &mut [u8] = &mut accounts.market.data.borrow_mut();
market_state.serialize(&mut market_state_data).unwrap();
let mut market_lamports = accounts.market.lamports.borrow_mut();
let mut bids_lamports = accounts.bids.lamports.borrow_mut();
let mut asks_lamports = accounts.asks.lamports.borrow_mut();
let mut event_queue_lamports = accounts.event_queue.lamports.borrow_mut();
let mut target_lamports = accounts.lamports_target_account.lamports.borrow_mut();
**target_lamports +=
**market_lamports + **bids_lamports + **asks_lamports + **event_queue_lamports;
**market_lamports = 0;
**bids_lamports = 0;
**asks_lamports = 0;
**event_queue_lamports = 0;
Ok(())
}