diff --git a/programs/drift/src/math/amm_spread.rs b/programs/drift/src/math/amm_spread.rs index af929f6a4f..2f4e1abf44 100644 --- a/programs/drift/src/math/amm_spread.rs +++ b/programs/drift/src/math/amm_spread.rs @@ -486,8 +486,14 @@ pub fn calculate_spread_reserves( }; let quote_asset_reserve_delta = if spread_with_offset.abs() > 1 { - let quote_reserve_divisor = - BID_ASK_SPREAD_PRECISION_I128 / (spread_with_offset / 2).cast::()?; + let mut quote_reserve_divisor = + (BID_ASK_SPREAD_PRECISION_I128 / (spread_with_offset / 2).cast::()?); + + // ensure the divisor is not zero + if quote_reserve_divisor == 0 { + quote_reserve_divisor = if spread_with_offset > 0 { 1 } else { -1 }; + } + market .amm .quote_asset_reserve @@ -507,6 +513,7 @@ pub fn calculate_spread_reserves( .amm .quote_asset_reserve .safe_sub(quote_asset_reserve_delta.unsigned_abs())? + .max(1) }; if market.contract_type == ContractType::Prediction { diff --git a/programs/drift/src/math/amm_spread/tests.rs b/programs/drift/src/math/amm_spread/tests.rs index 1d983ff1af..a88eedc8c0 100644 --- a/programs/drift/src/math/amm_spread/tests.rs +++ b/programs/drift/src/math/amm_spread/tests.rs @@ -189,6 +189,36 @@ mod test { assert_eq!(res, 0); } + + #[test] + fn calculate_extreme_spread_tests() { + let amm = AMM { + base_asset_reserve: 2 * AMM_RESERVE_PRECISION, + quote_asset_reserve: 2 * AMM_RESERVE_PRECISION, + sqrt_k: 2 * AMM_RESERVE_PRECISION, + peg_multiplier: PEG_PRECISION, + long_spread: (BID_ASK_SPREAD_PRECISION as u32) + 1000, + short_spread: (BID_ASK_SPREAD_PRECISION as u32) + 1000, + max_spread: (BID_ASK_SPREAD_PRECISION/2) as u32, + curve_update_intensity: 100, + ..AMM::default() + }; + + let mut market = PerpMarket { + amm, + ..PerpMarket::default() + }; + + let (bar_l, qar_l) = calculate_spread_reserves(&market, PositionDirection::Long).unwrap(); + let (bar_s, qar_s) = calculate_spread_reserves(&market, PositionDirection::Short).unwrap(); + + assert_eq!(bar_s, 4000000000000000000); + assert_eq!(qar_s, 1); + + assert_eq!(bar_l, 1000000000); + assert_eq!(qar_l, 4000000000); + } + #[test] fn calculate_spread_tests() { let base_spread = 1000; // .1%