Skip to content

Commit

Permalink
Update post only wrapper protection to skip expired orders (#274)
Browse files Browse the repository at this point in the history
* Update post only wrapper protection to skip expired orders

* NIL check
  • Loading branch information
brittcyr authored Nov 11, 2024
1 parent 293ab6c commit 7e14e67
Show file tree
Hide file tree
Showing 2 changed files with 29 additions and 4 deletions.
2 changes: 1 addition & 1 deletion programs/manifest/src/state/utils.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ use super::{
NO_EXPIRATION_LAST_VALID_SLOT,
};

pub(crate) fn get_now_slot() -> u32 {
pub fn get_now_slot() -> u32 {
// If we cannot get the clock (happens in tests, then only match with
// orders without expiration). We assume that the clock cannot be
// maliciously manipulated to clear all orders with expirations on the
Expand Down
31 changes: 28 additions & 3 deletions programs/wrapper/src/processors/batch_upate.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ use manifest::{
get_dynamic_account, get_mut_dynamic_account, invoke, ManifestInstruction,
},
quantities::{BaseAtoms, QuoteAtoms, QuoteAtomsPerBaseAtom, WrapperU64},
state::{DynamicAccount, MarketFixed, OrderType, RestingOrder},
state::{utils::get_now_slot, DynamicAccount, MarketFixed, OrderType, RestingOrder},
validation::{ManifestAccountInfo, Program, Signer},
};
use solana_program::{
Expand Down Expand Up @@ -160,8 +160,33 @@ fn prepare_orders(
let market_data: Ref<'_, &mut [u8]> = market.try_borrow_data().unwrap();
let market_ref: DynamicAccount<&MarketFixed, &[u8]> =
get_dynamic_account::<MarketFixed>(&market_data);
let best_ask_index: DataIndex = market_ref.get_asks().get_max_index();
let best_bid_index: DataIndex = market_ref.get_bids().get_max_index();
let mut best_ask_index: DataIndex = market_ref.get_asks().get_max_index();
let mut best_bid_index: DataIndex = market_ref.get_bids().get_max_index();

// Walk the tree until you find a non-expired order since those can be
// trivially ignored. Does not prevent unbacked global orders, but that
// would require global accounts and be too complicated to do here because
// this is only best-effort.
let now_slot: u32 = get_now_slot();

while best_ask_index != NIL
&& get_helper::<RBNode<RestingOrder>>(&market_data, best_ask_index)
.get_value()
.is_expired(now_slot)
{
best_ask_index = market_ref
.get_asks()
.get_next_lower_index::<RBNode<RestingOrder>>(best_ask_index);
}
while best_bid_index != NIL
&& get_helper::<RBNode<RestingOrder>>(&market_data, best_bid_index)
.get_value()
.is_expired(now_slot)
{
best_bid_index = market_ref
.get_bids()
.get_next_lower_index::<RBNode<RestingOrder>>(best_bid_index);
}

let best_ask_price: QuoteAtomsPerBaseAtom = if best_ask_index != NIL {
get_helper::<RBNode<RestingOrder>>(&market_data, best_ask_index)
Expand Down

0 comments on commit 7e14e67

Please sign in to comment.