From 1156947d51479bba963143bd260aafd4fd190d01 Mon Sep 17 00:00:00 2001 From: neverm1ndthat Date: Tue, 6 Oct 2026 15:53:41 +0800 Subject: [PATCH] fix(amm): normalize price scales before computing price impact Issue #1011 - computePriceImpact() compared spot and effective prices at different decimal scales. An integer spot price like 1 (scale=1) and a fractional effective price like 0.91 (scale=10^12) produced spotScaled=1 vs effectiveScaled=910000... but the subtraction treated them as same-scale values, so price impact always rounded to 0.00%. Fix: bring both values to their common scale via cross-multiplication before computing percentage impact. Existing 12 AMM tests continue to pass. --- src/ammCalculator.ts | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/src/ammCalculator.ts b/src/ammCalculator.ts index 4ae3d42..a91c9ec 100644 --- a/src/ammCalculator.ts +++ b/src/ammCalculator.ts @@ -435,16 +435,23 @@ function computePriceImpact(spotPrice: string, effectivePrice: string): string { const spot = parseDecimal(spotPrice); const effective = parseDecimal(effectivePrice); - + const spotScaled = spot.int * spot.scale + spot.frac; const effectiveScaled = effective.int * effective.scale + effective.frac; - if (spotScaled === 0n) return "0.00"; + // Issue #1011 — normalize both values to their common scale before + // comparing, so that an integer spot price ("1") and a fractional + // effective price ("0.91") are not compared at different scales. + const commonScale = spot.scale > effective.scale ? spot.scale : effective.scale; + const spotCommon = spotScaled * (commonScale / spot.scale); + const effectiveCommon = effectiveScaled * (commonScale / effective.scale); + + if (spotCommon === 0n) return "0.00"; // (spot - effective) / spot * 100 with 4 decimal places of precision const SCALE = 10000n; - const numerator = (spotScaled - effectiveScaled) * SCALE * 100n; - const denominator = spotScaled; + const numerator = (spotCommon - effectiveCommon) * SCALE * 100n; + const denominator = spotCommon; if (numerator <= 0n) return "0.00";