6.4 KiB
Uniswap V3 Math - Critical Learnings
Critical Implementation Details
Price Representation in KRAIKEN
_priceAtTick(tick)returns price² in X96 format, NOT regular price or sqrtPrice- This is intentional: price² = (sqrtPrice)² / 2^96
- Used for ETH requirement calculations in floor positioning
- To get regular price from price²: take sqrt and shift left by 48 bits
- VWAP stores price² for volume-weighted averaging
ETH Scarcity vs Abundance
- Scarcity: Floor ETH < Outstanding KRAIKEN * VWAP price → Floor moves to extreme ticks (140k+)
- Abundance: Sufficient ETH → Floor placed near VWAP tick
- Extreme floor positions (tick 141,200+) are CORRECT behavior in scarcity scenarios
- Scarcity protects protocol solvency by making KRAIKEN very cheap (ETH expensive)
Token Ordering and Price Representation
Price Direction Reference Table
| Scenario | token0 | token1 | Price Represents | Lower Tick → Higher Tick |
|---|---|---|---|---|
| token0isETH = true | ETH | KRAIKEN | ETH per KRAIKEN | KRAIKEN cheap → expensive |
| token0isETH = false | KRAIKEN | ETH | KRAIKEN per ETH | ETH cheap → expensive |
Understanding "Above" and "Below"
Critical distinction: "Price" in Uniswap V3 always refers to token1's price in units of token0.
When token0isETH = true (ETH is token0, KRAIKEN is token1):
- Price = KRAIKEN price in ETH (how much ETH to buy 1 KRAIKEN)
- Higher tick = Higher KRAIKEN price in ETH
- Lower tick = Lower KRAIKEN price in ETH
- "Price moved up" = KRAIKEN became more expensive = ETH became cheaper
- "Price moved down" = KRAIKEN became cheaper = ETH became more expensive
When token0isETH = false (KRAIKEN is token0, ETH is token1):
- Price = ETH price in KRAIKEN (how much KRAIKEN to buy 1 ETH)
- Higher tick = Higher ETH price in KRAIKEN
- Lower tick = Lower ETH price in KRAIKEN
- "Price moved up" = ETH became more expensive = KRAIKEN became cheaper
- "Price moved down" = ETH became cheaper = KRAIKEN became more expensive
This determines token composition:
| Current Price vs Position | Position Contains | Why |
|---|---|---|
| Below range (tick < tickLower) | 100% token1 | Token0 is too expensive to hold |
| Within range (tickLower ≤ tick ≤ tickUpper) | Both tokens | Active liquidity range |
| Above range (tick > tickUpper) | 100% token0 | Token1 is too expensive to hold |
Liquidity vs Token Amounts
Key Insight: Liquidity (L) is a mathematical constant representing capital efficiency, NOT token count.
- Liquidity is invariant: The liquidity value L doesn't change when price moves
- Token amounts are variable: Depend on liquidity L, price range, and current price location
- Same L, different ranges: Results in different token amounts due to price differences
Why Positions at Different Ranges Have Different Token Ratios
For the same liquidity value L:
- Position at lower ticks: Higher token1 price → fewer token1, more token0 potential
- Position at higher ticks: Lower token1 price → more token1, less token0 potential
This explains why a position with fewer tokens can have more liquidity (and thus more price impact resistance).
Liquidity Per Tick - The Critical Metric
When comparing positions of different widths, always normalize to liquidity per tick:
liquidityPerTick = totalLiquidity / (tickUpper - tickLower)
The discovery position maintains its target liquidity density through width adjustment:
// Ensure discovery has X times more liquidity per tick than anchor
discoveryLiquidity = anchorLiquidity * multiplier * discoveryWidth / anchorWidth
Key Takeaways
- Liquidity ≠ Token Count: Higher liquidity can mean fewer tokens at different price ranges
- Price Range Matters: Token composition depends on where positions sit relative to current price
- Normalize for Width: Always compare liquidity per tick when positions have different widths
- Token0 Ordering is Critical: Determines which direction is "up" or "down" in price
Critical Formulas for Out-of-Range Positions
When Position is Below Current Price (currentTick < tickLower)
The position holds only token0:
amount0 = L * (sqrt(priceUpper) - sqrt(priceLower)) / (sqrt(priceUpper) * sqrt(priceLower))
In Solidity/JavaScript with Q96 notation:
amount0 = liquidity * (sqrtRatioBX96 - sqrtRatioAX96) / sqrtRatioAX96 * Q96 / sqrtRatioBX96
When Position is Above Current Price (currentTick > tickUpper)
The position holds only token1:
amount1 = L * (sqrt(priceUpper) - sqrt(priceLower))
In Solidity/JavaScript with Q96 notation:
amount1 = liquidity * (sqrtRatioBX96 - sqrtRatioAX96) / Q96
Critical Insight: ETH Position Creation
When creating a position above current price with ETH in a token0isWeth pool:
- ETH is used as token1 (via getLiquidityForAmount1)
- The position will hold KRAIKEN when in range
- But if price drops below the range, it converts to holding ETH as token0
Example: Floor position created with 38 ETH at ticks [127400, 127600] when current is 123890:
- Creation: Uses getLiquidityForAmount1 with 38 ETH
- Result: Liquidity = 6.48e18
- Current holdings: 38 ETH (as token0, since price is below range)
Common Confusion Points
1. Price Direction vs ETH Value
When token0isWeth = true:
- Higher tick = Higher price = More KRAIKEN per ETH = ETH is MORE valuable
- Lower tick = Lower price = Less KRAIKEN per ETH = ETH is LESS valuable
This is counterintuitive because "price goes up" means the denominated asset (ETH) becomes more valuable.
2. Position Token Holdings
A position's token composition depends ONLY on:
- Current price location relative to the position range
- NOT on how the position was created
- NOT on which token was used to mint
3. The Floor Position "Below Current Price" Confusion
In KRAIKEN's three-position strategy:
- Floor position is placed where ETH is MORE valuable (higher ticks when token0isWeth)
- This is "below" current price from an ETH value perspective
- But "above" current tick numerically
- Selling KRAIKEN for ETH moves price TOWARD the floor position
4. Liquidity Calculation Direction
When minting a position out of range:
- Use getLiquidityForAmount0 if providing token0
- Use getLiquidityForAmount1 if providing token1
- The same liquidity value will require different token amounts depending on which token you provide