Agent-SOFR for a given asset and horizon decomposes into three additive terms. This decomposition is what makes the rate auditable — every basis point is traceable to one of the three components, and the API response returns the breakdown alongside the headline rate.
The three terms answer three distinct questions:
We aggregate seven heterogeneous sources, weighted by manipulation resistance. The weighted median (not mean) is taken so a single venue going stale or briefly manipulated cannot dominate.
| Source | Bucket | Weight | What it captures |
|---|---|---|---|
deribit_pcp_30d | Market-derived | 0.32 | Implied USD rate from ETH options put-call parity (30d tenor). Deepest options market; hardest to manipulate. |
hl_funding_smoothed | Market-derived | 0.22 | Hyperliquid ETH-PERP funding rate (smoothed 1h). Largest perp venue, expresses real demand. |
aevo_pcp | Market-derived | 0.11 | Aevo ETH options put-call parity — cross-check on options markets. |
deribit_basis_3m | Market-derived | 0.10 | Deribit ETH futures 3-month basis — cost-of-carry sanity check. |
aave_borrow_usdc | DeFi reference | 0.10 | Aave V3 Base USDC borrow rate. Capped influence — single governance vote can move it ≤60 bps. |
compound_borrow_usdc | DeFi reference | 0.05 | Compound Base USDC borrow rate. Independent governance sanity check. |
sofr_30d | Macro anchor | 0.10 | NY Fed SOFR 30-day average — TradFi long-horizon floor; prevents drift during illiquid crypto markets. |
Bucket totals: 75% market-derived, 15% DeFi reference, 10% macro. The 75/15/10 split is the manipulation-resistance constraint: no governance-set source can move the rate alone, and arbitrage-driven sources dominate.
Why WETH borrow rate is excluded: it's the ETH lending market (interest paid in ETH), structurally separate from USDC short rate. Including it would pollute the signal — we measure the rate at which agents borrow USD against ETH collateral, not the rate at which someone borrows ETH itself. Removed in v1.0.1.
The base anchor only tells you what borrowers pay on average. To price a specific loan you need the variance premium: the expected loss from collateral defaults given current realized + jump volatility.
We use the Barndorff-Nielsen & Shephard (2004, 2006) jump decomposition — the canonical method in econometrics for separating diffusive (continuous) variance from price jumps. Same math as production code in ARMSHookV3 (Uniswap v4 hook live on Base mainnet).
Identification of λ. Closed-form on the full 4.2-year dataset (444,219 bars), solved so total fee revenue covers impermanent loss with a 5% margin:
Numerator = required total fee revenue (with 5% buffer) minus what the continuous-only fee schedule already covers; denominator = variance contributed by jumps. Solving this in eth_jump_multihorizon.py:run_horizon yields λ = 1.0968 for the 5-minute horizon, rounded to 1.097 in production (LAMBDA = 1.097 in eth_segmented_fee.py:41).
Sensitivity-checked via a sweep over λ ∈ {0.50, 0.80, 1.00, 1.097, 1.30, 1.60, 2.00} in eth_hook_bar_pnl.py — the production value sits within the robust plateau where PnL is insensitive to ±20% perturbations of λ.
Over an arbitrary loan horizon T (expressed in 5-minute bars):
The intuition: P_default scales with σ/LTV-to-1 gap. A 92% LTV loan in a calm 0.4% σ_T regime has P_default ≈ 1.5e-5, contributing ~0 bps. The same loan in a 5% σ_T regime has P_default ≈ 0.005, contributing ~30 bps.
| Horizon | Regime | LTV | Approx. premium (bps) |
|---|---|---|---|
| 1h | RESTING | 80% | ≈ 4 |
| 1h | HIGH | 80% | ≈ 60 |
| 24h | EXTREME | 80% | ≈ 300 |
The variance_premium handles continuous risk. But realized jump-distribution evidence shows that extreme regimes have heavier tails than continuous models predict. The regime adjustment is an empirical correction: a step function that adds bps based on which of six volatility buckets we're currently in.
Boundaries are calibrated from 444,219 5-min bars (~4.2 years) of Binance ETH/USDC 1-second tickers aggregated upward (binance_history_eth.db). Time-share columns are observed frequencies — 78% of the time the market is in RESTING/LOW/NORMAL, only 1.1% of bars are in EXTREME.
| Mode | σ_5min boundary | Time-share | Risk premium | Max LTV cap |
|---|---|---|---|---|
| RESTING | < 14.2 bp | 46.4% | +0 bps | 92% |
| LOW | 14.2 – 17.8 bp | 15.6% | +5 bps | 90% |
| NORMAL | 17.8 – 23.3 bp | 16.0% | +15 bps | 85% |
| ELEVATED | 23.3 – 34.4 bp | 14.3% | +30 bps | 80% |
| HIGH | 34.4 – 62.9 bp | 6.7% | +60 bps | 70% |
| EXTREME | > 62.9 bp | 1.1% | +200 bps | 55% |
Hysteresis: Up-transitions are instant (shocks priced immediately, no lag). Down-transitions require σ to fall 10% below the boundary (eps_down = 0.10). This cuts mode-changes per day from 33.7 (naive) to 24.1 (-30%) while preserving 100% of HIGH/EXTREME shock-coverage.
Premium curve rationale: the exponential shape (0 / 5 / 15 / 30 / 60 / 200 bps, not linear) reflects empirical jump distribution — HIGH and EXTREME modes have much larger expected losses than linear extrapolation suggests. Mirrors RegimeCaps.sol retail fee escalation in our Uniswap hook, scaled down to 24h loan horizons.
Every design choice in Agent-SOFR is downstream of one constraint: no single actor — venue, validator, governance token, or oracle operator — should be able to move the published rate by more than a few basis points.
| Attack vector | Mitigation |
|---|---|
| Single-venue manipulation (wash trades on Aevo) | Weight cap at 11% per source; weighted median dominates |
| Aave governance vote to move USDC borrow rate | 10% weight + medianed across 7 sources = max effective move <60 bps |
| Stale source returns last cached value indefinitely | Each source has TTL guard; stale source dropped, weight redistributed |
| Oracle operator (us) signs malicious quote | Quote contains EIP-712 signature verifiable on-chain; oracle key rotatable; published `methodology_hash` lets any consumer verify "this rate matches this spec" |
| Flash loan against Aave to spike borrow rate momentarily | Sources sampled every 60s; flash-duration spikes don't survive aggregation |
| Long-horizon regime persistence (e.g. EXTREME stuck on) | Down-hysteresis means EXTREME → LOWER only after sustained calm; up-transition instant prevents under-pricing during shock |
To prove the spec is fully implementable from this document alone, here's a complete worked example. Anyone with the source weights + a Python REPL can reproduce this rate.
Setup: 2026-05-22, 1h horizon, hypothetical source readings:
| Source | Reading (%) | Weight |
|---|---|---|
| deribit_pcp_30d | 4.05 | 0.32 |
| hl_funding_smoothed | 10.95 | 0.22 |
| aevo_pcp | 3.00 | 0.11 |
| deribit_basis_3m | 4.74 | 0.10 |
| aave_borrow_usdc | 4.17 | 0.10 |
| compound_borrow_usdc | null (TODO) | 0.05 → redistributed |
| sofr_30d | 4.32 | 0.10 |
Step 1 — Drop null sources, renormalize weights: Compound returns null → its 0.05 weight is redistributed pro-rata to the other six. Effective weights: 0.337 / 0.232 / 0.116 / 0.105 / 0.105 / 0.105.
Step 2 — Compute weighted median. Sort sources by reading: 3.00 → 4.05 → 4.17 → 4.32 → 4.74 → 10.95. Walk cumulative weight; stop at the first source where cumulative ≥ 0.5. With effective weights, that's aave_borrow_usdc at 4.17%.
Step 3 — Compute variance over 1h horizon (12 bars):
Step 4 — Compute P_default at LTV 80% (assumed):
At 1h horizon in this regime, variance_premium ≈ 0.02% ≈ 2 bps. (At HIGH regime σ_T would be ~5×, P_default jumps materially.)
Step 5 — Regime adjustment. Current σ_5min = 19.8 bp → NORMAL regime → +15 bps.
Step 6 — Sum:
This matches the production endpoint's actual output to within 1 bp — any drift is from live-source readings vs. the hypothetical inputs above.
The methodology described here is not just a doc — it's the spec implemented in the production code at oracle/agent_sofr.py and oracle/rate_aggregator.py. Every paid response includes the full decomposition + a link back here:
GET /v1/rate/sofr/usd?horizon=1h { "ok": true, "rate": 4.34, "decomposition": { "base_anchor": 4.17, "variance_premium": 0.02, "regime_adjustment": 0.15 }, "sources": { ... }, "weights_applied": { ... }, "regime": { "mode": "NORMAL", ... }, "variance": { "cv_per_bar": 1.85e-6, ... }, "methodology": { "version": "agent-sofr-v1", "url": "https://regimeshift.xyz/methodology/agent-sofr-v1" } }
The methodology.version field is the contract between consumer and oracle. If we change the formula, we bump the version (agent-sofr-v2, etc.) — old methodology hash continues to resolve to this exact page, so consumers can always verify which spec produced a given rate.