Interest Rate Model Explorer
A live demo of the kinked interest rate curve nearly every DeFi lending protocol uses: gentle while the pool has spare liquidity, steep once it does not. Every parameter is fixed at deployment — no owner, no setter, no upgrade path — and every figure on this page is read straight off the contract on Base Sepolia.
Base Sepolia · testnet only
This demo is read-only. There is no wallet to connect and nothing to sign: every function on the contract is a view, so the whole page — including the slider below — is built from eth_call. You will not be asked for a signature and you will not spend any gas.
Model 0x3F5F…CeC8 · Deployed in block 44788685, tx 0xbd8b…d760 · Source on GitHub
What a kinked curve is
A lending pool has to answer one question continuously: given how much of it is currently lent out — its utilization — what should borrowers pay, and what should suppliers earn?
A single straight line does not work. If the rate rises evenly from empty to full, taking the last of the pool costs barely more than taking the first, and a pool that runs dry cannot honor withdrawals. So the curve has two segments joined at a bend called the kink: below it the rate rises gently, above it steeply. The steep half is what makes the final slice of liquidity expensive to borrow and profitable to replace.
borrow rate
^
| /
| / <- slope2, steep
| /
| __________/ <- the kink
| __________/
| __________/ <- slope1, gentle
| /
+-------------------------------------> utilization
0 kink 100%
The parameters, read from the chain
These six numbers are the contract. It has no setter, so what was passed to the constructor is what it means forever — which is why this table is read from the deployed contract on every page load rather than written into this page. A hardcoded table would be asserting that the curve cannot change; reading it demonstrates it.
Live data unavailable — showing the last known values.
| Constructor argument | What it does | Value | On chain (WAD) |
|---|---|---|---|
baseRatePerYear |
charged on a pool with nothing lent out | 2.00% | 20000000000000000 |
slope1PerYear |
added across the whole first segment, from idle to the kink | 8.00% | 80000000000000000 |
kink |
the utilization at which the curve steepens | 80.00% | 800000000000000000 |
slope2PerYear |
added across the second segment, from the kink to fully lent out | 100.00% | 1000000000000000000 |
reserveFactor |
the share of borrow interest the protocol keeps | 10.00% | 100000000000000000 |
maxBorrowRatePerYear |
the ceiling — the rate at 100% utilization, derived at construction | 110.00% | 1100000000000000000 |
Read at block 44792366. Every value is WAD-scaled: 1e18 means 1.0, so a rate of 20000000000000000 is 2% per year. The right-hand column is exactly what Basescan’s Read Contract tab returns, so you can check this page against the chain without scaling anything by hand.
The curve
| Utilization | Borrow rate | Supply rate |
|---|---|---|
| 0% | 2.00% | 0.00% |
| 25% | 4.50% | 1.01% |
| 50% | 7.00% | 3.15% |
| 80% the kink | 10.00% | 7.20% |
| 90% | 60.00% | 48.60% |
| 95% | 85.00% | 72.67% |
| 100% | 110.00% | 99.00% |
The supply rate is always the lower of the two, and not only because of the reserve factor: borrowers pay interest on the borrowed portion, while suppliers are paid across everything they supplied, lent out or idle. At 50% utilization half the pool is earning nothing, which is most of the gap you can see in the table.
The seam
The kink is the one place a fixed-point model breaks if it breaks at all: it is where two different formulas have to agree, to the wei. Here is the deployed contract asked for the borrow rate one wei either side of it.
| Utilization | Borrow rate | On chain (WAD) |
|---|---|---|
kink − 1 wei | 10.00% | 100000000000000000 |
kink — 80.00% | 10.00% | 100000000000000000 |
kink + 1 wei | 10.00% | 100000000000000005 |
The gentle segment arrives at exactly the value the steep segment starts from — the two middle figures are the same integer, not merely close. One wei further and the rate moves by 5, which is the steep segment’s rise per wei of utilization. That is what “no step at the kink” means for a function on the integers, where no jump cannot mean no change at all.
A worked pool
A pool holding 150 idle, with 50 lent out and 25 held as protocol reserves. Reserves come out of the denominator because they are not lending capacity, so the ratio is 50 over 175 — and the contract, not this page, computes it: 28.57% utilization, a borrow rate of 4.85% and a supply rate of 1.24%.
Move the utilization
- Utilization—
- Borrow rate—
- Supply rate—
Each move reads the deployed contract with eth_call. No wallet, no signature, no gas.
How it is verified
The contract passes the Pigfox Solidity pipeline on every push: formatting, build, tests, 100% line, statement, branch and function coverage with no exclusions, Slither at fail-on: low, and property fuzzing under both Echidna and Medusa.
Eight invariants are claimed — not for the one curve deployed here, but for the whole valid parameter space, so the harness constructs six curves including the awkward ones (a kink one wei above zero, one wei below full, every rate at its ceiling):
- the borrow rate never falls as the pool empties
- the two segments meet at the kink with no step between them
- an idle pool charges exactly the base rate
- the curve has a ceiling, and reaches it exactly at full utilization
- the pool never promises suppliers more than it charges borrowers
- an idle pool pays suppliers nothing
- no pool state reports more than fully lent out
- the model agrees with itself
The property count is declared, not counted: the harness states it as a literal, a static gate counts the predicates, and each fuzzer is checked against what it actually registered at runtime — so a property that quietly stops being picked up fails the build instead of reporting a smaller green run. The harness’s own detectors are tested too, by installing a model built to break each property and requiring the matching predicate to notice. Full detail, including the rounding decisions and the live read-back, in the repository.