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