From 631cd72f59a5cfa70abc08330f6688cf96fec1fb Mon Sep 17 00:00:00 2001 From: Danylo Kanievskyi Date: Wed, 30 Oct 2024 16:52:50 +0200 Subject: [PATCH] fix: perform more precise `sqrt` on bignumbers in `FluidDex` --- src/dex/fluid-dex/fluid-dex.ts | 17 +++++++---------- src/dex/fluid-dex/utils.ts | 15 +++++++++++++++ 2 files changed, 22 insertions(+), 10 deletions(-) create mode 100644 src/dex/fluid-dex/utils.ts diff --git a/src/dex/fluid-dex/fluid-dex.ts b/src/dex/fluid-dex/fluid-dex.ts index b0704e119..be13c52fa 100644 --- a/src/dex/fluid-dex/fluid-dex.ts +++ b/src/dex/fluid-dex/fluid-dex.ts @@ -32,6 +32,7 @@ import { extractReturnAmountPosition } from '../../executor/utils'; import { MultiResult } from '../../lib/multi-wrapper'; import { generalDecoder } from '../../lib/decoders'; import { BigNumber } from 'ethers'; +import { sqrt } from './utils'; export class FluidDex extends SimpleExchange implements IDex { eventPools: { [id: string]: FluidDexEventPool } = {}; @@ -610,18 +611,14 @@ export class FluidDex extends SimpleExchange implements IDex { ): bigint { // Adding 1e18 precision - const xyRoot = BigInt(Math.floor(Math.sqrt(Number(x * y * BigInt(1e18))))); - const x2y2Root = BigInt( - Math.floor(Math.sqrt(Number(x2 * y2 * BigInt(1e18)))), - ); + const xyRoot = sqrt(BigNumber.from(x).mul(y).mul(BigInt(1e18))).toBigInt(); + const x2y2Root = sqrt( + BigNumber.from(x2).mul(y2).mul(BigInt(1e18)), + ).toBigInt(); // Calculating 'a' using the given formula - const a = - (Number(y2) * Number(xyRoot) + - Number(t) * Number(xyRoot) - - Number(y) * Number(x2y2Root)) / - (Number(xyRoot) + Number(x2y2Root)); - return BigInt(Math.floor(a)); + const a = (y2 * xyRoot + t * xyRoot - y * x2y2Root) / (xyRoot + x2y2Root); + return a; } /** diff --git a/src/dex/fluid-dex/utils.ts b/src/dex/fluid-dex/utils.ts new file mode 100644 index 000000000..ff9dd3620 --- /dev/null +++ b/src/dex/fluid-dex/utils.ts @@ -0,0 +1,15 @@ +import { BigNumber } from 'ethers'; + +const ONE = BigNumber.from(1); +const TWO = BigNumber.from(2); + +export function sqrt(value: BigNumber) { + let x = value; + let z = x.add(ONE).div(TWO); + let y = x; + while (z.sub(y).isNegative()) { + y = z; + z = x.div(z).add(z).div(TWO); + } + return y; +}