diff --git a/position/_GET_position.gno b/position/_GET_position.gno index f3f95de9..e1fead4f 100644 --- a/position/_GET_position.gno +++ b/position/_GET_position.gno @@ -37,5 +37,5 @@ func PositionGetPositionTokensOwed1(tokenId uint64) bigint { } func PositionGetAmountsForLiquidity(sqrtRatioX96, sqrtRatioAX96, sqrtRatioBX96, liquidity bigint) (bigint, bigint) { - return liquidityAmountsGetAmountsForLiquidity(sqrtRatioX96, sqrtRatioAX96, sqrtRatioBX96, liquidity) + return GetAmountsForLiquidity(sqrtRatioX96, sqrtRatioAX96, sqrtRatioBX96, liquidity) } diff --git a/position/_RPC_api.gno b/position/_RPC_api.gno index 018cf858..d2303550 100644 --- a/position/_RPC_api.gno +++ b/position/_RPC_api.gno @@ -70,7 +70,7 @@ func rpcMakePosition(lpTokenId uint64) RpcPosition { lowerX96 := p.TickMathGetSqrtRatioAtTick(position.tickLower) upperX96 := p.TickMathGetSqrtRatioAtTick(position.tickUpper) - token0Balance, token1Balance := liquidityAmountsGetAmountsForLiquidity( + token0Balance, token1Balance := GetAmountsForLiquidity( currentX96, lowerX96, upperX96, diff --git a/position/_RPC_dry.gno b/position/_RPC_dry.gno index a52e1e84..df81bfc8 100644 --- a/position/_RPC_dry.gno +++ b/position/_RPC_dry.gno @@ -15,7 +15,7 @@ func DryMint( sqrtLowerX96 := p.TickMathGetSqrtRatioAtTick(tickLower) sqrtUpperX96 := p.TickMathGetSqrtRatioAtTick(tickUpper) - liquidity := liquidityAmountsGetLiquidityForAmounts( + liquidity := GetLiquidityForAmounts( sqrtRatioX96, sqrtLowerX96, sqrtUpperX96, diff --git a/position/liquidity_amounts.gno b/position/liquidity_amounts.gno index a7bba3ff..71d797f1 100644 --- a/position/liquidity_amounts.gno +++ b/position/liquidity_amounts.gno @@ -1,49 +1,53 @@ package position -func liquidityAmountsGetLiquidityForAmount0( - sqrtRatioAX96 bigint, - sqrtRatioBX96 bigint, - amount0 bigint, -) bigint { - if sqrtRatioAX96 > sqrtRatioBX96 { - sqrtRatioAX96, sqrtRatioBX96 = sqrtRatioBX96, sqrtRatioAX96 +import ( + "gno.land/r/demo/consts" +) + +// swapIfGreater checkes if the first value is greater than +// the second then swaps two values. +func swapIfGreater(a, b bigint) (bigint, bigint) { + if a > b { + return b, a } - intermediate := (sqrtRatioAX96 * sqrtRatioBX96) / Q96 + return a, b +} - return amount0 * intermediate / (sqrtRatioBX96 - sqrtRatioAX96) +// calcIntermediateValue computes the intermediate value +// used in liquidity calculations. +func calcIntermediateValue(sqrtRatioA, sqrtRatioB bigint) bigint { + return (sqrtRatioA * sqrtRatioB) / consts.Q96 } -func liquidityAmountsGetLiquidityForAmount1( - sqrtRatioAX96 bigint, - sqrtRatioBX96 bigint, - amount1 bigint, -) bigint { - if sqrtRatioAX96 > sqrtRatioBX96 { - sqrtRatioAX96, sqrtRatioBX96 = sqrtRatioBX96, sqrtRatioAX96 - } +// GetLiquidityForAmount0 calculates liquidity for a given amount of token 0. +func computeLiquidityForAmount0(sqrtRatioA, sqrtRatioB, amount0 bigint) bigint { + sqrtRatioA, sqrtRatioB = swapIfGreater(sqrtRatioA, sqrtRatioB) + intermediate := calcIntermediateValue(sqrtRatioA, sqrtRatioB) + diff := sqrtRatioB - sqrtRatioA - return amount1 * Q96 / (sqrtRatioBX96 - sqrtRatioAX96) + // we don't need to care about division by zero here. + return amount0 * intermediate / diff } -func liquidityAmountsGetLiquidityForAmounts( - sqrtRatioX96 bigint, - sqrtRatioAX96 bigint, - sqrtRatioBX96 bigint, - amount0 bigint, - amount1 bigint, -) bigint { - var liquidity bigint +// computeLiquidityForAmount1 calculates liquidity for a given amount of token 1. +func computeLiquidityForAmount1(sqrtRatioA, sqrtRatioB, amount1 bigint) bigint { + sqrtRatioA, sqrtRatioB = swapIfGreater(sqrtRatioA, sqrtRatioB) + diff := sqrtRatioB - sqrtRatioA - if sqrtRatioAX96 > sqrtRatioBX96 { - sqrtRatioAX96, sqrtRatioBX96 = sqrtRatioBX96, sqrtRatioAX96 - } + return (amount1 * consts.Q96) / diff +} - if sqrtRatioX96 <= sqrtRatioAX96 { - liquidity = liquidityAmountsGetLiquidityForAmount0(sqrtRatioAX96, sqrtRatioBX96, amount0) - } else if sqrtRatioX96 < sqrtRatioBX96 { - liquidity0 := liquidityAmountsGetLiquidityForAmount0(sqrtRatioX96, sqrtRatioBX96, amount0) - liquidity1 := liquidityAmountsGetLiquidityForAmount1(sqrtRatioAX96, sqrtRatioX96, amount1) +// GetLiquidityForAmounts calculates the liquidity for given amounts od token 0 and token 1. +func GetLiquidityForAmounts(sqrtRatioX, sqrtRatioA, sqrtRatioB, amount0, amount1 bigint) bigint { + sqrtRatioA, sqrtRatioB = swapIfGreater(sqrtRatioA, sqrtRatioB) + var liquidity bigint + + if sqrtRatioX <= sqrtRatioA { + liquidity = computeLiquidityForAmount0(sqrtRatioA, sqrtRatioB, amount0) + } else if sqrtRatioX < sqrtRatioB { + liquidity0 := computeLiquidityForAmount0(sqrtRatioX, sqrtRatioB, amount0) + liquidity1 := computeLiquidityForAmount1(sqrtRatioA, sqrtRatioX, amount1) if liquidity0 < liquidity1 { liquidity = liquidity0 @@ -52,42 +56,30 @@ func liquidityAmountsGetLiquidityForAmounts( } } else { - liquidity = liquidityAmountsGetLiquidityForAmount1(sqrtRatioAX96, sqrtRatioBX96, amount1) + liquidity = computeLiquidityForAmount1(sqrtRatioA, sqrtRatioB, amount1) } return liquidity } -func liquidityAmountsGetAmount0ForLiquidity( - sqrtRatioAX96 bigint, - sqrtRatioBX96 bigint, - liquidity bigint, -) bigint { - if sqrtRatioAX96 > sqrtRatioBX96 { - sqrtRatioAX96, sqrtRatioBX96 = sqrtRatioBX96, sqrtRatioAX96 - } +// computeAmount0ForLiquidity calculates the amount of token 0 for a given liquidity. +func computeAmount0ForLiquidity(sqrtRatioA, sqrtRatioB, liquidity bigint) bigint { + sqrtRatioA, sqrtRatioB = swapIfGreater(sqrtRatioA, sqrtRatioB) + diff := sqrtRatioB - sqrtRatioA - return ((liquidity << 96) * (sqrtRatioBX96 - sqrtRatioAX96) / sqrtRatioBX96) / sqrtRatioAX96 + return (liquidity << 96) * diff / (sqrtRatioB * sqrtRatioA) } -func liquidityAmountsGetAmount1ForLiquidity( - sqrtRatioAX96 bigint, - sqrtRatioBX96 bigint, - liquidity bigint, -) bigint { - if sqrtRatioAX96 > sqrtRatioBX96 { - sqrtRatioAX96, sqrtRatioBX96 = sqrtRatioBX96, sqrtRatioAX96 - } +// computeAmount1ForLiquidity calculates the amount of token 1 for a given liquidity. +func computeAmount1ForLiquidity(sqrtRatioA, sqrtRatioB, liquidity bigint) bigint { + sqrtRatioA, sqrtRatioB = swapIfGreater(sqrtRatioA, sqrtRatioB) + diff := sqrtRatioB - sqrtRatioA - return liquidity * (sqrtRatioBX96 - sqrtRatioAX96) / Q96 + return liquidity * diff / consts.Q96 } -func liquidityAmountsGetAmountsForLiquidity( - sqrtRatioX96 bigint, - sqrtRatioAX96 bigint, - sqrtRatioBX96 bigint, - liquidity bigint, -) (bigint, bigint) { +// GetAmountsForLiquidity calculates the amounts of token 0 and token 1 for a given liquidity. +func GetAmountsForLiquidity(sqrtRatioX96, sqrtRatioAX96, sqrtRatioBX96, liquidity bigint) (bigint, bigint) { var amount0, amount1 bigint if sqrtRatioAX96 > sqrtRatioBX96 { @@ -95,12 +87,12 @@ func liquidityAmountsGetAmountsForLiquidity( } if sqrtRatioX96 <= sqrtRatioAX96 { - amount0 = liquidityAmountsGetAmount0ForLiquidity(sqrtRatioAX96, sqrtRatioBX96, liquidity) + amount0 = computeAmount0ForLiquidity(sqrtRatioAX96, sqrtRatioBX96, liquidity) } else if sqrtRatioX96 < sqrtRatioBX96 { - amount0 = liquidityAmountsGetAmount0ForLiquidity(sqrtRatioX96, sqrtRatioBX96, liquidity) - amount1 = liquidityAmountsGetAmount1ForLiquidity(sqrtRatioAX96, sqrtRatioX96, liquidity) + amount0 = computeAmount0ForLiquidity(sqrtRatioX96, sqrtRatioBX96, liquidity) + amount1 = computeAmount1ForLiquidity(sqrtRatioAX96, sqrtRatioX96, liquidity) } else { - amount1 = liquidityAmountsGetAmount1ForLiquidity(sqrtRatioAX96, sqrtRatioBX96, liquidity) + amount1 = computeAmount1ForLiquidity(sqrtRatioAX96, sqrtRatioBX96, liquidity) } return amount0, amount1 diff --git a/position/liquidity_management.gno b/position/liquidity_management.gno index f689c6b3..b8631c05 100644 --- a/position/liquidity_management.gno +++ b/position/liquidity_management.gno @@ -11,7 +11,7 @@ func addLiquidity(params AddLiquidityParams) (bigint, bigint, bigint) { sqrtRatioAX96 := p.TickMathGetSqrtRatioAtTick(params.tickLower) sqrtRatioBX96 := p.TickMathGetSqrtRatioAtTick(params.tickUpper) - liquidity := liquidityAmountsGetLiquidityForAmounts( + liquidity := GetLiquidityForAmounts( sqrtPriceX96, sqrtRatioAX96, sqrtRatioBX96,