const MaxQuotePercentage, MinQuotePercentage, PERCENTAGE_DENOMINATOR
QuoteConstraints defines the valid range for swap quote percentages
package router handles token swaps through GnoSwap liquidity pools.
Swap routing engine for optimal trade execution across pools.
Router handles swap execution across multiple pools, finding optimal paths and managing slippage protection for traders.
ExactInSwapRouteSwaps an exact input amount for output, subject to a minimum net output.
ExactOutSwapRouteSwaps for a requested final user output amount with maximum input. The
amountOut target is post-router-fee: the router requests the corresponding
gross pool output, deducts the fee, then validates and transfers the net output.
DrySwapRouteSimulates a swap without execution.
Routes in the router follow swap direction ordering: tokenIn:tokenOut:fee
Example for swapping GNS to WUGNOT:
gno.land/r/gnoswap/gns.GNS:gno.land/r/gnoland/wugnot.wugnot:3000
Pools are identified using alphabetical ordering: token0:token1:fee
Example pool identifier (same pool as above):
gno.land/r/gnoland/wugnot.wugnot:gno.land/r/gnoswap/gns.GNS:3000 # gnoland/wugnot < gnoswap/gns alphabetically
IMPORTANT: Router swap functions do not accept native ugnot directly.
pkgPath.SYMBOL) such as "gno.land/r/gnoland/wugnot.wugnot"pkgPath.SYMBOL) such as "gno.land/r/gnoland/wugnot.wugnot"This matches the current implementation:
wugnot)Single-hop format:
tokenIn:tokenOut:fee
Multi-hop format (using POOL separator):
tokenIn:tokenB:fee1*POOL*tokenB:tokenC:fee2*POOL*tokenC:tokenOut:fee3
Single-hop example:
# Swapping GNS to WUGNOT
Route: gno.land/r/gnoswap/gns.GNS:gno.land/r/gnoland/wugnot.wugnot:3000
# Router interprets: tokenIn=gns, tokenOut=wugnot, fee=3000
Multi-hop example (GNS → WUGNOT → TOKEN_C):
# Each segment follows swap direction, connected by *POOL*
gno.land/r/gnoswap/gns.GNS:gno.land/r/gnoland/wugnot.wugnot:3000*POOL*gno.land/r/gnoland/wugnot.wugnot:gno.land/r/<namespace>/token_c.TOKEN_C:500
Split large trades across routes to minimize impact:
quoteArr: positive percentage per route, with one quote for each routeThe current router implementation does not handle native ugnot directly. It rejects native-coin handling and routes swaps only through token keys (pkgPath.SYMBOL) such as wrapped GNOT (wugnot).
pkgPath.SYMBOL) such as gno.land/r/gnoland/wugnot.wugnot for both inputs/outputs and route specifications."ugnot" as inputToken or outputToken to router swap functions.wugnot token contract path directly.For live liquidity-changing swaps:
amountOutMin = expected * (1 - slippage%)These snippets call the public domain proxy from a realm function with a current cur token.
Import the proxy package and qualify its function names in integrating code.
1// Simple exact input swap
2amountIn, amountOut := ExactInSwapRoute(
3 cross(cur),
4 "gno.land/r/gnoswap/gns.GNS", // input token
5 "gno.land/r/gnoland/wugnot.wugnot", // output token
6 "1000000", // amount (6 decimals)
7 "gno.land/r/gnoswap/gns.GNS:gno.land/r/gnoland/wugnot.wugnot:3000", // route
8 "100", // 100% through route
9 "950000", // min output
10 time.Now().Unix() + 300, // deadline
11 "g1referrer...", // referral
12)
13
14// Multi-hop swap
15ExactInSwapRoute(
16 cross(cur),
17 "gno.land/r/gnoswap/gns.GNS",
18 "gno.land/r/<namespace>/token_c.TOKEN_C",
19 "1000000",
20 "gno.land/r/gnoswap/gns.GNS:gno.land/r/gnoland/wugnot.wugnot:3000*POOL*gno.land/r/gnoland/wugnot.wugnot:gno.land/r/<namespace>/token_c.TOKEN_C:3000",
21 "100",
22 "900000",
23 deadline,
24 "",
25)
26
27// Split route for large trades
28ExactInSwapRoute(
29 cross(cur),
30 "gno.land/r/gnoswap/gns.GNS",
31 "gno.land/r/gnoland/wugnot.wugnot",
32 "10000000000",
33 "gno.land/r/gnoswap/gns.GNS:gno.land/r/gnoland/wugnot.wugnot:500,gno.land/r/gnoswap/gns.GNS:gno.land/r/gnoland/wugnot.wugnot:3000",
34 "60,40", // 60% through 0.05%, 40% through 0.3%
35 "9500000000",
36 deadline,
37 "",
38)
Single-hop functions support partial execution through a nonzero
sqrtPriceLimitX96:
1// Partial swap with price limit - may not consume full input amount
2amountIn, amountOut := ExactInSingleSwapRoute(
3 cross(cur),
4 "gno.land/r/gnoswap/gns.GNS", // input token
5 "gno.land/r/gnoland/wugnot.wugnot", // output token
6 "1000000", // max amount to swap
7 "gno.land/r/gnoswap/gns.GNS:gno.land/r/gnoland/wugnot.wugnot:3000", // single route
8 "950000", // min output
9 "1000000000000000000", // sqrtPriceLimitX96 (price limit)
10 deadline,
11 "",
12)
13// If the price limit is reached, only a partial amount is swapped. For exact-in
14// this can consume less input; exact-out can deliver less than its target.
15// amountOutMin or amountInMax remains enforced, respectively.
Native Token Assumptions: Passing "ugnot" to router swap functions will fail because router entrypoints reject native-coin handling.
Route vs Token Identifier Confusion: Using "ugnot" in route strings instead of "gno.land/r/gnoland/wugnot.wugnot" will cause transactions to fail since no pools exist for the "ugnot" identifier.
Wrong Token Path:
gno.land/r/gnoland/wugnot.wugnot when swapping wrapped GNOTugnot to router swap functionspkgPath.SYMBOL) such as "gno.land/r/gnoland/wugnot.wugnot" for both parameters and routesBoth single-hop functions support partial execution when
sqrtPriceLimitX96 is nonzero:
amountOutMin or amountInMax) still appliespackage router handles token swaps through GnoSwap liquidity pools.
The router provides user-facing swap functions with slippage protection, multi-hop routing, and both exact-input and exact-output swap modes.
Live exact-input calls enforce a minimum output and deadline. Live exact-output calls enforce a maximum input and deadline. DrySwapRoute is read-only and has no deadline or transfer.
QuoteConstraints defines the valid range for swap quote percentages
ErrorMessages for DrySwapRoute operations
swap can be done by multiple pools to separate each pool, we use POOL_SEPARATOR
1const (
2 Unknown SwapType = rawUnknown
3 // ExactIn represents a swap type where the input amount is exact and the output amount may vary.
4 // Used when a user wants to swap a specific amount of input tokens.
5 ExactIn SwapType = rawExactIn
6
7 // ExactOut represents a swap type where the output amount is exact and the input amount may vary.
8 // Used when a user wants to swap a specific amount of output tokens.
9 ExactOut SwapType = rawExactOut
10)BuildSingleHopRoutePath formats one route-direction single-hop path.
Parameters:
Returns:
NewRouterV1 creates a router v1 implementation backed by routerStore.
Parameters:
Returns:
NewExactInParams creates parameters for an exact-input swap.
Parameters:
Returns:
NewExactInSwapOperation creates an exact-input operation for router execution.
Parameters:
Returns:
NewExactOutParams creates parameters for an exact-output swap.
Parameters:
Returns:
NewExactOutSwapOperation creates an exact-output operation for router execution.
Parameters:
Returns:
NewRouteParser creates a parser for comma-separated route and quote strings.
Returns:
ExactInParams contains parameters for exact input swaps.
Process executes the validated exact-input operation in the propagated realm.
Parameters:
Returns:
Validate checks the exact-input amount and parses route/quote allocations.
Returns:
ExactOutParams contains parameters for exact output swaps.
ExactOutSwapOperation handles swaps where the output amount is specified.
Process executes the validated exact-output operation in the propagated realm.
Parameters:
Returns:
Validate checks the exact-output amount and parses route/quote allocations.
Returns:
RouteParser handles parsing and validation of routes and quotes
ParseRoutes splits route and quote strings and validates their pairing.
Parameters:
Returns:
ValidateQuoteSum verifies that each quote is positive, at most 100, and totals 100.
Parameters:
Returns:
ValidateRoutesAndQuotes checks route count, route/quote cardinality, and quote sum.
Parameters:
Returns:
1type RouterOperation interface {
2 // Validate checks operation parameters before processing.
3 //
4 // Returns:
5 // - err: nil when operation input is valid; validation error otherwise
6 Validate() error
7 // Process executes the operation in the propagated realm context.
8 //
9 // Parameters:
10 // - _: leading operation discriminator; callers pass 0
11 // - rlm: propagated current realm context used for pool interaction
12 //
13 // Returns:
14 // - result: swap amounts and route metadata, or nil when processing fails
15 // - err: nil on success; execution error otherwise
16 Process(_ int, rlm realm) (*SwapResult, error)
17} 1type SingleSwapParams struct {
2 tokenIn string // token to spend
3 tokenOut string // token to receive
4 fee uint32 // fee of the pool used to swap
5
6 // Amount specified for the swap:
7 // - Positive: exact input amount (tokenIn)
8 // - Negative: exact output amount (tokenOut)
9 amountSpecified int64
10
11 sqrtPriceLimitX96 *u256.Uint // sqrtPriceLimitX96 for the swap, empty string or zero string means no limit
12}SingleSwapParams contains parameters for executing a single pool swap. It represents the simplest form of swap that occurs within a single liquidity pool.
Fee returns the pool fee tier.
Returns:
SqrtPriceLimitX96 returns the optional Q64.96 square-root price limit. A nil stored limit is normalized to the zero value, which callers interpret as no explicit limit.
Returns:
TokenIn returns the input token contract path.
Returns:
TokenOut returns the output token contract path.
Returns:
SwapCallbackData contains the callback data required for swap execution. This type is used to pass necessary information during the swap callback process, ensuring proper token transfers and pool data updates.
SwapParams contains parameters for executing a multi-hop swap operation.
Fee returns the pool fee tier.
Returns:
Recipient returns the address that receives swap output.
Returns:
TokenIn returns the input token contract path.
Returns:
TokenOut returns the output token contract path.
Returns:
1type SwapParamsI interface {
2 // TokenIn returns the input token path required by swap processing.
3 //
4 // Returns:
5 // - tokenIn: token spent by the swap
6 TokenIn() string
7 // TokenOut returns the output token path required by swap processing.
8 //
9 // Returns:
10 // - tokenOut: token received by the swap
11 TokenOut() string
12 // Fee returns the pool fee tier required by swap processing.
13 //
14 // Returns:
15 // - fee: pool fee tier
16 Fee() uint32
17}SwapParamsI defines the common interface for swap parameters.
SwapProcessor handles the execution of swap operations
AddSwapResults adds one route's amounts to accumulated totals using overflow-safe arithmetic.
Parameters:
Returns:
ProcessMultiSwap simulates a multi-hop route in the requested direction.
Parameters:
Returns:
1func (p *SwapProcessor) ProcessSingleSwap(route string, amountSpecified int64) (amountIn, amountOut int64, err error)ProcessSingleSwap simulates one pool hop without executing transfers.
Parameters:
Returns:
ValidateSwapResults checks simulated amounts against exactness and slippage constraints.
Parameters:
Returns:
SwapResult encapsulates the outcome of a swap operation.
1type SwapRouteParams struct {
2 inputToken string
3 outputToken string
4 routeArr string
5 quoteArr string
6 deadline int64
7 typ SwapType
8 exactAmount int64 // amountIn for ExactIn, amountOut for ExactOut
9 limitAmount int64 // amountOutMin for ExactIn, amountInMax for ExactOut
10 sqrtPriceLimitX96 *u256.Uint // if sqrtPriceLimitX96 is zero string, it will be set to MIN_PRICE or MAX_PRICE
11}SwapRouteParams contains all parameters needed for swap route execution
ExactAmount returns the requested exact input or output amount.
Returns:
ExpectedExactAmountByFee returns the amount needed by pool execution after router-fee adjustment.
Parameters:
Returns:
IsSetSqrtPriceLimitX96 reports whether a nonzero caller price limit is configured.
Returns:
SwapCount counts pool hops across all comma-separated routes.
Returns:
SwapValidator provides validation methods for swap operations