PathrockNetwork Gno Explorer
HomeBlocksTransactionsTokensRealmsPackagesValidatorsAnalytics

PathrockNetwork Gno Explorer — an independent explorer for Gno.land Mainnet (gnoland-1), operated by PathrockNetwork. Not an official Gno.land service.

gnowebarchive RPC

gno.land/p/gnoswap/gnsmath/v1

Package
Open in gnoweb ↗

Overview

Kind
Pure package
Name
v1
Namespace
gnoswap / gnsmath
Files
11 (README)(gnomod.toml)
Exported functions
n/a — not supported for pure packages by the node (vm/qfuncs)
Module
gno.land/p/gnoswap/gnsmath/v1
gno
0.9

Files (11)

  • README.mdmarkdown
  • gnomod.tomltoml
  • bit_math.gnogno
  • consts.gnogno
  • doc.gnogno
  • errors.gnogno
  • liquidity_math.gnogno
  • safe_math.gnogno
  • sqrt_price_math.gnogno
  • swap_math.gnogno
  • tick_math.gnogno
  • swap_math.gnogno
    1package gnsmath23import (4	i256 "gno.land/p/gnoswap/int256/v1"5	u256 "gno.land/p/gnoswap/uint256/v1"6)78

    Functions

    not supported for pure packages by the node (vm/qfuncs)

    Signatures reconstructed verbatim from vm/qfuncs — interface params keep their inline definitions.

    // denominator represents 100% in the fee calculation basis (1,000,000 = 100%).
    9// Fee calculations use this to convert feePips to actual percentages.
    10// For example, feePips=3000 means 3000/1000000 = 0.3% fee.
    11const denominator = uint64(1_000_000)
    12
    13// SwapMathComputeSwapStep computes one swap step within a single tick range.
    14// It determines the next square-root price, input amount, output amount, and fee,
    15// using exact-input or exact-output semantics from amountRemaining.
    16//
    17// Parameters:
    18// - sqrtRatioCurrentX96: Current pool square-root price in Q96 fixed-point format.
    19// - sqrtRatioTargetX96: Tick-boundary square-root price that this step may reach.
    20// - liquidity: Non-negative liquidity active between the current and target prices.
    21// - amountRemaining: Signed amount remaining; non-negative selects exact input, negative selects exact output.
    22// - feePips: Fee rate in millionths of the input amount (3,000 represents 0.3%).
    23//
    24// Returns:
    25// - sqrtRatioNextX96: Square-root price after applying this step, within the valid pool price bounds.
    26// - amountIn: Amount of the input token consumed by this step, excluding the fee.
    27// - amountOut: Amount of the output token produced by this step.
    28// - feeAmount: Input-token fee charged for this step.
    29//
    30// Panics if an input pointer is nil, feePips is at least 1,000,000, arithmetic
    31// overflows, or the resulting square-root price is outside the valid bounds.
    32func SwapMathComputeSwapStep(
    33 sqrtRatioCurrentX96 *u256.Uint,
    34 sqrtRatioTargetX96 *u256.Uint,
    35 liquidity *u256.Uint,
    36 amountRemaining *i256.Int,
    37 feePips uint64,
    38) (*u256.Uint, *u256.Uint, *u256.Uint, *u256.Uint) {
    39 if sqrtRatioCurrentX96 == nil || sqrtRatioTargetX96 == nil ||
    40 liquidity == nil || amountRemaining == nil {
    41 panic("SwapMathComputeSwapStep: input parameters cannot be nil")
    42 }
    43
    44 // This function is publicly accessible and can be called by external users or contracts.
    45 // While the pool realm only uses predefined fee values (100, 500, 3000, 10000) which are safely within range,
    46 // external callers could potentially pass any feePips value. The fee calculation involves dividing by
    47 // (1000000 - feePips), so feePips must be strictly less than 1000000 to avoid division by zero.
    48 // This follows Uniswap V3's factory-level validation: require(fee < 1000000).
    49 if feePips >= denominator {
    50 panic("SwapMathComputeSwapStep: feePips must be less than 1000000")
    51 }
    52
    53 // zeroForOne determines swap direction based on the relationship of current vs. target
    54 zeroForOne := sqrtRatioCurrentX96.Gte(sqrtRatioTargetX96)
    55
    56 // POSITIVE == EXACT_IN => Estimated AmountOut
    57 // NEGATIVE == EXACT_OUT => Estimated AmountIn
    58 exactIn := !amountRemaining.IsNeg()
    59
    60 amountRemainingAbs := amountRemaining.Abs()
    61 feeRateInPips := u256.NewUint(feePips)
    62 withoutFeeRateInPips := u256.NewUint(denominator - feePips)
    63
    64 sqrtRatioNextX96 := u256.Zero()
    65 amountIn := u256.Zero()
    66 amountOut := u256.Zero()
    67 feeAmount := u256.Zero()
    68
    69 if exactIn {
    70 // Handle EXACT_IN scenario as a separate function
    71 sqrtRatioNextX96, amountIn = handleExactIn(
    72 zeroForOne,
    73 sqrtRatioCurrentX96,
    74 sqrtRatioTargetX96,
    75 liquidity,
    76 amountRemainingAbs, // use absolute value here
    77 withoutFeeRateInPips,
    78 )
    79 } else {
    80 // Handle EXACT_OUT scenario as a separate function
    81 sqrtRatioNextX96, amountOut = handleExactOut(
    82 zeroForOne,
    83 sqrtRatioCurrentX96,
    84 sqrtRatioTargetX96,
    85 liquidity,
    86 amountRemainingAbs,
    87 )
    88 }
    89
    90 // isMax checks if we've hit the boundary price (target)
    91 isMax := sqrtRatioTargetX96.Eq(sqrtRatioNextX96)
    92
    93 // Calculate final amountIn, amountOut if needed
    94 if zeroForOne {
    95 // If isMax && exactIn, we already have the correct amountIn
    96 if !(isMax && exactIn) {
    97 amountIn = getAmount0DeltaHelper(
    98 sqrtRatioNextX96,
    99 sqrtRatioCurrentX96,
    100 liquidity,
    101 true,
    102 )
    103 }
    104 // If isMax && !exactIn, we already have the correct amountOut
    105 if !(isMax && !exactIn) {
    106 amountOut = getAmount1DeltaHelper(
    107 sqrtRatioNextX96,
    108 sqrtRatioCurrentX96,
    109 liquidity,
    110 false,
    111 )
    112 }
    113 } else {
    114 if !(isMax && exactIn) {
    115 amountIn = getAmount1DeltaHelper(
    116 sqrtRatioCurrentX96,
    117 sqrtRatioNextX96,
    118 liquidity,
    119 true,
    120 )
    121 }
    122 if !(isMax && !exactIn) {
    123 amountOut = getAmount0DeltaHelper(
    124 sqrtRatioCurrentX96,
    125 sqrtRatioNextX96,
    126 liquidity,
    127 false,
    128 )
    129 }
    130 }
    131
    132 // If we're in EXACT_OUT mode but overcalculated 'amountOut'
    133 if !exactIn && amountOut.Gt(amountRemainingAbs) {
    134 amountOut = amountRemainingAbs
    135 }
    136
    137 // Fee logic
    138 // If exactIn and we haven't hit the target, the difference is the fee
    139 // Else, compute fee from feePips
    140 if exactIn && !sqrtRatioNextX96.Eq(sqrtRatioTargetX96) {
    141 feeAmount = u256.Zero().Sub(amountRemainingAbs, amountIn)
    142 } else {
    143 feeAmount = u256.MulDivRoundingUp(
    144 amountIn,
    145 feeRateInPips,
    146 withoutFeeRateInPips,
    147 )
    148 }
    149
    150 // Final sanity check for resulting price
    151 if sqrtRatioNextX96.Lt(MIN_SQRT_RATIO()) || sqrtRatioNextX96.Gt(MAX_SQRT_RATIO()) {
    152 panic(errInvalidPoolSqrtPrice)
    153 }
    154
    155 return sqrtRatioNextX96, amountIn, amountOut, feeAmount
    156}
    157
    158// handleExactIn handles the EXACT_IN scenario for swaps, returning the next sqrt price and
    159// a provisional amount. When the target price is reached, it returns the exact amount needed.
    160// When the target is not reached, it returns the amount needed to reach the target (which will
    161// be recalculated by the caller since we only moved partially).
    162// This internal function processes swaps where the input amount is specified exactly.
    163func handleExactIn(
    164 zeroForOne bool,
    165 sqrtRatioCurrentX96,
    166 sqrtRatioTargetX96,
    167 liquidity,
    168 amountRemainingAbs,
    169 withoutFeeRateInPips *u256.Uint,
    170) (*u256.Uint, *u256.Uint) {
    171 amountRemainingLessFee := u256.MulDiv(
    172 amountRemainingAbs,
    173 withoutFeeRateInPips,
    174 u256.NewUint(denominator),
    175 )
    176
    177 amountIn := u256.Zero()
    178
    179 if zeroForOne {
    180 amountIn = getAmount0DeltaHelper(
    181 sqrtRatioTargetX96,
    182 sqrtRatioCurrentX96,
    183 liquidity,
    184 true,
    185 )
    186 } else {
    187 amountIn = getAmount1DeltaHelper(
    188 sqrtRatioCurrentX96,
    189 sqrtRatioTargetX96,
    190 liquidity,
    191 true,
    192 )
    193 }
    194
    195 if amountRemainingLessFee.Gte(amountIn) {
    196 return sqrtRatioTargetX96, amountIn
    197 }
    198
    199 // We don't reach target price; use partial move
    200 nextSqrt := getNextSqrtPriceFromInput(
    201 sqrtRatioCurrentX96,
    202 liquidity,
    203 amountRemainingLessFee,
    204 zeroForOne,
    205 )
    206
    207 // Return the partially moved price and the amount to reach target (will be recalculated by caller)
    208 return nextSqrt, amountIn
    209}
    210
    211// handleExactOut handles the EXACT_OUT scenario for swaps, returning the next sqrt price and
    212// a provisional amount. When the target price is reached, it returns the exact amount produced.
    213// When the target is not reached due to insufficient liquidity, it returns the amount that would
    214// be produced if we reached the target (which will be recalculated by the caller).
    215// This internal function processes swaps where the output amount is specified exactly.
    216func handleExactOut(
    217 zeroForOne bool,
    218 sqrtRatioCurrentX96, sqrtRatioTargetX96, liquidity, amountRemainingAbs *u256.Uint,
    219) (*u256.Uint, *u256.Uint) {
    220 amountOut := u256.Zero()
    221
    222 if zeroForOne {
    223 amountOut = getAmount1DeltaHelper(sqrtRatioTargetX96, sqrtRatioCurrentX96, liquidity, false)
    224 } else {
    225 amountOut = getAmount0DeltaHelper(sqrtRatioCurrentX96, sqrtRatioTargetX96, liquidity, false)
    226 }
    227
    228 // Fast path: if sufficient liquidity, use target price
    229 if amountRemainingAbs.Gte(amountOut) {
    230 return sqrtRatioTargetX96, amountOut
    231 }
    232
    233 // Otherwise, partial move: compute next price from residual output amount
    234 // and return the amount to reach target (will be recalculated by caller)
    235 nextSqrt := getNextSqrtPriceFromOutput(
    236 sqrtRatioCurrentX96,
    237 liquidity,
    238 amountRemainingAbs,
    239 zeroForOne,
    240 )
    241
    242 return nextSqrt, amountOut
    243}
    244