TL;DR — the decision rule

Hold through. Every observed spike in the 2-year window mean-reverted in 1–3 days, and the wstETH/WETH on-chain discount widens during these stress windows (precisely because panicking loopers are dumping wstETH). At the worst observed spike (Aave WETH borrow 17.54% on 2025-07-16), holding one day cost ~4 bps per dollar of debt while the DEX exit cost was 8–28 bps. The decision rule:

Unwind only if discount_bps + fee_bps < (peak_rate − stETH_yield) × expected_spike_days / 365 × 10_000.

With historically observed spike durations of ≤3 days and DEX discounts that widen during spikes (not shrink), the right-hand side is almost never larger than the left. Hold.

The single scenario where unwinding pays: discount stays narrow (< 5 bps) AND the rate sits >5pp above stETH yield for >5 days. We have not observed that combination in this dataset.

Question

Looping wstETH against WETH is structurally exposed to the WETH borrow rate. When utilization on Aave/Spark/Morpho spikes (typical cause: a wave of new loop entries pushing supply utilization toward 100%), the IRM kinks borrow rates upward — sometimes dramatically (peak observed: 17.54% on Aave).

A position holder has two options:

We wanted a defensible decision rule for the operator on call, parameterised by observable inputs (peak rate, current DEX discount, stETH yield).

Methodology

Data sources & how to reproduce

Two pulls plus a transform:

  1. scripts/pull-borrow-history.py — Reads Pool.getReserveData(WETH).currentVariableBorrowRate from Aave V3 (0x87870Bca…) and Spark (0xC13e21B6…) on Ethereum mainnet at 53 bi-weekly blocks spanning 2024-05-29 → 2026-05-29. Output: data/borrow-history.json.

  2. scripts/pull-morpho-history.py — For the same 53 blocks, reads the Morpho Blue main wstETH/WETH market (id 0xb8fc70e8…, LLTV 96.5%, oracle 0xbD60A6770b…) via Morpho.market(id) and computes the borrow APR via AdaptiveCurveIRM.borrowRateView(params, market). Output: data/morpho-history.json.

  3. Densification around the worst spike (2025-07-16). Reads the same Aave call + the Curve stETH/ETH pool’s get_dy(1, 0, 1e18) (1 stETH → ETH quote) at daily blocks 2025-07-16 → 2025-08-01, plus wstETH’s stEthPerToken() to compute the wstETH/WETH discount = (fair − market) / fair. Results are in the “Findings” tables below.

Lido stETH APY is pulled from DeFiLlama’s free chart endpoint (yields.llama.fi/chart/747c1d2a-…) — DeFiLlama paywalls historical borrow rates but exposes supply yields. Output: data/lido.json.

To rerun: python3 scripts/pull-borrow-history.py && python3 scripts/pull-morpho-history.py from this folder, with $RPC_ETH set to a drpc archive node (or equivalent). Each pull takes ~3 minutes.

Assumptions baked in: (a) Aave/Spark/Morpho rates are ray-encoded annualised APRs (verified by spot-check against on-chain at deployment day); (b) Curve get_dy is used as the marginal DEX price — single 1-stETH probe is enough for the basis but not for sizing the actual unwind cost (which depends on position size); (c) the wstETH/WETH “fair” rate is the on-chain stEthPerToken() assuming stETH = ETH at par, which is the same assumption Spark and Morpho oracles make.

Findings

Lido stETH yield vs Aave/Spark/Morpho WETH borrow rates, annualised, Jul 2024 – Jan 2026

Five worst spike weeks in the 2-year window

DatePeak venuePeak ratewstETH/WETH DEX discount at the same blockBreak-even hold-through duration
2025-07-16Aave17.54%8.6 bps~3 days
2025-07-22Aave7.62%28.1 bps~21 days
2025-03-17Spark5.97%4.7 bps~5 days
2026-05-01Aave4.59%14.4 bps~24 days
2025-04-14Aave3.94%5.5 bps~14 days

“Break-even hold-through duration” = the unwind cost (discount + ~3 bps fee) divided by the daily hold cost ((peak_rate − stETH_yield) / 365 expressed in bps). If the actual spike duration is shorter than this, holding through is the right call.

The worst spike densified — Aave WETH borrow + wstETH DEX discount, daily

DateAave WETH borrowwstETH/WETH DEX discount
2025-07-1617.54%8.6 bps
2025-07-184.70%28.3 bps
2025-07-202.66%17.1 bps
2025-07-227.62%28.1 bps
2025-07-242.98%16.9 bps
2025-07-262.96%18.6 bps
2025-07-282.90%11.0 bps
2025-07-302.97%12.6 bps
2025-08-012.90%11.6 bps

The peak was a single-day event. By July 18 (2 days later) the rate had dropped from 17.54% to 4.70%; by July 20 (4 days later) it was 2.66%, fully normal. The wstETH discount peaked on day 2, after the rate had already partially mean-reverted — confirming the pattern that loopers panicking is what drives the discount, and that the panic itself is poorly timed.

Two-year averages (n = 53 bi-weekly samples)

Lido stETH yieldAave WETH borrowSpark WETH borrowMorpho WETH borrow
Mean2.82%2.62%2.27%2.29%
Max7.62%5.97%6.52%
Min1.92%1.68%0.72%
Avg net carry vs stETH+0.20pp+0.55pp+0.54pp
Weeks negative carry (of 53)524

All three venues’ borrow rates spike together (2025-07-22 saw Aave 7.62%, Morpho 6.52%, Spark held lower at 3.24%; 2025-03-17 saw Spark 5.97% with the others near 2.7%). Cross-venue spike correlation is high but not perfect — a spike on one venue does not guarantee a spike on the others, which is itself useful information (relocating across venues is a partial hedge).

Decision framework

Per dollar of WETH debt:

The rule:

unwind if:  discount_bps + 3 < (peak_rate − stETH_yield) × expected_spike_days / 365 × 10_000
hold otherwise

For the operator on call: if the DEX discount is wider than the gross negative-carry over 3 days, hold. It always has been.

Failure modes (re-run the study when any of these change):

Caveats