PathrockNetwork Gno Explorer
HomeBlocksTransactionsRealmsPackagesValidatorsAnalytics

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/r/gnoswap/pool/v1

Realm
Open in gnoweb ↗

Overview

Kind
Realm (renderable)
Name
v1
Namespace
gnoswap / pool
Files
24 (README)(gnomod.toml)
Exported functions
3
Module
gno.land/r/gnoswap/pool/v1
gno
0.9

Files (24)

  • README.mdmarkdown
  • gnomod.tomltoml
  • assert.gnogno
  • doc.gnogno
  • errors.gnogno
  • event_info.gnogno
  • factory_param.gnogno
  • getter_utils.gnogno
  • getter.gnogno
  • init.gnogno
  • instance.gnogno
  • lock.gnogno
  • manager.gnogno
  • oracle.gnogno
  • pool.gnogno
  • position.gnogno
  • protocol_fee.gnogno
  • render.gnogno
  • swap.gnogno
  • tick_bitmap.gnogno
  • tick.gnogno
  • transfer.gnogno
  • type.gnogno
  • utils.gnogno
  • tick.gnogno
    1package pool23import (4	"gno.land/p/gnoswap/consts/v1"5	"gno.land/p/gnoswap/gnsmath/v1"6	ufmt "gno.land/p/nt/ufmt/v0"78

    Functions

    • GetPoolPath(token0Path string, token1Path string, fee uint32) string

    • NewPoolV1(store interface {GetFeeAmountTickSpacing func() map[uint32]int32; GetObservations func() *gno.land/p/nt/bptree/v0.BPTree; GetPendingProtocolFee func(string) int64; GetPendingProtocolFees func() map[string]int64; GetPoolCreationFee func() int64; GetPools func() *gno.land/p/nt/bptree/v0.BPTree; GetSlot0FeeProtocol func() uint8; GetSwapEndHook func() func(.uverse.realm, string) .uverse.error; GetSwapStartHook func() func(.uverse.realm, string, int64); GetTickCrossHook func() func(.uverse.realm, string, int32, bool, int64); GetUnlocked func() bool; GetWithdrawalFeeBPS func() uint64; HasFeeAmountTickSpacing func() bool; HasObservations func() bool; HasPendingProtocolFees func() bool; HasPoolCreationFee func() bool; HasPools func() bool; HasSlot0FeeProtocol func() bool; HasSwapEndHook func() bool; HasSwapStartHook func() bool; HasTickCrossHook func() bool; HasUnlocked func() bool; HasWithdrawalFeeBPS func() bool; RemovePendingProtocolFee func(int, .uverse.realm, string) .uverse.error; SetFeeAmountTickSpacing func(int, .uverse.realm, map[uint32]int32) .uverse.error; SetObservations func(int, .uverse.realm, *gno.land/p/nt/bptree/v0.BPTree) .uverse.error; SetPendingProtocolFee func(int, .uverse.realm, string, int64) .uverse.error; SetPendingProtocolFees func(int, .uverse.realm, map[string]int64) .uverse.error; SetPoolCreationFee func(int, .uverse.realm, int64) .uverse.error; SetPools func(int, .uverse.realm, *gno.land/p/nt/bptree/v0.BPTree) .uverse.error; SetSlot0FeeProtocol func(int, .uverse.realm, uint8) .uverse.error; SetSwapEndHook func(int, .uverse.realm, func(.uverse.realm, string) .uverse.error) .uverse.error; SetSwapStartHook func(int, .uverse.realm, func(.uverse.realm, string, int64)) .uverse.error; SetTickCrossHook func(int, .uverse.realm, func(.uverse.realm, string, int32, bool, int64)) .uverse.error; SetUnlocked func(int, .uverse.realm, bool) .uverse.error; SetWithdrawalFeeBPS func(int, .uverse.realm, uint64) .uverse.error}) interface {Burn func(int, .uverse.realm, string, string, uint32, int32, int32, string, .uverse.address) (string, string); Collect func(int, .uverse.realm, string, string, uint32, .uverse.address, int32, int32, string, string) (string, string); CollectProtocol func(int, .uverse.realm, string, string, uint32, .uverse.address, string, string) (string, string); CollectSwapFee func(int, .uverse.realm, string, string, uint32, .uverse.address, int32, int32, string, string) (string, string, string, string); CreatePool func(int, .uverse.realm, string, string, uint32, string); DrySwap func(string, string, uint32, bool, string, string) (string, string, .uverse.error); ExistsPoolPath func(string) bool; GetBalanceToken0 func(string) (int64, .uverse.error); GetBalanceToken1 func(string) (int64, .uverse.error); GetFee func(string) (uint32, .uverse.error); GetFeeAmountTickSpacing func(uint32) (int32, .uverse.error); GetFeeAmountTickSpacings func() map[uint32]int32; GetFeeGrowthGlobal0X128 func(string) (*gno.land/p/gnoswap/uint256/v1.Uint, .uverse.error); GetFeeGrowthGlobal1X128 func(string) (*gno.land/p/gnoswap/uint256/v1.Uint, .uverse.error); GetFeeGrowthGlobalX128 func(string) (*gno.land/p/gnoswap/uint256/v1.Uint, *gno.land/p/gnoswap/uint256/v1.Uint, .uverse.error); GetInitializedTicksInRange func(string, int32, int32) ([]int32, .uverse.error); GetLiquidity func(string) (*gno.land/p/gnoswap/uint256/v1.Uint, .uverse.error); GetObservationAt func(string, uint16) (gno.land/r/gnoswap/pool.Observation, .uverse.error); GetPendingProtocolFees func() map[string]int64; GetPoolCreationFee func() int64; GetPoolPositions func(string) *gno.land/p/nt/bptree/rotree/v0.ReadOnlyTree; GetPools func() *gno.land/p/nt/bptree/rotree/v0.ReadOnlyTree; GetPositionFeeGrowthInside0LastX128 func(string, string) (string, .uverse.error); GetPositionFeeGrowthInside1LastX128 func(string, string) (string, .uverse.error); GetPositionFeeGrowthInsideLastX128 func(string, string) (string, string, .uverse.error); GetPositionLiquidity func(string, string) (string, .uverse.error); GetPositionTokensOwed0 func(string, string) (int64, .uverse.error); GetPositionTokensOwed1 func(string, string) (int64, .uverse.error); GetProtocolFeesToken0 func(string) (int64, .uverse.error); GetProtocolFeesToken1 func(string) (int64, .uverse.error); GetSlot0 func(string) gno.land/r/gnoswap/pool.Slot0; GetSlot0FeeProtocol func(string) (uint8, .uverse.error); GetSlot0SqrtPriceX96 func(string) (*gno.land/p/gnoswap/uint256/v1.Uint, .uverse.error); GetSlot0Tick func(string) (int32, .uverse.error); GetSlot0Unlocked func(string) (bool, .uverse.error); GetTickBitmaps func(string, int16) (string, .uverse.error); GetTickCumulativeOutside func(string, int32) (int64, .uverse.error); GetTickFeeGrowthOutside0X128 func(string, int32) (string, .uverse.error); GetTickFeeGrowthOutside1X128 func(string, int32) (string, .uverse.error); GetTickFeeGrowthOutsideX128 func(string, int32) (string, string, .uverse.error); GetTickInfo func(string, int32) (gno.land/r/gnoswap/pool.TickInfo, .uverse.error); GetTickInitialized func(string, int32) (bool, .uverse.error); GetTickLiquidityGross func(string, int32) (string, .uverse.error); GetTickLiquidityNet func(string, int32) (string, .uverse.error); GetTickSecondsOutside func(string, int32) (uint32, .uverse.error); GetTickSecondsPerLiquidityOutsideX128 func(string, int32) (string, .uverse.error); GetTickSpacing func(string) (int32, .uverse.error); GetToken0Path func(string) (string, .uverse.error); GetToken1Path func(string) (string, .uverse.error); GetWithdrawalFee func() uint64; IncreaseObservationCardinalityNext func(int, .uverse.realm, string, string, uint32, uint16); Mint func(int, .uverse.realm, string, string, uint32, int32, int32, string, .uverse.address) (string, string); Observe func(string, []uint32) ([]int64, []string, .uverse.error); OracleConsult func(string, uint32) (int32, *gno.land/p/gnoswap/uint256/v1.Uint, .uverse.error); Render func(string) string; SetFeeProtocol func(int, .uverse.realm, uint8, uint8); SetPoolCreationFee func(int, .uverse.realm, int64); SetSwapEndHook func(int, .uverse.realm, func(.uverse.realm, string) .uverse.error); SetSwapStartHook func(int, .uverse.realm, func(.uverse.realm, string, int64)); SetTickCrossHook func(int, .uverse.realm, func(.uverse.realm, string, int32, bool, int64)); SetWithdrawalFee func(int, .uverse.realm, uint64); SnapshotCumulativesInside func(string, int32, int32) (int64, *gno.land/p/gnoswap/uint256/v1.Uint, uint32, .uverse.error); Swap func(int, .uverse.realm, string, string, uint32, .uverse.address, bool, string, string, func(.uverse.realm, int64, int64, *gno.land/r/gnoswap/pool.CallbackMarker) .uverse.error) (string, string)}

    • NewTickEventInfo(tickID int32, tickInfo struct{liquidityGross string; liquidityNet string; feeGrowthOutside0X128 string; feeGrowthOutside1X128 string; tickCumulativeOutside int64; secondsPerLiquidityOutsideX128 string; secondsOutside uint32; initialized bool}) *gno.land/r/gnoswap/pool/v1.tickEventInfo

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

    Rendered

    RenderedRawgnoweb ↗
    This realm does not provide renderable output (vm/qrender → NoRenderDeclError). View on gnoweb ↗

    vm/qrender output, sanitized (docs/render-security.md) and displayed in an empty-sandbox iframe — scripts, forms and popups cannot run. Links stay inert in-preview; right-click to open.

    i256 "gno.land/p/gnoswap/int256/v1"
    9 u256 "gno.land/p/gnoswap/uint256/v1"
    10 pl "gno.land/r/gnoswap/pool"
    11)
    12
    13// MAX_LIQUIDITY_PER_TICK_* values are spacing-specific limits returned by
    14// calculateMaxLiquidityPerTick; they are not a universal uint128 maximum.
    15
    16const (
    17 MAX_LIQUIDITY_PER_TICK_SPACING_1 = "191757530477355301479181766273477"
    18 MAX_LIQUIDITY_PER_TICK_SPACING_10 = "1917569901783203986719870431555990"
    19 MAX_LIQUIDITY_PER_TICK_SPACING_60 = "11505743598341114571880798222544994"
    20 MAX_LIQUIDITY_PER_TICK_SPACING_200 = "38350317471085141830651933667504588"
    21 MIN_TICK int32 = -887272
    22 MAX_TICK int32 = 887272
    23)
    24
    25// maxLiquidityPerTickSpacing* return the precomputed max-liquidity-per-tick for
    26// each supported tick spacing. They are constructors (not package-level vars) so
    27// each caller receives a fresh instance — calculateMaxLiquidityPerTick returns
    28// the value directly to callers, and a shared singleton could otherwise be
    29// mutated in place and corrupt every caller. Values are built from little-endian
    30// [4]uint64 literals to avoid runtime decimal parsing.
    31func maxLiquidityPerTickSpacing1FromDec() *u256.Uint {
    32 return &u256.Uint{3639524637645646277, 10395196556700, 0, 0} // 191757530477355301479181766273477
    33}
    34
    35func maxLiquidityPerTickSpacing10FromDec() *u256.Uint {
    36 return &u256.Uint{4727306266354938262, 103951672670308, 0, 0} // 1917569901783203986719870431555990
    37}
    38
    39func maxLiquidityPerTickSpacing60FromDec() *u256.Uint {
    40 return &u256.Uint{1428959955126579298, 623727610269131, 0, 0} // 11505743598341114571880798222544994
    41}
    42
    43func maxLiquidityPerTickSpacing200FromDec() *u256.Uint {
    44 return &u256.Uint{6592429331424883148, 2078974875882965, 0, 0} // 38350317471085141830651933667504588
    45}
    46
    47// getFeeGrowthInside calculates the fee growth within a specified tick range.
    48//
    49// This function computes the accumulated fee growth for token 0 and token 1 inside a given tick range
    50// (`tickLower` to `tickUpper`) relative to the current tick position (`tickCurrent`). It isolates the fee
    51// growth within the range by subtracting the fee growth below the lower tick and above the upper tick
    52// from the global fee growth.
    53//
    54// Parameters:
    55// - tickLower: int32, the lower tick boundary of the range.
    56// - tickUpper: int32, the upper tick boundary of the range.
    57// - tickCurrent: int32, the current tick index.
    58// - feeGrowthGlobal0X128: *u256.Uint, the global fee growth for token 0 in X128 precision.
    59// - feeGrowthGlobal1X128: *u256.Uint, the global fee growth for token 1 in X128 precision.
    60//
    61// Returns:
    62// - *u256.Uint: Fee growth inside the tick range for token 0.
    63// - *u256.Uint: Fee growth inside the tick range for token 1.
    64//
    65// Workflow:
    66// 1. Retrieve the tick information (`lower` and `upper`) for the lower and upper tick boundaries
    67// using `p.getTick`.
    68// 2. Calculate the fee growth below the lower tick using `getFeeGrowthBelowX128`.
    69// 3. Calculate the fee growth above the upper tick using `getFeeGrowthAboveX128`.
    70// 4. Subtract the fee growth below and above the range from the global fee growth values:
    71// feeGrowthInside = feeGrowthGlobal - feeGrowthBelow - feeGrowthAbove
    72// 5. Return the computed fee growth values for token 0 and token 1 within the range.
    73//
    74// Behavior:
    75// - The fee growth is isolated within the range `[tickLower, tickUpper]`.
    76// - The function ensures the calculations accurately consider the tick boundaries and the current tick position.
    77//
    78// Example:
    79//
    80// ```gno
    81//
    82// feeGrowth0, feeGrowth1 := pool.getFeeGrowthInside(
    83// 100, 200, 150, globalFeeGrowth0, globalFeeGrowth1,
    84// )
    85// println("Fee Growth Inside (Token 0):", feeGrowth0)
    86// println("Fee Growth Inside (Token 1):", feeGrowth1)
    87//
    88// ```
    89func getFeeGrowthInside(
    90 p *pl.Pool,
    91 tickLower int32,
    92 tickUpper int32,
    93 tickCurrent int32,
    94 feeGrowthGlobal0X128 *u256.Uint,
    95 feeGrowthGlobal1X128 *u256.Uint,
    96) (*u256.Uint, *u256.Uint) {
    97 lower := getTick(p, tickLower)
    98 upper := getTick(p, tickUpper)
    99
    100 feeGrowthBelow0X128, feeGrowthBelow1X128 := getFeeGrowthBelowX128(tickLower, tickCurrent, feeGrowthGlobal0X128, feeGrowthGlobal1X128, lower)
    101 feeGrowthAbove0X128, feeGrowthAbove1X128 := getFeeGrowthAboveX128(tickUpper, tickCurrent, feeGrowthGlobal0X128, feeGrowthGlobal1X128, upper)
    102
    103 feeGrowthInside0X128 := u256.Zero().Sub(u256.Zero().Sub(feeGrowthGlobal0X128, feeGrowthBelow0X128), feeGrowthAbove0X128)
    104 feeGrowthInside1X128 := u256.Zero().Sub(u256.Zero().Sub(feeGrowthGlobal1X128, feeGrowthBelow1X128), feeGrowthAbove1X128)
    105
    106 return feeGrowthInside0X128, feeGrowthInside1X128
    107}
    108
    109// tickUpdate updates the state of a specific tick.
    110//
    111// This function applies a given liquidity change (liquidityDelta) to the specified tick, updates
    112// the fee growth values if necessary, and adjusts the net liquidity based on whether the tick
    113// is an upper or lower boundary. It also verifies that the total liquidity does not exceed the
    114// maximum allowed value and ensures the net liquidity stays within the valid int128 range.
    115//
    116// Parameters:
    117// - tick: int32, the index of the tick to update.
    118// - tickCurrent: int32, the current active tick index.
    119// - liquidityDelta: *i256.Int, the amount of liquidity to add or remove.
    120// - feeGrowthGlobal0X128: *u256.Uint, the global fee growth value for token 0.
    121// - feeGrowthGlobal1X128: *u256.Uint, the global fee growth value for token 1.
    122// - secondsPerLiquidityCumulativeX128: *u256.Uint, the current oracle accumulator used to
    123// seed the outside accumulator of a newly initialized active tick (tick <= tickCurrent).
    124// - tickCumulative: int64, the current oracle tick accumulator used for the same seeding.
    125// - blockTimestamp: int64, the current block timestamp used for the same seeding.
    126// - upper: bool, indicates if this is the upper boundary (true for upper, false for lower).
    127// - maxLiquidity: *u256.Uint, the maximum allowed liquidity.
    128//
    129// Returns:
    130// - flipped: bool, indicates if the tick's initialization state has changed.
    131// (e.g., liquidity transitioning from zero to non-zero, or vice versa)
    132//
    133// Workflow:
    134// 1. Nil input values are replaced with zero.
    135// 2. The function retrieves the tick information for the specified tick index.
    136// 3. Applies the liquidityDelta to compute the new total liquidity (liquidityGross).
    137// - If the total liquidity exceeds the maximum allowed value, the function panics.
    138// 4. Checks whether the tick's initialized state has changed and sets the `flipped` flag.
    139// 5. If the tick was previously uninitialized and its index is less than or equal to the current tick,
    140// the fee growth values are initialized to the current global values.
    141// 6. Updates the tick's net liquidity:
    142// - For an upper boundary, it subtracts liquidityDelta.
    143// - For a lower boundary, it adds liquidityDelta.
    144// - Ensures the net liquidity remains within the int128 range using `checkOverFlowInt128`.
    145// 7. Updates the tick's state with the new values.
    146// 8. Returns whether the tick's initialized state has flipped.
    147//
    148// Panic Conditions:
    149// - The total liquidity (liquidityGross) exceeds the maximum allowed liquidity (maxLiquidity).
    150// - The net liquidity (liquidityNet) exceeds the int128 range.
    151//
    152// Example:
    153//
    154// ```gno
    155//
    156// flipped := pool.tickUpdate(10, 5, liquidityDelta, feeGrowth0, feeGrowth1, secondsPerLiquidityCumulativeX128, tickCumulative, blockTimestamp, true, maxLiquidity)
    157// println("Tick flipped:", flipped)
    158//
    159// ```
    160func tickUpdate(
    161 p *pl.Pool,
    162 tick int32,
    163 tickCurrent int32,
    164 liquidityDelta *i256.Int,
    165 feeGrowthGlobal0X128 *u256.Uint,
    166 feeGrowthGlobal1X128 *u256.Uint,
    167 secondsPerLiquidityCumulativeX128 *u256.Uint,
    168 tickCumulative int64,
    169 blockTimestamp int64,
    170 upper bool,
    171 maxLiquidity *u256.Uint,
    172) (flipped bool) {
    173 tickInfo := getTick(p, tick)
    174
    175 liquidityGrossBefore := u256.MustFromDecimal(tickInfo.LiquidityGross())
    176 liquidityGrossAfter := gnsmath.LiquidityMathAddDelta(liquidityGrossBefore, liquidityDelta)
    177
    178 if !liquidityGrossAfter.Lte(maxLiquidity) {
    179 panic(newErrorWithDetail(
    180 errLiquidityCalculation,
    181 ufmt.Sprintf("liquidityGrossAfter(%s) overflows maxLiquidity(%s)", liquidityGrossAfter.ToString(), maxLiquidity.ToString()),
    182 ))
    183 }
    184
    185 flipped = liquidityGrossAfter.IsZero() != liquidityGrossBefore.IsZero()
    186
    187 if liquidityGrossBefore.IsZero() {
    188 if tick <= tickCurrent {
    189 tickInfo.SetFeeGrowthOutside0X128(feeGrowthGlobal0X128.ToString())
    190 tickInfo.SetFeeGrowthOutside1X128(feeGrowthGlobal1X128.ToString())
    191 tickInfo.SetSecondsPerLiquidityOutsideX128(secondsPerLiquidityCumulativeX128.ToString())
    192 tickInfo.SetTickCumulativeOutside(tickCumulative)
    193 tickInfo.SetSecondsOutside(uint32(blockTimestamp))
    194 }
    195 tickInfo.SetInitialized(true)
    196 }
    197
    198 tickInfo.SetLiquidityGross(liquidityGrossAfter.ToString())
    199
    200 liquidityNet := i256.MustFromDecimal(tickInfo.LiquidityNet())
    201 if upper {
    202 newLiquidityNet := i256.Zero().Sub(liquidityNet, liquidityDelta)
    203 checkOverFlowInt128(newLiquidityNet)
    204 tickInfo.SetLiquidityNet(newLiquidityNet.ToString())
    205 } else {
    206 newLiquidityNet := i256.Zero().Add(liquidityNet, liquidityDelta)
    207 checkOverFlowInt128(newLiquidityNet)
    208 tickInfo.SetLiquidityNet(newLiquidityNet.ToString())
    209 }
    210
    211 setTick(p, tick, tickInfo)
    212
    213 return flipped
    214}
    215
    216// tickCross updates a tick's state when it is crossed and returns the liquidity net.
    217// Updates fee growth and oracle accumulator values for the tick.
    218func tickCross(
    219 p *pl.Pool,
    220 tick int32,
    221 feeGrowthGlobal0X128 *u256.Uint,
    222 feeGrowthGlobal1X128 *u256.Uint,
    223 secondsPerLiquidityCumulativeX128 *u256.Uint,
    224 tickCumulative int64,
    225 blockTimestamp int64,
    226) *i256.Int {
    227 thisTick := getTick(p, tick)
    228
    229 feeOutside0 := u256.MustFromDecimal(thisTick.FeeGrowthOutside0X128())
    230 feeOutside1 := u256.MustFromDecimal(thisTick.FeeGrowthOutside1X128())
    231 thisTick.SetFeeGrowthOutside0X128(u256.Zero().Sub(feeGrowthGlobal0X128, feeOutside0).ToString())
    232 thisTick.SetFeeGrowthOutside1X128(u256.Zero().Sub(feeGrowthGlobal1X128, feeOutside1).ToString())
    233
    234 tickSecondsPerLiquidity := u256.MustFromDecimal(thisTick.SecondsPerLiquidityOutsideX128())
    235 thisTick.SetSecondsPerLiquidityOutsideX128(u256.Zero().Sub(secondsPerLiquidityCumulativeX128, tickSecondsPerLiquidity).ToString())
    236 thisTick.SetTickCumulativeOutside(tickCumulative - thisTick.TickCumulativeOutside())
    237 thisTick.SetSecondsOutside(uint32(blockTimestamp) - thisTick.SecondsOutside())
    238
    239 setTick(p, tick, thisTick)
    240
    241 return i256.MustFromDecimal(thisTick.LiquidityNet())
    242}
    243
    244// setTick updates the tick data for the specified tick index in the pool.
    245func setTick(p *pl.Pool, tick int32, newTickInfo pl.TickInfo) {
    246 p.SetTick(tick, newTickInfo)
    247}
    248
    249// deleteTick deletes the tick data for the specified tick index in the pool.
    250func deleteTick(p *pl.Pool, tick int32) {
    251 p.DeleteTick(tick)
    252}
    253
    254// getTick retrieves the TickInfo associated with the specified tick index from the pool.
    255// If the TickInfo contains any nil fields, they are replaced with zero values using valueOrZero.
    256//
    257// Parameters:
    258// - tick: The tick index (int32) for which the TickInfo is to be retrieved.
    259//
    260// Behavior:
    261// - Retrieves the TickInfo for the given tick from the pool's tick map.
    262// - Ensures that all fields of TickInfo are non-nil by calling valueOrZero, which replaces nil values with zero.
    263// - Returns the updated TickInfo.
    264//
    265// Returns:
    266// - TickInfo: The tick data with all fields guaranteed to have valid values (nil fields are set to zero).
    267//
    268// Use Case:
    269// This function ensures the retrieved tick data is always valid and safe for further operations,
    270// such as calculations or updates, by sanitizing nil fields in the TickInfo structure.
    271func getTick(p *pl.Pool, tick int32) pl.TickInfo {
    272 tickInfo, err := p.GetTick(tick)
    273 if err != nil {
    274 return pl.NewTickInfo()
    275 }
    276
    277 return tickInfo
    278}
    279
    280// mustGetTick retrieves the TickInfo for a specific tick, panicking if the tick does not exist.
    281//
    282// This function ensures that the requested tick data exists in the pool's tick mapping.
    283// If the tick does not exist, it panics with an appropriate error message.
    284//
    285// Parameters:
    286// - tick: int32, the index of the tick to retrieve.
    287//
    288// Returns:
    289// - TickInfo: The information associated with the specified tick.
    290//
    291// Behavior:
    292// - Checks if the tick exists in the pool's tick mapping (`p.ticks`).
    293// - If the tick exists, it returns the corresponding `TickInfo`.
    294// - If the tick does not exist, the function panics with a descriptive error.
    295//
    296// Panic Conditions:
    297// - The specified tick does not exist in the pool's mapping.
    298//
    299// Example:
    300//
    301// ```gno
    302//
    303// tickInfo := pool.mustGetTick(10)
    304// ufmt.Println("Tick Info:", tickInfo)
    305//
    306// ```
    307func mustGetTick(p *pl.Pool, tick int32) *pl.TickInfo {
    308 tickInfo, err := p.GetTick(tick)
    309 if err != nil {
    310 panic(err)
    311 }
    312
    313 return &tickInfo
    314}
    315
    316// calculateMaxLiquidityPerTick calculates the maximum liquidity
    317// per tick for a given tick spacing.
    318func calculateMaxLiquidityPerTick(tickSpacing int32) *u256.Uint {
    319 switch tickSpacing {
    320 case 1:
    321 return maxLiquidityPerTickSpacing1FromDec()
    322 case 10:
    323 return maxLiquidityPerTickSpacing10FromDec()
    324 case 60:
    325 return maxLiquidityPerTickSpacing60FromDec()
    326 case 200:
    327 return maxLiquidityPerTickSpacing200FromDec()
    328 default:
    329 minTick := (MIN_TICK / tickSpacing) * tickSpacing
    330 maxTick := (MAX_TICK / tickSpacing) * tickSpacing
    331 numTicks := uint64((maxTick-minTick)/tickSpacing) + 1
    332
    333 return u256.Zero().Div(consts.MaxUint128(), u256.NewUint(numTicks))
    334 }
    335}
    336
    337// getFeeGrowthBelowX128 calculates the fee growth below a specified tick.
    338//
    339// This function computes the fee growth for token 0 and token 1 below a given tick (`tickLower`)
    340// relative to the current tick (`tickCurrent`). The fee growth values are adjusted based on whether
    341// the `tickCurrent` is above or below the `tickLower`.
    342//
    343// Parameters:
    344// - tickLower: int32, the lower tick boundary for fee calculation.
    345// - tickCurrent: int32, the current tick index.
    346// - feeGrowthGlobal0X128: *u256.Uint, the global fee growth for token 0 in X128 precision.
    347// - feeGrowthGlobal1X128: *u256.Uint, the global fee growth for token 1 in X128 precision.
    348// - lowerTick: TickInfo, the fee growth and liquidity details for the lower tick.
    349//
    350// Returns:
    351// - *u256.Uint: Fee growth below `tickLower` for token 0.
    352// - *u256.Uint: Fee growth below `tickLower` for token 1.
    353//
    354// Workflow:
    355// 1. If `tickCurrent` is greater than or equal to `tickLower`:
    356// - Return the `feeGrowthOutside0X128` and `feeGrowthOutside1X128` values of the `lowerTick`.
    357// 2. If `tickCurrent` is below `tickLower`:
    358// - Compute the fee growth below the lower tick by subtracting `feeGrowthOutside` values
    359// from the global fee growth values (`feeGrowthGlobal0X128` and `feeGrowthGlobal1X128`).
    360// 3. Return the calculated fee growth values for both tokens.
    361//
    362// Behavior:
    363// - If `tickCurrent >= tickLower`, the fee growth outside the lower tick is returned as-is.
    364// - If `tickCurrent < tickLower`, the fee growth is calculated as:
    365// feeGrowthBelow = feeGrowthGlobal - feeGrowthOutside
    366//
    367// Example:
    368//
    369// ```gno
    370//
    371// feeGrowth0, feeGrowth1 := getFeeGrowthBelowX128(
    372// 100, 150, globalFeeGrowth0, globalFeeGrowth1, lowerTickInfo,
    373// )
    374// println("Fee Growth Below:", feeGrowth0, feeGrowth1)
    375func getFeeGrowthBelowX128(
    376 tickLower, tickCurrent int32,
    377 feeGrowthGlobal0X128, feeGrowthGlobal1X128 *u256.Uint,
    378 lowerTick pl.TickInfo,
    379) (*u256.Uint, *u256.Uint) {
    380 feeOutside0 := u256.MustFromDecimal(lowerTick.FeeGrowthOutside0X128())
    381 feeOutside1 := u256.MustFromDecimal(lowerTick.FeeGrowthOutside1X128())
    382
    383 if tickCurrent >= tickLower {
    384 return feeOutside0, feeOutside1
    385 }
    386
    387 feeGrowthBelow0X128 := u256.Zero().Sub(feeGrowthGlobal0X128, feeOutside0)
    388 feeGrowthBelow1X128 := u256.Zero().Sub(feeGrowthGlobal1X128, feeOutside1)
    389
    390 return feeGrowthBelow0X128, feeGrowthBelow1X128
    391}
    392
    393// getFeeGrowthAboveX128 calculates the fee growth above a specified tick.
    394//
    395// This function computes the fee growth for token 0 and token 1 above a given tick (`tickUpper`)
    396// relative to the current tick (`tickCurrent`). The fee growth values are adjusted based on whether
    397// the `tickCurrent` is above or below the `tickUpper`.
    398//
    399// Parameters:
    400// - tickUpper: int32, the upper tick boundary for fee calculation.
    401// - tickCurrent: int32, the current tick index.
    402// - feeGrowthGlobal0X128: *u256.Uint, the global fee growth for token 0 in X128 precision.
    403// - feeGrowthGlobal1X128: *u256.Uint, the global fee growth for token 1 in X128 precision.
    404// - upperTick: TickInfo, the fee growth and liquidity details for the upper tick.
    405//
    406// Returns:
    407// - *u256.Uint: Fee growth above `tickUpper` for token 0.
    408// - *u256.Uint: Fee growth above `tickUpper` for token 1.
    409//
    410// Workflow:
    411// 1. If `tickCurrent` is less than `tickUpper`:
    412// - Return the `feeGrowthOutside0X128` and `feeGrowthOutside1X128` values of the `upperTick`.
    413// 2. If `tickCurrent` is greater than or equal to `tickUpper`:
    414// - Compute the fee growth above the upper tick by subtracting `feeGrowthOutside` values
    415// from the global fee growth values (`feeGrowthGlobal0X128` and `feeGrowthGlobal1X128`).
    416// 3. Return the calculated fee growth values for both tokens.
    417//
    418// Behavior:
    419// - If `tickCurrent < tickUpper`, the fee growth outside the upper tick is returned as-is.
    420// - If `tickCurrent >= tickUpper`, the fee growth is calculated as:
    421// feeGrowthAbove = feeGrowthGlobal - feeGrowthOutside
    422//
    423// Example:
    424//
    425// feeGrowth0, feeGrowth1 := getFeeGrowthAboveX128(
    426// 200, 150, globalFeeGrowth0, globalFeeGrowth1, upperTickInfo,
    427// )
    428// println("Fee Growth Above:", feeGrowth0, feeGrowth1)
    429//
    430// ```
    431func getFeeGrowthAboveX128(
    432 tickUpper, tickCurrent int32,
    433 feeGrowthGlobal0X128, feeGrowthGlobal1X128 *u256.Uint,
    434 upperTick pl.TickInfo,
    435) (*u256.Uint, *u256.Uint) {
    436 feeOutside0 := u256.MustFromDecimal(upperTick.FeeGrowthOutside0X128())
    437 feeOutside1 := u256.MustFromDecimal(upperTick.FeeGrowthOutside1X128())
    438
    439 if tickCurrent < tickUpper {
    440 return feeOutside0, feeOutside1
    441 }
    442
    443 feeGrowthAbove0X128 := u256.Zero().Sub(feeGrowthGlobal0X128, feeOutside0)
    444 feeGrowthAbove1X128 := u256.Zero().Sub(feeGrowthGlobal1X128, feeOutside1)
    445
    446 return feeGrowthAbove0X128, feeGrowthAbove1X128
    447}
    448
    449// validateTicks validates the tick range for a liquidity position.
    450//
    451// This function performs three essential checks to ensure the provided
    452// tick values are valid before creating or modifying a liquidity position.
    453func validateTicks(tickLower, tickUpper int32) error {
    454 if tickLower >= tickUpper {
    455 return makeErrorWithDetails(
    456 errInvalidTickRange,
    457 ufmt.Sprintf("tickLower(%d), tickUpper(%d)", tickLower, tickUpper),
    458 )
    459 }
    460
    461 if tickLower < MIN_TICK {
    462 return makeErrorWithDetails(
    463 errTickLowerInvalid,
    464 ufmt.Sprintf("tickLower(%d) < MIN_TICK(%d)", tickLower, MIN_TICK),
    465 )
    466 }
    467
    468 if tickUpper > MAX_TICK {
    469 return makeErrorWithDetails(
    470 errTickUpperInvalid,
    471 ufmt.Sprintf("tickUpper(%d) > MAX_TICK(%d)", tickUpper, MAX_TICK),
    472 )
    473 }
    474
    475 return nil
    476}
    477