78 lines
3.1 KiB
Markdown
78 lines
3.1 KiB
Markdown
# 02: StableSwap Invariant
|
|
|
|
## Source
|
|
- **Protocol**: Curve Finance / Balancer V2/V3
|
|
- **Files**: `StableMath.sol` (Balancer), Curve StableSwap whitepaper
|
|
- **Repo**: `balancer/balancer-v2-monorepo`, `balancer/balancer-v3-monorepo`
|
|
|
|
## Rationale for MYCO
|
|
|
|
StableSwap is essential for **reserve tranches that hold pegged assets** (e.g., multiple stablecoins, or wrapped versions of the same underlying). Within a single tranche, assets should trade near 1:1 with minimal slippage — exactly what StableSwap provides.
|
|
|
|
For MYCO:
|
|
1. If multiple stablecoins (USDC, USDT, DAI) serve as reserve, they should be priced via StableSwap within their tranche rather than weighted product
|
|
2. The amplification parameter A lets us tune how "stable" the peg is — higher A = tighter peg, lower A = more AMM-like
|
|
3. The Newton-Raphson solver pattern established here is reused by the E-CLP and P-AMM primitives
|
|
4. Production-proven across $B+ in Curve and Balancer stable pools
|
|
|
|
## Invariant
|
|
|
|
$$A \cdot n^n \cdot S + D = A \cdot D \cdot n^n + \frac{D^{n+1}}{n^n \cdot P}$$
|
|
|
|
where:
|
|
- $A$ = amplification coefficient ($1 \leq A \leq 50{,}000$)
|
|
- $n$ = number of tokens
|
|
- $S = \sum b_i$ (sum of balances)
|
|
- $P = \prod b_i$ (product of balances)
|
|
- $D$ = the invariant (total virtual liquidity, analogous to constant-sum amount)
|
|
|
|
**Limiting behavior:**
|
|
- $A \to \infty$: $D \to S$ (constant sum — perfect 1:1 peg)
|
|
- $A \to 0$: $D^{n+1} \to n^n \cdot P \cdot D$ → reduces to constant product
|
|
|
|
## Swap Math
|
|
|
|
To compute `amountOut` for a given `amountIn`:
|
|
|
|
1. Compute $D$ from current balances
|
|
2. Set `new_balance[token_in] = old_balance[token_in] + amountIn`
|
|
3. Solve for `new_balance[token_out]` using the quadratic:
|
|
|
|
$$y^2 + \left(S' + \frac{D}{A \cdot n^n} - D\right) y = \frac{D^{n+1}}{A \cdot n^{2n} \cdot P'}$$
|
|
|
|
where $S'$, $P'$ exclude the target token. Solved via Newton-Raphson:
|
|
|
|
$$y_{k+1} = \frac{y_k^2 + c}{2y_k + b - D}$$
|
|
|
|
4. `amountOut = old_balance[token_out] - new_balance[token_out]`
|
|
|
|
## Parameters
|
|
|
|
| Parameter | Range | Effect |
|
|
|-----------|-------|--------|
|
|
| $A$ | [1, 50000] | Amplification. Higher = tighter peg, lower slippage near 1:1 |
|
|
| $n$ | [2, 5] | Number of tokens in the stable pool |
|
|
|
|
**Balancer V3 additions:**
|
|
- `MAX_IMBALANCE_RATIO = 10,000` — max ratio between highest and lowest balance
|
|
- `StableSurgeHook` — imbalance-contingent fees (see primitive #10)
|
|
|
|
## Properties
|
|
|
|
- **Convexity**: Level sets are convex
|
|
- **Homogeneous degree 1**: $D(k \cdot \vec{b}) = k \cdot D(\vec{b})$
|
|
- **Low slippage near peg**: For balanced pools with high A, swaps near 1:1 have ~zero price impact
|
|
- **High slippage far from peg**: When balances diverge significantly, the curve steepens rapidly (protective)
|
|
|
|
## MYCO Application
|
|
|
|
Within the reserve tranching layer, each tranche that holds pegged assets (e.g., a stablecoin basket) uses StableSwap internally. This means:
|
|
|
|
- Depositing any accepted stablecoin into the stable tranche incurs minimal friction
|
|
- The tranche's internal invariant (D) grows smoothly with deposits
|
|
- The tranche's total value feeds into the outer bonding surface as one aggregate reserve dimension
|
|
|
|
## Implementation
|
|
|
|
See `src/primitives/stableswap.py`
|