Redemption Curve¶
The Vault-K-NO prices every redemption using a quadratic curve applied to aggregate NAVs. The curve fairly distributes available liquidity between investors who redeem early in a day window and those who redeem later.
The Formula¶
where:
// Conceptual (real-valued):
fill = redeemedToday / dailyCap // in [0.0, 1.0]
// Integer arithmetic (mandatory — both values are USDC, 6 dec):
fill = redeemedToday * 1e18 / dailyCap // in [0, 1e18]
aggModeledNAV = Σ positionModeledValue(i) + idleReserve // all slots
aggMarketNAV = Σ positionMarketValue(i) + idleReserve // all slots
exitNAV is the curve-weighted aggregate vault NAV (USDC, 6 dec) — a total vault valuation, not a per-share price. To convert to USDC for a redemption: exitValue = shares * exitNAV / totalShares.
Fill must be 1e18 fixed-point in integer arithmetic
Writing fill = redeemedToday / dailyCap produces 0 for all partial fills (integer division of two USDC values). This silently collapses the curve to aggMarketNAV on every withdrawal. The * 1e18 scaling is mandatory.
Curve Behavior¶
| Fill Level | Exit Price | Interpretation |
|---|---|---|
fill = 0 (start of day, no redemptions yet) |
aggModeledNAV |
Best case — full modeled NAV, no curve discount |
fill = 0.5 (half the daily cap consumed) |
aggMarketNAV + 0.25 × (aggModeledNAV − aggMarketNAV) |
Discounted toward market NAV |
fill = 1.0 (daily cap fully consumed) |
aggMarketNAV |
Worst case — pure market NAV |
The quadratic shape means the discount is mild at low fills and accelerates near the cap. Early redeemers bear little discount; late redeemers receive pure market NAV pricing.
Example¶
Suppose:
- aggModeledNAV = $2,000,000
- aggMarketNAV = $1,900,000 (gap = 5%)
- dailyCap = $38,000 (2% of market NAV)
| Redemption order | Fill before | Fill after | Avg exit price per share |
|---|---|---|---|
| First $10K | 0.00 | 0.263 | ~$1.968 per $1 modeled |
| Next $10K | 0.263 | 0.526 | ~$1.939 per $1 modeled |
| Last $10K | 0.526 | 0.789 | ~$1.912 per $1 modeled |
Aggregate Agnosticism¶
The curve is agnostic to how many positions exist. It sees two aggregate numbers — aggModeledNAV and aggMarketNAV — and prices the exit between them. Adding or removing positions changes the aggregates but not the formula.
Average Curve NAV Calculation¶
When processing a withdrawal request, the vault computes the average curve-weighted vault NAV over the fill range [fillBefore, fillAfter] using the exact closed-form integral:
function _avgCurvePrice(
uint256 fillBefore, // pre-scaled: redeemedToday * 1e18 / dailyCap
uint256 fillAfter, // pre-scaled: (redeemedToday + requestValue) * 1e18 / dailyCap
uint256 mdl, // aggModeledNAV (USDC, 6 dec)
uint256 mkt // aggMarketNAV (USDC, 6 dec)
) internal pure returns (uint256 curveNAV)
curveNAV is a total vault valuation (USDC, 6 dec) between aggMarketNAV and aggModeledNAV — it is not a per-share price. The USDC owed to the investor is shares * curveNAV / totalShares. This ensures fair average pricing even when a single large withdrawal spans a significant fill range.
Daily Window Reset¶
At the start of each new 24-hour window (tracked by dayStart), redeemedToday resets to zero. This resets fill to 0, and the next redemption starts again at full modeled NAV pricing.
The DayRolled event is emitted with the new dayStart timestamp and the previous day's total redeemed amount.