MangoAccount: Fixes after audit

This commit is contained in:
Christian Kamm 2022-08-29 15:36:21 +02:00
parent d63c5bfc76
commit 7d508e5df5
4 changed files with 38 additions and 42 deletions

View File

@ -1159,7 +1159,7 @@ mod tests {
// Run a health test that includes all the side values (like referrer_rebates_accrued)
#[test]
fn test_health0() {
let buffer = MangoAccount::default().try_to_vec().unwrap();
let buffer = MangoAccount::default_for_tests().try_to_vec().unwrap();
let mut account = MangoAccountValue::from_bytes(&buffer).unwrap();
let group = Pubkey::new_unique();
@ -1338,7 +1338,7 @@ mod tests {
expected_health: f64,
}
fn test_health1_runner(testcase: &TestHealth1Case) {
let buffer = MangoAccount::default().try_to_vec().unwrap();
let buffer = MangoAccount::default_for_tests().try_to_vec().unwrap();
let mut account = MangoAccountValue::from_bytes(&buffer).unwrap();
let group = Pubkey::new_unique();

View File

@ -103,8 +103,8 @@ pub struct MangoAccount {
pub perp_open_orders: Vec<PerpOpenOrder>,
}
impl Default for MangoAccount {
fn default() -> Self {
impl MangoAccount {
pub fn default_for_tests() -> Self {
Self {
name: Default::default(),
group: Pubkey::default(),
@ -131,9 +131,8 @@ impl Default for MangoAccount {
perp_open_orders: vec![PerpOpenOrder::default(); 2],
}
}
}
impl MangoAccount {
/// Number of bytes needed for the MangoAccount, including the discriminator
pub fn space(
token_count: u8,
serum3_count: u8,
@ -185,7 +184,7 @@ impl MangoAccount {
#[test]
fn test_serialization_match() {
let mut account = MangoAccount::default();
let mut account = MangoAccount::default_for_tests();
account.group = Pubkey::new_unique();
account.owner = Pubkey::new_unique();
account.name = crate::util::fill_from_str("abcdef").unwrap();
@ -502,13 +501,11 @@ impl<
// get iter over all active TokenPositions
pub fn active_token_positions(&self) -> impl Iterator<Item = &TokenPosition> + '_ {
(0..self.header().token_count())
.map(|i| self.token_position_by_raw_index(i))
.filter(|token| token.is_active())
self.all_token_positions().filter(|token| token.is_active())
}
pub fn serum3_orders(&self, market_index: Serum3MarketIndex) -> Option<&Serum3Orders> {
self.active_serum3_orders()
self.all_serum3_orders()
.find(|p| p.is_active_for_market(market_index))
}
@ -521,13 +518,12 @@ impl<
}
pub fn active_serum3_orders(&self) -> impl Iterator<Item = &Serum3Orders> + '_ {
(0..self.header().serum3_count())
.map(|i| self.serum3_orders_by_raw_index(i))
self.all_serum3_orders()
.filter(|serum3_order| serum3_order.is_active())
}
pub fn perp_position(&self, market_index: PerpMarketIndex) -> Option<&PerpPosition> {
self.active_perp_positions()
self.all_perp_positions()
.find(|p| p.is_active_for_market(market_index))
}
@ -540,17 +536,15 @@ impl<
}
pub fn active_perp_positions(&self) -> impl Iterator<Item = &PerpPosition> {
(0..self.header().perp_count())
.map(|i| self.perp_position_by_raw_index(i))
.filter(|p| p.is_active())
self.all_perp_positions().filter(|p| p.is_active())
}
pub fn perp_orders_by_raw_index(&self, raw_index: usize) -> &PerpOpenOrder {
pub fn perp_order_by_raw_index(&self, raw_index: usize) -> &PerpOpenOrder {
get_helper(self.dynamic(), self.header().perp_oo_offset(raw_index))
}
pub fn all_perp_orders(&self) -> impl Iterator<Item = &PerpOpenOrder> {
(0..self.header().perp_oo_count()).map(|i| self.perp_orders_by_raw_index(i))
(0..self.header().perp_oo_count()).map(|i| self.perp_order_by_raw_index(i))
}
pub fn perp_next_order_slot(&self) -> Option<usize> {
@ -563,8 +557,7 @@ impl<
market_index: PerpMarketIndex,
client_order_id: u64,
) -> Option<(i128, Side)> {
for i in 0..self.header().perp_oo_count() {
let oo = self.perp_orders_by_raw_index(i);
for oo in self.all_perp_orders() {
if oo.order_market == market_index && oo.client_order_id == client_order_id {
return Some((oo.order_id, oo.order_side));
}
@ -577,8 +570,7 @@ impl<
market_index: PerpMarketIndex,
order_id: i128,
) -> Option<Side> {
for i in 0..self.header().perp_oo_count() {
let oo = self.perp_orders_by_raw_index(i);
for oo in self.all_perp_orders() {
if oo.order_market == market_index && oo.order_id == order_id {
return Some(oo.order_side);
}
@ -730,7 +722,7 @@ impl<
market_index: Serum3MarketIndex,
) -> Option<&mut Serum3Orders> {
let raw_index_opt = self
.active_serum3_orders()
.all_serum3_orders()
.position(|p| p.is_active_for_market(market_index));
raw_index_opt.map(|raw_index| self.serum3_orders_mut_by_raw_index(raw_index))
}
@ -741,7 +733,7 @@ impl<
get_helper_mut(self.dynamic_mut(), offset)
}
pub fn perp_orders_mut_by_raw_index(&mut self, raw_index: usize) -> &mut PerpOpenOrder {
pub fn perp_order_mut_by_raw_index(&mut self, raw_index: usize) -> &mut PerpOpenOrder {
let offset = self.header().perp_oo_offset(raw_index);
get_helper_mut(self.dynamic_mut(), offset)
}
@ -751,7 +743,7 @@ impl<
perp_market_index: PerpMarketIndex,
) -> Result<(&mut PerpPosition, usize)> {
let mut raw_index_opt = self
.active_perp_positions()
.all_perp_positions()
.position(|p| p.is_active_for_market(perp_market_index));
if raw_index_opt.is_none() {
raw_index_opt = self.all_perp_positions().position(|p| !p.is_active());
@ -779,6 +771,7 @@ impl<
side: Side,
order: &LeafNode,
) -> Result<()> {
// TODO: pass in the PerpPosition, currently has a creation side-effect
let mut perp_account = self.ensure_perp_position(perp_market_index).unwrap().0;
match side {
Side::Bid => {
@ -790,7 +783,7 @@ impl<
};
let slot = order.owner_slot as usize;
let mut oo = self.perp_orders_mut_by_raw_index(slot);
let mut oo = self.perp_order_mut_by_raw_index(slot);
oo.order_market = perp_market_index;
oo.order_side = side;
oo.order_id = order.key;
@ -799,8 +792,9 @@ impl<
}
pub fn remove_perp_order(&mut self, slot: usize, quantity: i64) -> Result<()> {
// TODO: pass in the PerpPosition, currently has a creation side-effect
{
let oo = self.perp_orders_mut_by_raw_index(slot);
let oo = self.perp_order_mut_by_raw_index(slot);
require_neq!(oo.order_market, FREE_ORDER_SLOT);
let order_side = oo.order_side;
let perp_market_index = oo.order_market;
@ -818,7 +812,7 @@ impl<
}
// release space
let oo = self.perp_orders_mut_by_raw_index(slot);
let oo = self.perp_order_mut_by_raw_index(slot);
oo.order_market = FREE_ORDER_SLOT;
oo.order_side = Side::Bid;
oo.order_id = 0i128;
@ -832,6 +826,7 @@ impl<
perp_market: &mut PerpMarket,
fill: &FillEvent,
) -> Result<()> {
// TODO: pass in the PerpPosition, currently has a creation side-effect
let pa = self.ensure_perp_position(perp_market_index).unwrap().0;
pa.settle_funding(perp_market);
@ -871,6 +866,7 @@ impl<
perp_market: &mut PerpMarket,
fill: &FillEvent,
) -> Result<()> {
// TODO: pass in the PerpPosition, currently has a creation side-effect
let pa = self.ensure_perp_position(perp_market_index).unwrap().0;
pa.settle_funding(perp_market);

View File

@ -393,7 +393,7 @@ impl<'a> Book<'a> {
side_to_cancel_option: Option<Side>,
) -> Result<()> {
for i in 0..mango_account.header.perp_oo_count() {
let oo = mango_account.perp_orders_by_raw_index(i);
let oo = mango_account.perp_order_by_raw_index(i);
if oo.order_market == FREE_ORDER_SLOT
|| oo.order_market != perp_market.perp_market_index
{

View File

@ -101,7 +101,7 @@ mod tests {
let mut new_order =
|book: &mut Book, event_queue: &mut EventQueue, side, price, now_ts| -> i128 {
let buffer = MangoAccount::default().try_to_vec().unwrap();
let buffer = MangoAccount::default_for_tests().try_to_vec().unwrap();
let mut account = MangoAccountValue::from_bytes(&buffer).unwrap();
let quantity = 1;
@ -124,7 +124,7 @@ mod tests {
u8::MAX,
)
.unwrap();
account.perp_orders_by_raw_index(0).order_id
account.perp_order_by_raw_index(0).order_id
};
// insert bids until book side is full
@ -196,7 +196,7 @@ mod tests {
market.maker_fee = I80F48::from_num(-0.001f64);
market.taker_fee = I80F48::from_num(0.01f64);
let buffer = MangoAccount::default().try_to_vec().unwrap();
let buffer = MangoAccount::default_for_tests().try_to_vec().unwrap();
let mut maker = MangoAccountValue::from_bytes(&buffer).unwrap();
let mut taker = MangoAccountValue::from_bytes(&buffer).unwrap();
@ -225,19 +225,19 @@ mod tests {
)
.unwrap();
assert_eq!(
maker.perp_orders_mut_by_raw_index(0).order_market,
maker.perp_order_mut_by_raw_index(0).order_market,
market.perp_market_index
);
assert_eq!(
maker.perp_orders_mut_by_raw_index(1).order_market,
maker.perp_order_mut_by_raw_index(1).order_market,
FREE_ORDER_SLOT
);
assert_ne!(maker.perp_orders_mut_by_raw_index(0).order_id, 0);
assert_eq!(maker.perp_orders_mut_by_raw_index(0).client_order_id, 42);
assert_eq!(maker.perp_orders_mut_by_raw_index(0).order_side, Side::Bid);
assert_ne!(maker.perp_order_mut_by_raw_index(0).order_id, 0);
assert_eq!(maker.perp_order_mut_by_raw_index(0).client_order_id, 42);
assert_eq!(maker.perp_order_mut_by_raw_index(0).order_side, Side::Bid);
assert!(bookside_contains_key(
&book.bids,
maker.perp_orders_mut_by_raw_index(0).order_id
maker.perp_order_mut_by_raw_index(0).order_id
));
assert!(bookside_contains_price(&book.bids, price));
assert_eq!(
@ -279,7 +279,7 @@ mod tests {
// the remainder of the maker order is still on the book
// (the maker account is unchanged: it was not even passed in)
let order =
bookside_leaf_by_key(&book.bids, maker.perp_orders_by_raw_index(0).order_id).unwrap();
bookside_leaf_by_key(&book.bids, maker.perp_order_by_raw_index(0).order_id).unwrap();
assert_eq!(order.price(), price);
assert_eq!(order.quantity, bid_quantity - match_quantity);
@ -292,7 +292,7 @@ mod tests {
// the taker account is updated
assert_eq!(
taker.perp_orders_by_raw_index(0).order_market,
taker.perp_order_by_raw_index(0).order_market,
FREE_ORDER_SLOT
);
assert_eq!(taker.perp_position_by_raw_index(0).bids_base_lots, 0);
@ -334,7 +334,7 @@ mod tests {
.unwrap();
assert_eq!(market.open_interest, 2 * match_quantity);
assert_eq!(maker.perp_orders_by_raw_index(0).order_market, 0);
assert_eq!(maker.perp_order_by_raw_index(0).order_market, 0);
assert_eq!(
maker.perp_position_by_raw_index(0).bids_base_lots,
bid_quantity - match_quantity