From 42eb38deb07140384045e98d11edda716b273987 Mon Sep 17 00:00:00 2001 From: lil perp Date: Mon, 23 Dec 2024 14:26:50 -0500 Subject: [PATCH] program: fix small precision issues (#1399) * program: fix small precision issues * sdk: add numeratorScale/denominatorScale for getWithdrawalLimit * update CHANGELOG.md --------- Co-authored-by: 0xbigz <83473873+0xbigz@users.noreply.github.com> --- CHANGELOG.md | 1 + programs/drift/src/math/margin.rs | 9 +++++++-- programs/drift/src/math/orders.rs | 9 +++++++-- sdk/src/user.ts | 19 +++++++++++++++---- 4 files changed, 30 insertions(+), 8 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 232ef2f92..5f9069dbc 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -16,6 +16,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - program: fix force delete user for token 2022 ([#1358](https://github.com/drift-labs/protocol-v2/pull/1358)) - program: fix liquidating dust prediction mkt position ([#1397](https://github.com/drift-labs/protocol-v2/pull/1397)) +- program: spot market decimals under 6 precision fixes ([#1399](https://github.com/drift-labs/protocol-v2/pull/1399)) ### Breaking diff --git a/programs/drift/src/math/margin.rs b/programs/drift/src/math/margin.rs index b04f22e56..be883b6ed 100644 --- a/programs/drift/src/math/margin.rs +++ b/programs/drift/src/math/margin.rs @@ -801,14 +801,19 @@ pub fn calculate_max_withdrawable_amount( let free_collateral = calculation.get_free_collateral()?; - let precision_increase = 10u128.pow(spot_market.decimals - 6); + let (numerator_scale, denominator_scale) = if spot_market.decimals > 6 { + (10_u128.pow(spot_market.decimals - 6), 1) + } else { + (1, 10_u128.pow(6 - spot_market.decimals)) + }; free_collateral .safe_mul(MARGIN_PRECISION_U128)? .safe_div(asset_weight.cast()?)? .safe_mul(PRICE_PRECISION)? .safe_div(oracle_price.cast()?)? - .safe_mul(precision_increase)? + .safe_mul(numerator_scale)? + .safe_div(denominator_scale)? .cast() } diff --git a/programs/drift/src/math/orders.rs b/programs/drift/src/math/orders.rs index 45553ab34..7d55d761d 100644 --- a/programs/drift/src/math/orders.rs +++ b/programs/drift/src/math/orders.rs @@ -1130,12 +1130,17 @@ pub fn calculate_max_spot_order_size( user_custom_asset_weight, )?; - let precision_increase = 10i128.pow(spot_market.decimals - 6); + let (numerator_scale, denominator_scale) = if spot_market.decimals > 6 { + (10_i128.pow(spot_market.decimals - 6), 1) + } else { + (1, 10_i128.pow(6 - spot_market.decimals)) + }; let calculate_order_size_and_free_collateral_delta = |free_collateral_delta: u32| { let new_order_size = free_collateral .safe_sub(OPEN_ORDER_MARGIN_REQUIREMENT.cast()?)? - .safe_mul(precision_increase)? + .safe_mul(numerator_scale)? + .safe_div(denominator_scale)? .safe_mul(SPOT_WEIGHT_PRECISION.cast()?)? .safe_div(free_collateral_delta.cast()?)? .safe_mul(PRICE_PRECISION_I128)? diff --git a/sdk/src/user.ts b/sdk/src/user.ts index 2ecae8b8d..16e9c82c8 100644 --- a/sdk/src/user.ts +++ b/sdk/src/user.ts @@ -36,7 +36,6 @@ import { QUOTE_PRECISION_EXP, QUOTE_SPOT_MARKET_INDEX, SPOT_MARKET_WEIGHT_PRECISION, - TEN, TEN_THOUSAND, TWO, ZERO, @@ -3540,7 +3539,16 @@ export class User { const freeCollateral = this.getFreeCollateral(); const initialMarginRequirement = this.getInitialMarginRequirement(); const oracleData = this.getOracleDataForSpotMarket(marketIndex); - const precisionIncrease = TEN.pow(new BN(spotMarket.decimals - 6)); + const { numeratorScale, denominatorScale } = + spotMarket.decimals > 6 + ? { + numeratorScale: new BN(10).pow(new BN(spotMarket.decimals - 6)), + denominatorScale: new BN(1), + } + : { + numeratorScale: new BN(1), + denominatorScale: new BN(10).pow(new BN(6 - spotMarket.decimals)), + }; const { canBypass, depositAmount: userDepositAmount } = this.canBypassWithdrawLimits(marketIndex); @@ -3566,7 +3574,9 @@ export class User { PRICE_PRECISION ), oracleData.price - ).mul(precisionIncrease); + ) + .mul(numeratorScale) + .div(denominatorScale); } const maxWithdrawValue = BN.min( @@ -3592,7 +3602,8 @@ export class User { .div(new BN(spotMarket.initialLiabilityWeight)) .mul(PRICE_PRECISION) .div(oracleData.price) - .mul(precisionIncrease); + .mul(numeratorScale) + .div(denominatorScale); const maxBorrowValue = BN.min( maxWithdrawValue.add(maxLiabilityAllowed),