From 04b6a37176f8be72c4cbe0f807994fffee303471 Mon Sep 17 00:00:00 2001 From: 0xbigz <83473873+0xbigz@users.noreply.github.com> Date: Wed, 11 Dec 2024 13:59:34 -0500 Subject: [PATCH] program: bound-quote-reserve-divisor --- programs/drift/src/math/amm_spread.rs | 11 ++++++-- programs/drift/src/math/amm_spread/tests.rs | 30 +++++++++++++++++++++ 2 files changed, 39 insertions(+), 2 deletions(-) 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%