const MaxQuotePercentage, MinQuotePercentage, PERCENTAGE_DENOMINATOR
QuoteConstraints defines the valid range for swap quote percentages
package v1 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 exact input amount for minimum output.
ExactOutSwapRouteSwaps for exact output amount with maximum input.
DrySwapRouteSimulates swap without execution.
Routes in the router follow swap direction ordering: tokenIn:tokenOut:fee
Example for swapping BAR to BAZ:
gno.land/r/demo/bar:gno.land/r/demo/baz:3000
Pools are identified using alphabetical ordering: token0:token1:fee
Example pool identifier (same pool as above):
gno.land/r/demo/bar:gno.land/r/demo/baz:3000 # if bar < baz alphabetically
IMPORTANT: When using native GNOT tokens, there's a critical distinction between token identifiers and route paths:
"ugnot" for inputToken and outputToken parameters"gno.land/r/gnoland/wugnot" in route stringsThis dual-identifier system exists because:
Correct Usage Example:
1// CORRECT: inputToken="ugnot", route uses wugnot path
2ExactInSwapRoute(
3 "ugnot", // input token identifier
4 "gno.land/r/demo/bar", // output token
5 "1000000",
6 "gno.land/r/gnoland/wugnot:gno.land/r/demo/bar:3000", // route uses wugnot
7 "100", "950000", deadline, ""
8)
9
10// INCORRECT: using "ugnot" in route will fail
11ExactInSwapRoute(
12 "ugnot", "gno.land/r/demo/bar", "1000000",
13 "ugnot:gno.land/r/demo/bar:3000", // Wrong: pools don't exist for "ugnot"
14 "100", "950000", deadline, ""
15)
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 BAR to BAZ
Route: gno.land/r/demo/bar:gno.land/r/demo/baz:3000
# Router interprets: tokenIn=bar, tokenOut=baz, fee=3000
Multi-hop example (BAR → BAZ → QUX):
# Each segment follows swap direction, connected by *POOL*
gno.land/r/demo/bar:gno.land/r/demo/baz:3000*POOL*gno.land/r/demo/baz:gno.land/r/demo/qux:500
Split large trades across routes to minimize impact:
quoteArr: Percentage per route (must sum to 100)The Router automatically handles native GNOT token operations through wrapping/unwrapping mechanisms:
"ugnot" to specify native GNOT as input token"ugnot" to specify native GNOT as output token"gno.land/r/gnoland/wugnot" in route specificationsWhen using native GNOT tokens, you must send the appropriate amount of native ugnot with your function call:
amountIn amount of ugnotamountIn amount of ugnotamountInMax amount of ugnotamountInMax amount of ugnotamountOutMin = expected * (1 - slippage%) 1// Simple exact input swap
2amountIn, amountOut := ExactInSwapRoute(
3 "gno.land/r/demo/bar", // input token
4 "gno.land/r/demo/baz", // output token
5 "1000000", // amount (6 decimals)
6 "gno.land/r/demo/bar:gno.land/r/demo/baz:3000", // route
7 "100", // 100% through route
8 "950000", // min output
9 time.Now().Unix() + 300, // deadline
10 "g1referrer...", // referral
11)
12
13// Multi-hop swap
14ExactInSwapRoute(
15 "gno.land/r/demo/bar",
16 "gno.land/r/demo/baz",
17 "1000000",
18 "gno.land/r/demo/bar:gno.land/r/gnoland/wugnot:3000*POOL*gno.land/r/gnoland/wugnot:gno.land/r/demo/baz:3000",
19 "100",
20 "900000",
21 deadline,
22 "",
23)
24
25// Split route for large trades
26ExactInSwapRoute(
27 "gno.land/r/demo/usdc",
28 "ugnot",
29 "10000000000",
30 "gno.land/r/demo/usdc:gno.land/r/gnoland/wugnot:500,gno.land/r/demo/usdc:gno.land/r/gnoland/wugnot:3000",
31 "60,40", // 60% through 0.05%, 40% through 0.3%
32 "9500000000",
33 deadline,
34 "",
35)
Single swap functions support partial execution through price limits:
1// Partial swap with price limit - may not consume full input amount
2amountIn, amountOut := ExactInSingleSwapRoute(
3 "gno.land/r/demo/bar", // input token
4 "gno.land/r/demo/baz", // output token
5 "1000000", // max amount to swap
6 "gno.land/r/demo/bar:gno.land/r/demo/baz:3000", // single route
7 "950000", // min output
8 "1000000000000000000", // sqrtPriceLimitX96 (price limit)
9 deadline,
10 "",
11)
12// If price limit is reached, only partial amount is swapped
13// Remaining input tokens stay with user (no refund needed for GRC20 tokens)
When using native GNOT, automatic refunds handle unused amounts:
1// STEP 1: Approve WUGNOT for potential refunds
2wugnot.Approve(cross, routerAddress, 2000000) // Approve more than needed
3
4// STEP 2: ExactIn with native GNOT (send exactly amountIn)
5amountIn, amountOut := ExactInSwapRoute(
6 "ugnot", // native input
7 "gno.land/r/demo/bar", // output token
8 "1000000", // send this amount of ugnot with call
9 "gno.land/r/gnoland/wugnot:gno.land/r/demo/bar:3000",
10 "100", "950000", deadline, ""
11)
12// Any unused GNOT automatically refunded
13
14// STEP 3: ExactOut with native GNOT (send amountInMax)
15amountIn, amountOut := ExactOutSwapRoute(
16 "ugnot", // native input
17 "gno.land/r/demo/bar", // output token
18 "1000000", // exact output desired
19 "gno.land/r/gnoland/wugnot:gno.land/r/demo/bar:3000",
20 "100",
21 "1200000", // send this max amount of ugnot with call
22 deadline, ""
23)
24// Excess GNOT (1200000 - actual_input_used) automatically refunded
25
26// STEP 4: Single swap with partial execution + refund
27amountIn, amountOut := ExactInSingleSwapRoute(
28 "ugnot", // native input
29 "gno.land/r/demo/bar", // output token
30 "1000000", // send this amount of ugnot with call
31 "gno.land/r/gnoland/wugnot:gno.land/r/demo/bar:3000",
32 "950000",
33 "1000000000000000000", // price limit may cause partial swap
34 deadline, ""
35)
36// Unswapped GNOT due to price limit automatically refunded
WUGNOT Approval Forgotten: Most transaction failures with native GNOT occur because developers forget to approve WUGNOT spending before calling router functions.
Route vs Token Identifier Confusion: Using "ugnot" in route strings instead of "gno.land/r/gnoland/wugnot" will cause transactions to fail since no pools exist for the "ugnot" identifier.
Incorrect Native Token Send Amount:
amountIn of native gnotamountInMax of native gnotMissing Refund Handling: When integrating, remember that native GNOT refunds are automatic but require prior WUGNOT approval.
"ugnot" for parameters, "gno.land/r/gnoland/wugnot" for routesThe ExactInSingleSwapRoute and ExactOutSingleSwapRoute functions support partial execution when sqrtPriceLimitX96 is set. This means:
package v1 handles token swaps through GnoSwap liquidity pools.
The router provides user-facing swap functions with slippage protection, multi-hop routing, and automatic GNOT wrapping/unwrapping. It supports both exact input and exact output swap modes.
All swap functions include deadline checks and minimum output validation to protect users from unfavorable price movements.
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 _ SwapDirection = iota
3 // Forward indicates a swap processing direction from the first pool to the last pool.
4 // Used primarily for exactIn swaps where the input amount is known.
5 Forward
6
7 // Backward indicates a swap processing direction from the last pool to the first pool.
8 // Used primarily for exactOut swaps where the output amount is known and input amounts
9 // Need to be calculated in reverse order.
10 Backward
11) 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)BuildSingleHopPath creates a single-hop route path string. Format: "tokenA:tokenB:fee"
Parameters: - tokenA: input token address - tokenB: output token address - fee: pool fee (e.g., 500, 3000, 10000)
Returns: - string: formatted single-hop route path
Example:
NewExactInParams creates a new ExactInParams instance.
NewExactOutParams creates a new ExactOutParams instance.
NewExactOutSwapOperation creates a new exact-out swap operation.
NewRouteParser creates a new route parser instance.
DryMultiSwapExecutor implements MultiSwapExecutor for dry run simulations.
DrySwapExecutor implements SwapExecutor for dry swaps.
ExactInParams contains parameters for exact input swaps.
ExactOutParams contains parameters for exact output swaps.
ExactOutSwapOperation handles swaps where the output amount is specified.
MultiSwapExecutor defines the interface for multi-hop swap operation execution.
1type MultiSwapProcessor struct {
2 executor MultiSwapExecutor
3 direction SwapDirection
4 router *routerV1
5 isSimulate bool
6 // payer is the address used to identify the user. For real swaps it is the
7 // PreviousRealm address; for dry-run paths it is resolved at the entry point.
8 payer address
9}MultiSwapProcessor handles the execution flow for multi-hop swaps.
RealMultiSwapExecutor implements MultiSwapExecutor for actual swap operations.
RealSwapExecutor implements SwapExecutor for actual swaps.
RouteParser handles parsing and validation of routes and quotes
ParseRoutes parses route and quote strings into slices and validates them.
ValidateQuoteSum ensures all quotes add up to 100%.
ValidateRoutesAndQuotes ensures routes and quotes meet required criteria.
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.
SqrtPriceLimitX96 returns the sqrtPriceLimitX96 for the swap. If sqrtPriceLimitX96 is empty string, it will return zero.
TokenIn returns the input token address.
TokenOut returns the output token address.
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.
SwapDirection represents the direction of swap execution in multi-hop swaps. It determines whether swaps are processed in forward order (first to last pool) or backward order (last to first pool).
SwapExecutor defines the interface for executing swaps.
SwapParams contains parameters for executing a multi-hop swap operation.
Fee returns the pool fee tier.
Recipient returns the recipient address.
TokenIn returns the input token address.
TokenOut returns the output token address.
SwapParamsI defines the common interface for swap parameters.
SwapProcessor handles the execution of swap operations
AddSwapResults safely adds swap result amounts, checking for overflow.
Parameters:
Returns:
ProcessMultiSwap handles a multi-hop swap simulation.
Parameters:
Returns:
1func (p *SwapProcessor) ProcessSingleSwap(route string, amountSpecified int64) (amountIn, amountOut int64, err error)ProcessSingleSwap handles a single-hop swap simulation.
Parameters:
Returns:
ValidateSwapResults checks if the swap results meet the required 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
when exact out, calculate amount to fetch from pool including router fee
SwapValidator provides validation methods for swap operations