Skip to content

Commit

Permalink
Programs: fix for audit v0.25.0 (#970)
Browse files Browse the repository at this point in the history
* Programs: remove anchor close has it is done manually anyway

* Programs: fix a bug where a pegged order might be skipped even if it was valid

(cherry picked from commit 905cc01)
(cherry picked from commit 47c2707)
  • Loading branch information
farnyser committed Aug 9, 2024
1 parent 98ed7ef commit 69d8660
Show file tree
Hide file tree
Showing 3 changed files with 63 additions and 15 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,7 @@ pub struct GroupChangeInsuranceFund<'info> {
pub group: AccountLoader<'info, Group>,
pub admin: Signer<'info>,

#[account(
mut,
close = payer,
)]
#[account(mut)]
pub insurance_vault: Account<'info, TokenAccount>,

#[account(mut)]
Expand Down
70 changes: 60 additions & 10 deletions programs/mango-v4/src/state/orderbook/bookside.rs
Original file line number Diff line number Diff line change
Expand Up @@ -238,6 +238,7 @@ impl BookSide {
mod tests {
use super::*;
use bytemuck::Zeroable;
use std::collections::HashSet;

fn new_order_tree(order_tree_type: OrderTreeType) -> OrderTreeNodes {
let mut ot = OrderTreeNodes::zeroed();
Expand Down Expand Up @@ -281,8 +282,11 @@ mod tests {
.insert_leaf(&mut root_pegged, &new_leaf(key))
.unwrap();

let mut pegged_prices = vec![];

while root_pegged.leaf_count < 100 {
let price_data: u64 = oracle_pegged_price_data(rng.gen_range(-20..20));
let price = rng.gen_range(-20..20);
let price_data: u64 = oracle_pegged_price_data(price);
let seq_num: u64 = rng.gen_range(0..1000);
let key = new_node_key(side, price_data, seq_num);
if keys.contains(&key) {
Expand All @@ -292,6 +296,7 @@ mod tests {
order_tree
.insert_leaf(&mut root_pegged, &new_leaf(key))
.unwrap();
pegged_prices.push(price);
}

while root_fixed.leaf_count < 100 {
Expand Down Expand Up @@ -332,6 +337,12 @@ mod tests {
total += 1;
}
assert!(total >= 101); // some oracle peg orders could be skipped

let skipped_pegged_orders = pegged_prices
.iter()
.filter(|x| oracle_price_lots + **x <= 0)
.count();
assert_eq!(total, 200 - skipped_pegged_orders);
if oracle_price_lots > 20 {
assert_eq!(total, 200);
}
Expand All @@ -340,15 +351,31 @@ mod tests {

#[test]
fn bookside_iteration_random() {
bookside_iteration_random_helper(Side::Bid);
bookside_iteration_random_helper(Side::Ask);
for i in 0..10 {
bookside_iteration_random_helper(Side::Bid);
bookside_iteration_random_helper(Side::Ask);
}
}

fn bookside_setup() -> BookSide {
bookside_setup_advanced(
&[(100, 0), (120, 5)],
&[(-10, 0, 100), (-15, 0, -1), (-20, 7, 95)],
Side::Bid,
)
}

fn bookside_setup_advanced(
fixed: &[(i64, u16)],
pegged: &[(i64, u16, i64)],
side: Side,
) -> BookSide {
use std::cell::RefCell;

let side = Side::Bid;
let order_tree_type = OrderTreeType::Bids;
let order_tree_type = match side {
Side::Bid => OrderTreeType::Bids,
Side::Ask => OrderTreeType::Asks,
};

let order_tree = RefCell::new(new_order_tree(order_tree_type));
let mut root_fixed = OrderTreeRoot::zeroed();
Expand Down Expand Up @@ -381,11 +408,12 @@ mod tests {
.unwrap();
};

add_fixed(100, 0);
add_fixed(120, 5);
add_pegged(-10, 0, 100);
add_pegged(-15, 0, -1);
add_pegged(-20, 7, 95);
for (price, tif) in fixed {
add_fixed(*price, *tif);
}
for (price_offset, tif, limit) in pegged {
add_pegged(*price_offset, *tif, *limit);
}

BookSide {
roots: [root_fixed, root_pegged],
Expand Down Expand Up @@ -458,4 +486,26 @@ mod tests {
assert_eq!(p, 120);
assert_eq!(order_prices(0, 100), Vec::<i64>::new());
}

#[test]
fn bookside_iterate_when_first_peg_is_skipped() {
use std::cell::RefCell;

let bookside = RefCell::new(bookside_setup_advanced(
&[],
&[(-100, 0, 50), (-20, 0, 50), (-30, 0, 50)],
Side::Ask,
));

let order_prices = |now_ts: u64, oracle: i64| -> Vec<i64> {
bookside
.borrow()
.iter_valid(now_ts, oracle)
.map(|it| it.price_lots)
.collect()
};

assert_eq!(order_prices(0, 200), vec![100, 170, 180]);
assert_eq!(order_prices(0, 100), vec![70, 80]);
}
}
3 changes: 2 additions & 1 deletion programs/mango-v4/src/state/orderbook/bookside_iterator.rs
Original file line number Diff line number Diff line change
Expand Up @@ -170,7 +170,8 @@ impl<'a> Iterator for BookSideIter<'a> {
if oracle_pegged_price(self.oracle_price_lots, o_node, side).0 != OrderState::Skipped {
break;
}
o_peek = self.oracle_pegged_iter.next()
self.oracle_pegged_iter.next();
o_peek = self.oracle_pegged_iter.peek();
}

let f_peek = self.fixed_iter.peek();
Expand Down

0 comments on commit 69d8660

Please sign in to comment.