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
  • transfer.gnogno
    1package pool23import (4	ufmt "gno.land/p/nt/ufmt/v0"56	prabc "gno.land/p/gnoswap/rbac/v1"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.

    "gno.land/r/gnoswap/access/v1"
    9 "gno.land/r/gnoswap/common"
    10 pl "gno.land/r/gnoswap/pool"
    11
    12 "gno.land/p/gnoswap/gnsmath/v1"
    13 i256 "gno.land/p/gnoswap/int256/v1"
    14 u256 "gno.land/p/gnoswap/uint256/v1"
    15)
    16
    17// safeTransfer performs a token transfer out of the pool while ensuring
    18// the pool has sufficient balance and updating internal accounting.
    19// This function is typically used during swaps and liquidity removals.
    20//
    21// Important requirements:
    22// - The amount must be a positive value representing tokens to transfer out
    23// - The pool must have sufficient balance for the transfer
    24// - The transfer amount must fit within int64 range
    25//
    26// Parameters:
    27// - p: the pool instance
    28// - to: destination address for the transfer
    29// - tokenPath: path identifier of the token to transfer
    30// - amount: amount to transfer (positive u256.Uint value)
    31// - isToken0: true if transferring token0, false for token1
    32//
    33// The function will:
    34// 1. Check pool has sufficient balance
    35// 2. Execute the transfer
    36// 3. Subtract the amount from pool's internal balance
    37//
    38// Panics if any validation fails or if the transfer fails
    39func (i *poolV1) safeTransfer(
    40 _ int,
    41 rlm realm,
    42 p *pl.Pool,
    43 to address,
    44 tokenPath string,
    45 amount *u256.Uint,
    46 isToken0 bool,
    47) {
    48 token0 := p.BalanceToken0()
    49 token1 := p.BalanceToken1()
    50 amountInt64 := gnsmath.SafeConvertToInt64(amount)
    51
    52 if err := validatePoolBalance(token0, token1, amountInt64, isToken0); err != nil {
    53 panic(err)
    54 }
    55
    56 common.SafeGRC20Transfer(0, rlm, tokenPath, to, amountInt64)
    57
    58 newBalance, err := updatePoolBalance(token0, token1, amountInt64, isToken0)
    59 if err != nil {
    60 panic(err)
    61 }
    62
    63 poolBalances := p.Balances()
    64
    65 if isToken0 {
    66 poolBalances.SetToken0(newBalance)
    67 } else {
    68 poolBalances.SetToken1(newBalance)
    69 }
    70
    71 p.SetBalances(poolBalances)
    72}
    73
    74// safeTransferFrom securely transfers tokens into the pool while ensuring balance consistency.
    75//
    76// This function performs the following steps:
    77// 1. Validates and converts the transfer amount to `int64` using `gnsmath.SafeConvertToInt64`.
    78// 2. Executes the token transfer using `TransferFrom` via the token teller contract.
    79// 3. Verifies that the destination balance reflects the correct amount after transfer.
    80// 4. Updates the pool's internal balances (`token0` or `token1`) and validates the updated state.
    81//
    82// Parameters:
    83// - p (*pl.Pool): The pool instance to transfer tokens into.
    84// - from (address): Source address for the token transfer.
    85// - to (address): Destination address, typically the pool address.
    86// - tokenPath (string): Path identifier for the token being transferred.
    87// - amount (*u256.Uint): The amount of tokens to transfer (must be a positive value).
    88// - isToken0 (bool): A flag indicating whether the token being transferred is token0 (`true`) or token1 (`false`).
    89//
    90// Panics:
    91// - If the `amount` exceeds the int64 range during conversion.
    92// - If the token transfer (`TransferFrom`) fails.
    93// - If the destination balance after the transfer does not match the expected amount.
    94// - If the pool's internal balances (`token0` or `token1`) overflow or become inconsistent.
    95//
    96// Notes:
    97// - The function assumes that the sender (`from`) has approved the pool to spend the specified tokens.
    98// - The balance consistency check ensures that no tokens are lost or double-counted during the transfer.
    99// - Pool balance updates are performed atomically to ensure internal consistency.
    100func (i *poolV1) safeTransferFrom(
    101 _ int,
    102 rlm realm,
    103 p *pl.Pool,
    104 from, to address,
    105 tokenPath string,
    106 amount *u256.Uint,
    107 isToken0 bool,
    108) {
    109 amountInt64 := gnsmath.SafeConvertToInt64(amount)
    110
    111 beforeBalance := common.BalanceOf(tokenPath, to)
    112
    113 common.SafeGRC20TransferFrom(0, rlm, tokenPath, from, to, amountInt64)
    114
    115 afterBalance := common.BalanceOf(tokenPath, to)
    116 if gnsmath.SafeAddInt64(beforeBalance, amountInt64) != afterBalance {
    117 panic(ufmt.Sprintf(
    118 "%v. beforeBalance(%d) + amount(%d) != afterBalance(%d)",
    119 errTransferFailed, beforeBalance, amountInt64, afterBalance,
    120 ))
    121 }
    122
    123 poolBalances := p.Balances()
    124
    125 // update pool balances
    126 if isToken0 {
    127 poolBalances.SetToken0(gnsmath.SafeAddInt64(poolBalances.Token0(), amountInt64))
    128 } else {
    129 poolBalances.SetToken1(gnsmath.SafeAddInt64(poolBalances.Token1(), amountInt64))
    130 }
    131
    132 p.SetBalances(poolBalances)
    133}
    134
    135// safeSwapCallback executes a swap callback and validates the token payment.
    136//
    137// This function implements the flash swap pattern where the pool first sends output tokens
    138// to the recipient, then invokes the callback to receive input tokens from the caller.
    139// The callback is responsible for transferring the required input tokens to the pool.
    140//
    141// Callback Signature:
    142//
    143// func(cur realm, amount0Delta, amount1Delta int64, _ *pool.CallbackMarker) error
    144//
    145// Delta Convention (following Uniswap V3 standard):
    146// - Positive delta: Amount the pool must RECEIVE (input token)
    147// - Negative delta: Amount the pool has SENT (output token)
    148//
    149// For zeroForOne swaps (token0 → token1):
    150// - amount0Delta > 0: Pool receives token0 (input)
    151// - amount1Delta < 0: Pool sends token1 (output)
    152//
    153// For oneForZero swaps (token1 → token0):
    154// - amount0Delta < 0: Pool sends token0 (output)
    155// - amount1Delta > 0: Pool receives token1 (input)
    156//
    157// Parameters:
    158// - p: The pool instance
    159// - tokenPath: Path of the input token that pool must receive
    160// - amountInInt256: Amount pool must receive (positive i256.Int)
    161// - amountOutInt256: Amount pool has sent (negative i256.Int)
    162// - zeroForOne: Swap direction (true = token0 to token1)
    163// - swapCallback: Callback function that must transfer input tokens to pool
    164//
    165// The callback needed:
    166// 1. Verify the caller is the legitimate pool contract address to prevent unauthorized invocations
    167// 2. Transfer at least `amountIn` of input tokens to the pool
    168// 3. Return nil on success, or an error to revert the swap
    169//
    170// Example callback implementation:
    171//
    172// func(cur realm, amount0Delta, amount1Delta int64, _ *pool.CallbackMarker) error {
    173// // Security check: ensure this callback is invoked by the legitimate pool
    174// caller := runtime.PreviousRealm().Address()
    175// poolAddr := chain.PackageAddress("gno.land/r/gnoswap/pool")
    176//
    177// if caller != poolAddr {
    178// panic("unauthorized caller")
    179// }
    180//
    181// if amount0Delta > 0 {
    182// // Transfer token0 to pool
    183// token0.Transfer(cross, poolAddr, amount0Delta)
    184// }
    185// if amount1Delta > 0 {
    186// // Transfer token1 to pool
    187// token1.Transfer(cross, poolAddr, amount1Delta)
    188// }
    189// return nil
    190// }
    191func (i *poolV1) safeSwapCallback(
    192 _ int,
    193 rlm realm,
    194 p *pl.Pool,
    195 tokenPath string,
    196 amountInInt256 *i256.Int,
    197 amountOutInt256 *i256.Int,
    198 zeroForOne bool,
    199 swapCallback func(cur realm, amount0Delta, amount1Delta int64, _ *pl.CallbackMarker) error,
    200) {
    201 if swapCallback == nil {
    202 panic(makeErrorWithDetails(
    203 errInvalidInput,
    204 "swapCallback is nil",
    205 ))
    206 }
    207
    208 currentAddress := access.MustGetAddress(prabc.ROLE_POOL.String())
    209
    210 amountIn := amountInInt256.Int64()
    211 amountOut := amountOutInt256.Int64()
    212 balanceBefore := common.BalanceOf(tokenPath, currentAddress)
    213
    214 // Make callback to the calling contract
    215 // The contract should transfer tokens to pool within this callback
    216 // Following Uniswap V3 convention:
    217 // - Positive delta: amount the pool must receive (input token)
    218 // - Negative delta: amount the pool has sent (output token)
    219 var amount0Delta, amount1Delta, beforeTokenBalance int64
    220
    221 if zeroForOne {
    222 // zeroForOne: pool receives token0 (positive), sends token1 (negative)
    223 amount0Delta = amountIn
    224 amount1Delta = amountOut
    225 beforeTokenBalance = p.BalanceToken0()
    226 } else {
    227 // !zeroForOne: pool receives token1 (positive), sends token0 (negative)
    228 amount0Delta = amountOut
    229 amount1Delta = amountIn
    230 beforeTokenBalance = p.BalanceToken1()
    231 }
    232
    233 // execute swap callback
    234 // CallbackMarker is created by the pool module to enforce type-system level validation.
    235 // Allocation goes through pl.NewCallbackMarker so the alloc happens in pool realm
    236 // (interrealm v2 forbids /r/-declared types being constructed outside their owner).
    237 err := swapCallback(cross(rlm), amount0Delta, amount1Delta, pl.NewCallbackMarker())
    238 if err != nil {
    239 panic(err)
    240 }
    241
    242 balanceAfter := common.BalanceOf(tokenPath, currentAddress)
    243 balanceIncrease := gnsmath.SafeSubInt64(balanceAfter, balanceBefore)
    244
    245 // check insufficient payment by swap callback
    246 if balanceIncrease < amountIn {
    247 panic(makeErrorWithDetails(
    248 errInsufficientPayment,
    249 ufmt.Sprintf("insufficient payment: expected %d, received %d", amountIn, balanceIncrease),
    250 ))
    251 }
    252
    253 // check overflow update pool balance
    254 resultTokenBalance := gnsmath.SafeAddInt64(beforeTokenBalance, amountIn)
    255
    256 poolBalances := p.Balances()
    257
    258 if zeroForOne {
    259 poolBalances.SetToken0(resultTokenBalance)
    260 } else {
    261 poolBalances.SetToken1(resultTokenBalance)
    262 }
    263
    264 p.SetBalances(poolBalances)
    265}
    266
    267// validatePoolBalance checks if the pool has sufficient balance of either token0 and token1
    268// before proceeding with a transfer. This prevents the pool won't go into a negative balance.
    269func validatePoolBalance(token0, token1, amount int64, isToken0 bool) error {
    270 if amount < 0 {
    271 return ufmt.Errorf("%v. amount(%d) must be positive", errTransferFailed, amount)
    272 }
    273
    274 if isToken0 {
    275 if token0 < amount {
    276 return ufmt.Errorf(
    277 "%v. token0(%d) >= amount(%d)",
    278 errTransferFailed, token0, amount,
    279 )
    280 }
    281 return nil
    282 }
    283 if token1 < amount {
    284 return ufmt.Errorf(
    285 "%v. token1(%d) >= amount(%d)",
    286 errTransferFailed, token1, amount,
    287 )
    288 }
    289 return nil
    290}
    291
    292// updatePoolBalance calculates the new balance after a transfer and validate.
    293// It ensures the resulting balance won't be negative or overflow.
    294func updatePoolBalance(
    295 token0, token1, amount int64,
    296 isToken0 bool,
    297) (int64, error) {
    298 if amount < 0 {
    299 return 0, ufmt.Errorf("%v. amount(%d) must be positive", errBalanceUpdateFailed, amount)
    300 }
    301
    302 if isToken0 {
    303 if token0 < amount {
    304 return 0, ufmt.Errorf(
    305 "%v. cannot decrease, token0(%d) - amount(%d)",
    306 errBalanceUpdateFailed, token0, amount,
    307 )
    308 }
    309 return gnsmath.SafeSubInt64(token0, amount), nil
    310 }
    311
    312 if token1 < amount {
    313 return 0, ufmt.Errorf(
    314 "%v. cannot decrease, token1(%d) - amount(%d)",
    315 errBalanceUpdateFailed, token1, amount,
    316 )
    317 }
    318 return gnsmath.SafeSubInt64(token1, amount), nil
    319}
    320