From 29f4af2208310925e20797b7a92e4e2cc27fb488 Mon Sep 17 00:00:00 2001 From: Chris Heaney Date: Tue, 19 Aug 2025 10:49:40 -0400 Subject: [PATCH] program: min/max last fill price with inital amm price --- programs/drift/src/controller/orders.rs | 18 +++++++++++------ programs/drift/src/math/fulfillment.rs | 26 +++++++++++++------------ 2 files changed, 26 insertions(+), 18 deletions(-) diff --git a/programs/drift/src/controller/orders.rs b/programs/drift/src/controller/orders.rs index 84c2010c66..d1dfa38a26 100644 --- a/programs/drift/src/controller/orders.rs +++ b/programs/drift/src/controller/orders.rs @@ -1296,7 +1296,7 @@ pub fn fill_perp_order( AMMAvailability::Unavailable }; - let (base_asset_amount, quote_asset_amount) = fulfill_perp_order( + let (base_asset_amount, quote_asset_amount, initial_amm_price) = fulfill_perp_order( user, order_index, &user_key, @@ -1339,7 +1339,13 @@ pub fn fill_perp_order( None, )?; - perp_market.last_fill_price = fill_price; + if initial_amm_price != 0 { + if order_direction == PositionDirection::Long { + perp_market.last_fill_price = initial_amm_price.min(fill_price); + } else { + perp_market.last_fill_price = initial_amm_price.max(fill_price); + } + } } let base_asset_amount_after = user.perp_positions[position_index].base_asset_amount; @@ -1754,7 +1760,7 @@ fn fulfill_perp_order( amm_availability: AMMAvailability, fill_mode: FillMode, oracle_stale_for_margin: bool, -) -> DriftResult<(u64, u64)> { +) -> DriftResult<(u64, u64, u64)> { let market_index = user.orders[user_order_index].market_index; let user_order_position_decreasing = @@ -1771,7 +1777,7 @@ fn fulfill_perp_order( let perp_market_oi_before = perp_market.get_open_interest(); drop(perp_market); - let fulfillment_methods = { + let (fulfillment_methods, initial_amm_price) = { let market = perp_market_map.get_ref(&market_index)?; let oracle_price = oracle_map.get_price_data(&market.oracle_id())?.price; @@ -1790,7 +1796,7 @@ fn fulfill_perp_order( }; if fulfillment_methods.is_empty() { - return Ok((0, 0)); + return Ok((0, 0, initial_amm_price)); } let mut base_asset_amount = 0_u64; @@ -2055,7 +2061,7 @@ fn fulfill_perp_order( )?; } - Ok((base_asset_amount, quote_asset_amount)) + Ok((base_asset_amount, quote_asset_amount, initial_amm_price)) } #[allow(clippy::type_complexity)] diff --git a/programs/drift/src/math/fulfillment.rs b/programs/drift/src/math/fulfillment.rs index c4892bedf8..fc16d3f680 100644 --- a/programs/drift/src/math/fulfillment.rs +++ b/programs/drift/src/math/fulfillment.rs @@ -24,7 +24,7 @@ pub fn determine_perp_fulfillment_methods( slot: u64, min_auction_duration: u8, fill_mode: FillMode, -) -> DriftResult> { +) -> DriftResult<(Vec, u64)> { if order.post_only { return determine_perp_fulfillment_methods_for_maker( order, @@ -52,11 +52,13 @@ pub fn determine_perp_fulfillment_methods( let maker_direction = order.direction.opposite(); - let mut amm_price = match maker_direction { + let initial_amm_price = match maker_direction { PositionDirection::Long => amm.bid_price(amm_reserve_price)?, PositionDirection::Short => amm.ask_price(amm_reserve_price)?, }; + let mut amm_price = initial_amm_price; + for (maker_key, maker_order_index, maker_price) in maker_orders_info.iter() { let taker_crosses_maker = match limit_price { Some(taker_price) => do_orders_cross(maker_direction, *maker_price, taker_price), @@ -101,7 +103,7 @@ pub fn determine_perp_fulfillment_methods( } } - Ok(fulfillment_methods) + Ok((fulfillment_methods, initial_amm_price)) } fn determine_perp_fulfillment_methods_for_maker( @@ -114,9 +116,14 @@ fn determine_perp_fulfillment_methods_for_maker( slot: u64, min_auction_duration: u8, fill_mode: FillMode, -) -> DriftResult> { +) -> DriftResult<(Vec, u64)> { let maker_direction = order.direction; + let amm_price = match maker_direction { + PositionDirection::Long => amm.ask_price(amm_reserve_price)?, + PositionDirection::Short => amm.bid_price(amm_reserve_price)?, + }; + let can_fill_with_amm = can_fill_with_amm( amm_availability, valid_oracle_price, @@ -127,22 +134,17 @@ fn determine_perp_fulfillment_methods_for_maker( )?; if !can_fill_with_amm { - return Ok(vec![]); + return Ok((vec![], amm_price)); } - let amm_price = match maker_direction { - PositionDirection::Long => amm.ask_price(amm_reserve_price)?, - PositionDirection::Short => amm.bid_price(amm_reserve_price)?, - }; - let maker_price = limit_price.safe_unwrap()?; let amm_crosses_maker = do_orders_cross(maker_direction, maker_price, amm_price); if amm_crosses_maker { - Ok(vec![PerpFulfillmentMethod::AMM(None)]) + Ok((vec![PerpFulfillmentMethod::AMM(None)], amm_price)) } else { - Ok(vec![]) + Ok((vec![], amm_price)) } }