Interest rates
A two-slope curve, and why it bends where it does.
The borrow rate is a function of utilisation — how much of the Earn vault's USDG is currently borrowed. It is measured once, for the whole vault, and every market that lends from the vault prices at that one figure:
utilisation = B / A
B = Σ totalBorrowAssets over the vault's markets
A = vault's idle USDG + Σ totalSupplyAssetsB is everything borrowed from the vault's markets. A is everything the vault has to lend: its
idle USDG plus what it already has in markets. Reserves are not counted; they belong to the
protocol. The vault stores the result and exposes it as utilization(); the interest rate model's
utilizationOf(router) returns the figure a market's rate uses.
Each market keeps its own curve, so one utilisation does not mean one rate: at the same utilisation, each market charges its own. A borrow in one market raises the rate in all of them, because it takes from the same pool of lenders' USDG.
The vault does not push deposits into markets (its supply queue is empty): new USDG stays idle, and
a market pulls from it when a borrow needs more cash than the market holds. Moving USDG from idle
into a market does not change A, so it does not change the rate. Every market prices at the same
vault-wide utilisation, including a market with no debt of its own. The arithmetic, with figures read
from the chain, is on interest rate model.
The curve
Two slopes meeting at a kink. Every market has its own curve; they share the kink, the max rate and the max utilisation:
| Market | Base rate, at 0% | Rate at the kink | Kink | Max rate, at 100% | Max utilisation |
|---|---|---|---|---|---|
| SPY / USDG | 0.5% | 6% | 80% | 100% | 100% |
| WETH / USDG | 0.5% | 7% | 80% | 100% | 100% |
| QQQ / USDG | 0.5% | 7% | 80% | 100% | 100% |
| NVDA / USDG | 1% | 9% | 80% | 100% | 100% |
| MSFT / USDG | 1% | 9% | 80% | 100% | 100% |
| AAPL / USDG | 1% | 9% | 80% | 100% | 100% |
| GOOGL / USDG | 1% | 9% | 80% | 100% | 100% |
| TSLA / USDG | 1% | 12% | 80% | 100% | 100% |
| SPCX / USDG | 1.5% | 14% | 80% | 100% | 100% |
| AMD / USDG | 1.5% | 14% | 80% | 100% | 100% |
Set by the protocol Safe (transaction nonce 4, executed at block 96020636 on 23 October 2026) and read from the interest rate model at block 96027397. Until then all five markets shared 0.5% / 8% / 100% with a kink at 80% and a max utilisation of 90%. MSFT/USDG and AAPL/USDG were listed on 27 October 2026 with NVDA/USDG's curve (read at block 99388687). QQQ/USDG, GOOGL/USDG and AMD/USDG were listed on 13 November 2026 with WETH/USDG's, NVDA/USDG's and SPCX/USDG's curves respectively (read at block 113204091).
Riskier collateral pays more. The markets' only lender is the shared Earn vault, so its depositors are the ones who absorb bad debt first if a liquidation comes too late. A market whose collateral can fall further between two prices pays them more for that risk. SPY is an index and the least volatile; QQQ is an index too, of a narrower set of stocks, and pays WETH's rate; WETH trades around the clock, so there is no weekend gap; NVDA, MSFT, AAPL and GOOGL are single stocks; TSLA, SPCX and AMD are the most volatile, and pay the most.
Below the kink a market's rate climbs linearly from its base rate to its kink rate. Above it the second slope runs from the kink rate to the max rate at 100% utilisation:
below the kink: rate = base + utilisation / 80% × (kink rate − base)
above the kink: rate = kink rate + (utilisation − 80%) / 20% × (100% − kink rate)| Utilisation | SPY | WETH, QQQ | NVDA, MSFT, AAPL, GOOGL | TSLA | SPCX, AMD |
|---|---|---|---|---|---|
| 0% | 0.5% | 0.5% | 1% | 1% | 1.5% |
| 40% | 3.25% | 3.75% | 5% | 6.5% | 7.75% |
| 80% | 6% | 7% | 9% | 12% | 14% |
| 90% | 53% | 53.5% | 54.5% | 56% | 57% |
| 100% | 100% | 100% | 100% | 100% | 100% |
Utilisation above 100% is clamped, so the rate never exceeds the max rate.
Max utilisation is a separate limit, and it is 100%. A borrow reverts MaxUtilizationReached
when the vault's utilisation after it would be at or above the borrowing market's max utilisation,
whichever market it is made in. At 100% that means borrowing is allowed until the vault is fully
lent: only a borrow that would take utilisation to exactly 100% reverts. The headroom is shared:
what one market borrows, the others can no longer borrow. maxBorrowable() on a market's router
returns the largest borrow it would accept now. Utilisation can also move without a new borrow —
interest accrues onto the debt, and lenders can withdraw idle USDG — and the rate keeps following
the curve.
There is therefore no guaranteed cash buffer for lenders who want to withdraw. What is left to keep one is price: past the kink, every market's rate climbs steeply towards 100%.
Why the bend
A lending market has one lever to keep withdrawals possible, and it is price. Below the kink there is plenty of idle liquidity and no reason to discourage borrowing. Above it, every additional borrow eats into the idle USDG that lets lenders exit — and with max utilisation at 100%, nothing else reserves it — so the rate rises fast enough that borrowers repay and suppliers arrive.
The steepness is not a fee. It is the mechanism that makes the pool self-correcting without anyone intervening.
What lenders receive
supply rate = borrow rate × (totalBorrowAssets / totalSupplyAssets) × (1 − reserve factor)That is the return on what the Earn vault has in the market. The ratio is the market's own
borrowed over supply held, not the vault-wide utilisation the curve uses. An Earn depositor
receives the vault's blended return across markets, less the vault's fee — see
Earn vault. Before the fee, that blend is each market's borrow rate weighted by
its share of the debt: Σ (market's borrow rate × its totalBorrowAssets) / A × (1 − reserve factor).
If all of the debt were in one market, it would be borrow rate × utilisation × (1 − reserve factor).
Two things follow. A high borrow rate at low utilisation earns lenders little, because few
borrowers are paying it. And the reserve factor is a real deduction — 10% on every market, even though
the stored value reads 0. Read the effective value from reserveFactor(router): reading the stored
0 as zero overstates the supply APY.
Accrual
Interest is owed every second, but it is written to storage only when accrueInterest() runs.
Each run charges the whole window since the last one, linearly, at the rate of that window, and adds
it to the debt — so the next run charges interest on that interest. Interest therefore
compounds at every booking, not continuously and not on a schedule, and a busy market compounds
more often than a quiet one.
accrueInterest() runs automatically on borrow, repay, liquidation, supplying and withdrawing
collateral, and every Earn vault deposit or withdrawal. Because every market's rate depends on the
vault's utilisation, the vault only stores a new utilisation after every market has accrued at
the old one: each borrow, repay and liquidation calls the vault's accrueInterestAll(), and every
vault deposit and withdrawal does the same. Between those moments every market's rate is fixed,
so no market is charged at a rate set by later activity. Both calls are permissionless: anyone can
make them. There is no action a borrower or lender needs to take.
Formulas, rounding and a worked example are on
interest accrual; what compounding does to the annual figure is on
APR and APY.
Curves are per market
The curve is configured per market on the interest rate model, keyed by the market's router
address, and each market's is different — see the curve. One is changed without
touching the others: setLendingPoolRateCurve(router, …) sets one market's base rate, kink rate,
kink, max utilisation and max rate in a single call. The utilisation it is applied to is always the
vault's.