Search Apps Documentation Source Content File Folder Download Copy Actions Download

README.md

3.77 Kb · 179 lines

Position

NFT-based liquidity position management for concentrated liquidity.

Overview

Each liquidity position is a unique GRC721 NFT containing pool identifier, price range, liquidity amount, accumulated fees, and token balances.

Configuration

  • Withdrawal Fee: 1% on collected fees
  • Max Position Size: No limit
  • Transfer Restrictions: Non-transferable NFTs

Core Functions

Mint

Creates new position NFT with initial liquidity.

  • Validates tick range alignment
  • Calculates optimal token ratio
  • Returns actual amounts used

IncreaseLiquidity

Adds liquidity to existing position.

  • Maintains same price range
  • Pro-rata token amounts

DecreaseLiquidity

Removes liquidity while keeping NFT.

  • Two-step: decrease then collect
  • Calculates owed tokens

CollectFee

Claims accumulated swap fees.

  • No liquidity removal required
  • 1% protocol fees applied

Reposition

Updates an existing position's price range.

  • Requires position to be cleared first (zero liquidity/tokens owed)
  • Reuses the same position ID and NFT
  • Adds new liquidity to the updated range

Technical Details

Tick Alignment

Ticks must align with pool's tick spacing:

0.01% fee: every 1 tick
0.05% fee: every 10 ticks
0.3% fee: every 60 ticks
1% fee: every 200 ticks

Optimal Range Width

Stable Pairs (USDC/USDT):

  • Narrow: ±0.05% (max efficiency)
  • Medium: ±0.1% (balanced)
  • Wide: ±0.5% (safety)

Correlated Pairs (WETH/stETH):

  • Narrow: ±0.5%
  • Medium: ±1%
  • Wide: ±2%

Volatile Pairs (WETH/USDC):

  • Narrow: ±5%
  • Medium: ±10%
  • Wide: ±25%

Capital Efficiency

Concentration factor vs infinite range:

Range ±0.1%  → 2000x efficient
Range ±1%    → 200x efficient
Range ±10%   → 20x efficient
Range ±50%   → 4x efficient

Token Calculations

Below range (token1 only):

amount1 = L * (sqrtUpper - sqrtLower)
amount0 = 0

Above range (token0 only):

amount0 = L * (sqrtUpper - sqrtLower) / (sqrtUpper * sqrtLower)
amount1 = 0

In range (both tokens):

amount0 = L * (sqrtUpper - sqrtCurrent) / (sqrtUpper * sqrtCurrent)
amount1 = L * (sqrtCurrent - sqrtLower)

Usage

 1// Mint new position through the proxy realm
 2tokenId, liquidity, amount0, amount1 := position.Mint(
 3    cross,
 4    "gno.land/r/onbloc/weth",  // token0
 5    "gno.land/r/gnoswap/test_token/test_usdc",  // token1
 6    3000,                      // fee
 7    -887220,                   // tickLower
 8    887220,                    // tickUpper
 9    "1000000",                 // amount0Desired
10    "2000000000",              // amount1Desired
11    "950000",                  // amount0Min
12    "1900000000",              // amount1Min
13    deadline,
14    recipient,                 // mintTo
15    "",                        // referrer
16)
17
18// Add liquidity
19positionId, liquidity, amount0, amount1, poolPath := position.IncreaseLiquidity(
20    cross,
21    tokenId,
22    "500000",
23    "1000000000",
24    "475000",
25    "950000000",
26    deadline,
27)
28
29// Collect fees
30positionId, fee0, fee1, poolPath, token0Path, token1Path := position.CollectFee(
31    cross,
32    tokenId,
33)
34
35// Reposition to new range (requires cleared position)
36positionId, liquidity, tickLower, tickUpper, amount0, amount1 := position.Reposition(
37    cross,
38    tokenId,
39    -443610,                   // new tickLower
40    443610,                    // new tickUpper
41    "1000000",                 // amount0Desired
42    "2000000000",              // amount1Desired
43    "950000",                  // amount0Min
44    "1900000000",              // amount1Min
45    deadline,
46)

Security

  • Tick range validation prevents invalid positions
  • Slippage protection on all operations
  • Deadline prevents stale transactions
  • Position NFTs are non-transferable
  • Only owner can manage their positions