Files
precompile/dex/liquidity_amounts.go
zeekay 278cb100b0 refactor: clean precompile names — v4-aligned, no aliases
LP-9010  LXPool        v4 PoolManager (singleton pool state)
LP-9011  LXOracle      Price aggregation
LP-9012  LXRouter      v4 SwapRouter (external swap entry)
LP-9013  LXHooks       v4 hook registry
LP-9014  LXFlash       Flash accounting
LP-9020  LXBook        CLOB orderbook engine
LP-9030  LXVault       Custody + margin
LP-9040  LXFeed        Derived/computed pricing
LP-9050  LXLend        Lending pool
LP-9060  LXAutoRepay   Self-repaying loans
LP-9070  LXLiquidator  Liquidation engine
LP-9080  LXTransmuter  Debt → collateral conversion
LP-9090  LXFillAttest  Settlement attestation

Removed all backward-compat aliases. One name per address.
2026-03-02 16:54:55 +00:00

117 lines
3.8 KiB
Go

// Copyright (C) 2025, Lux Industries Inc. All rights reserved.
// See the file LICENSE for licensing terms.
package dex
import (
"math/big"
)
// LiquidityAmounts implements Uniswap V4's LiquidityAmounts.sol helper library.
// These are view functions used to compute optimal liquidity from desired token amounts,
// and to compute token amounts from a given liquidity position.
// GetLiquidityForAmount0 computes the liquidity amount that corresponds to
// a given amount of token0 and price range [sqrtRatioAX96, sqrtRatioBX96].
//
// liquidity = amount0 * sqrtRatioA * sqrtRatioB / (sqrtRatioB - sqrtRatioA)
func GetLiquidityForAmount0(sqrtRatioAX96, sqrtRatioBX96, amount0 *big.Int) *big.Int {
a, b := sqrtRatioAX96, sqrtRatioBX96
if a.Cmp(b) > 0 {
a, b = b, a
}
intermediate := MulDiv(a, b, Q96)
diff := new(big.Int).Sub(b, a)
if diff.Sign() <= 0 {
return big.NewInt(0)
}
return MulDiv(amount0, intermediate, diff)
}
// GetLiquidityForAmount1 computes the liquidity amount that corresponds to
// a given amount of token1 and price range [sqrtRatioAX96, sqrtRatioBX96].
//
// liquidity = amount1 * Q96 / (sqrtRatioB - sqrtRatioA)
func GetLiquidityForAmount1(sqrtRatioAX96, sqrtRatioBX96, amount1 *big.Int) *big.Int {
a, b := sqrtRatioAX96, sqrtRatioBX96
if a.Cmp(b) > 0 {
a, b = b, a
}
diff := new(big.Int).Sub(b, a)
if diff.Sign() <= 0 {
return big.NewInt(0)
}
return MulDiv(amount1, Q96, diff)
}
// GetLiquidityForAmounts computes the maximum liquidity that can be minted
// from the given token amounts at the current price, within the given price range.
//
// If current price is below the range, all liquidity comes from token0.
// If current price is above the range, all liquidity comes from token1.
// If current price is within the range, use the minimum of both.
func GetLiquidityForAmounts(
sqrtRatioX96, sqrtRatioAX96, sqrtRatioBX96, amount0, amount1 *big.Int,
) *big.Int {
a, b := sqrtRatioAX96, sqrtRatioBX96
if a.Cmp(b) > 0 {
a, b = b, a
}
if sqrtRatioX96.Cmp(a) <= 0 {
// Current price below range: only token0 needed
return GetLiquidityForAmount0(a, b, amount0)
}
if sqrtRatioX96.Cmp(b) >= 0 {
// Current price above range: only token1 needed
return GetLiquidityForAmount1(a, b, amount1)
}
// Current price within range: use min of both
liq0 := GetLiquidityForAmount0(sqrtRatioX96, b, amount0)
liq1 := GetLiquidityForAmount1(a, sqrtRatioX96, amount1)
if liq0.Cmp(liq1) < 0 {
return liq0
}
return liq1
}
// GetAmount0ForLiquidity computes the amount of token0 for a given liquidity
// and price range. Does not round up (used for view functions).
func GetAmount0ForLiquidity(sqrtRatioAX96, sqrtRatioBX96, liquidity *big.Int) *big.Int {
return GetAmount0Delta(sqrtRatioAX96, sqrtRatioBX96, liquidity, false)
}
// GetAmount1ForLiquidity computes the amount of token1 for a given liquidity
// and price range. Does not round up (used for view functions).
func GetAmount1ForLiquidity(sqrtRatioAX96, sqrtRatioBX96, liquidity *big.Int) *big.Int {
return GetAmount1Delta(sqrtRatioAX96, sqrtRatioBX96, liquidity, false)
}
// GetAmountsForLiquidity computes both token amounts for a given liquidity
// position at the current price.
func GetAmountsForLiquidity(
sqrtRatioX96, sqrtRatioAX96, sqrtRatioBX96, liquidity *big.Int,
) (amount0, amount1 *big.Int) {
a, b := sqrtRatioAX96, sqrtRatioBX96
if a.Cmp(b) > 0 {
a, b = b, a
}
if sqrtRatioX96.Cmp(a) <= 0 {
// Below range: only token0
amount0 = GetAmount0ForLiquidity(a, b, liquidity)
amount1 = big.NewInt(0)
} else if sqrtRatioX96.Cmp(b) >= 0 {
// Above range: only token1
amount0 = big.NewInt(0)
amount1 = GetAmount1ForLiquidity(a, b, liquidity)
} else {
// Within range: both tokens
amount0 = GetAmount0ForLiquidity(sqrtRatioX96, b, liquidity)
amount1 = GetAmount1ForLiquidity(a, sqrtRatioX96, liquidity)
}
return
}