harb/onchain/UNISWAP_V3_MATH.md
2025-08-18 00:16:09 +02:00

159 lines
No EOL
6.4 KiB
Markdown

# 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.
1. **Liquidity is invariant**: The liquidity value L doesn't change when price moves
2. **Token amounts are variable**: Depend on liquidity L, price range, and current price location
3. **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:
```solidity
liquidityPerTick = totalLiquidity / (tickUpper - tickLower)
```
The discovery position maintains its target liquidity density through width adjustment:
```solidity
// Ensure discovery has X times more liquidity per tick than anchor
discoveryLiquidity = anchorLiquidity * multiplier * discoveryWidth / anchorWidth
```
## Key Takeaways
1. **Liquidity ≠ Token Count**: Higher liquidity can mean fewer tokens at different price ranges
2. **Price Range Matters**: Token composition depends on where positions sit relative to current price
3. **Normalize for Width**: Always compare liquidity per tick when positions have different widths
4. **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:
```javascript
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:
```javascript
amount1 = liquidity * (sqrtRatioBX96 - sqrtRatioAX96) / Q96
```
### Critical Insight: ETH Position Creation
When creating a position above current price with ETH in a token0isWeth pool:
1. ETH is used as token1 (via getLiquidityForAmount1)
2. The position will hold KRAIKEN when in range
3. 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