Each scenario is measured twice: against the exact inputs, which is what a protocol sees, and against the inputs as each format rounds them, which isolates the arithmetic. The chart covers every input; the table below it is the reference input, cell by cell.
BL127's and BL19's deployed contracts checked live on Sepolia: 1,913 results at block 12,017,732, 0 mismatches. The other libraries' results reproduce locally with make ladder. 2026-10-29, runner 0x7683126a…. Re-run: uv run scripts/ladder/livecap.py
How this was measured
- truth
- For every scenario, input and N the same loop is run in exact real arithmetic with mpmath at 300 decimal digits (scripts/ladder/ladder.py), from the exact rational parameters in scenarios.json. Closed forms are used where the loop has one (compounding, the cumulative product, the geometric mean, the round trip, per-second and continuous accrual, the option walk, the decay and the adaptive rate); the bonding curve, the amortising loan and the Black-Scholes chain are stepped.
- rounding
- Inputs are floored on the grids and rounded to nearest on the floats: each library receives the parameters floored into its own representation (2^-128, 2^-64, 10^-18 or 10^-27 units) or, for ABDKMathQuad and BL19, the nearest float (scripts/ladder/inputs.json). truthFormat is the exact loop started from those parameters, so digitsFormat measures the library's arithmetic alone, while digits measures what a protocol sees: the format's rounding of the inputs plus the arithmetic. One exception: Morpho accrues from the per-second rate, rateAnnual / 31536000 floored to WAD, while truthFormat is built from the annual rate the other libraries receive, so Morpho's digitsFormat still includes its own input's rounding. Likewise in the adaptive rate, FraxLend and Euler compute from their own inputs (utilisation, step, half-life or speed) while truthFormat is built from rate0 and x, so their digitsFormat includes the rounding of those inputs (Euler's speed floored to WAD per second, FraxLend's half-life to whole seconds).
- inputs
- The parameters are short decimals (0.1/365, 10000, 0.05) as a protocol's governance would set them. A short decimal can sit exactly on the 10^-18 and 10^-27 grids, so WAD and RAY libraries often receive their inputs exactly while the binary formats round them; this favours WAD and RAY in digits (against exact inputs) and is visible as the gap between digits and digitsFormat. The decay scenario's eps are reciprocals of time constants in seconds (1/1036800 for twelve days), which no grid holds exactly.
- powers
- Integer powers are each library's own idiom, not one algorithm: BL127 and BL19 use compound (a correctly rounded (1 + r)^n that never forms a rounded 1 + r), Maker uses rpow (binary exponentiation in RAY), the WAD and 64.64 libraries and binary128 use exp(n ln(1 + r)) or their pow. Per-second accrual and compound-pow measure those choices as much as the formats.
- digits
- digits = floor(-log10 |v - t| / |t|), the number of correct leading significant digits by relative error, an integer; a result equal to the truth is exact (exact = true, digits = 100, the one cap on this field) and is drawn as a marker, never as a number. digits1 is the same quantity floored to one decimal instead of to an integer. It is not a string comparison: a value can be correct to 36 digits while its 37th printed digit happens to agree with the truth, or while a carry makes the printed prefix differ earlier.
- precision
- No format can be right to more digits than it holds at the result's magnitude: prec is 237 log10 2 = 71.3 for BL19 and 113 log10 2 = 34.0 for binary128 at any magnitude, and -log10(ulp / |t|) on the fixed grids, with ulp 2^-128 (BL127), 2^-64 (64.64), 10^-18 (WAD) or 10^-27 (RAY): 38.5 for BL127 at 1, 42.5 at 10^4. A cell may land closer to the truth than that by luck; digitsCapped = min(digits1, prec), and prec for an exact cell, is what the charts plot and the summaries aggregate, so no median or band exceeds the format's precision.
- medians
- Each scenario's median, minimum and maximum at each N are taken over the inputs that every library with any completed input at that N completed, so every library's median is over the same inputs. Each library's completed count is reported, and a library that completed fewer than all inputs is shown as k/n. Where no input is common to all of them, a revert counts as 0 digits over all inputs instead (basis revertsAsZero); the dataset records the basis and the inputs per N.
- interest
- For the compounding and accrual scenarios the digits are also measured on the interest, b - principal against t - principal (interestDigits1, interestCapped, with the format's precision taken against the interest's magnitude). Relative digits of a balance flatter a format when the interest is a small part of it: after one day the interest is about 10^-4 of the balance.
- wei
- For the deep-tail option, absErrWei is |v - t| in wei of the strike at 18 decimals ($100 = 10^20 wei). Past d1 = -8 the true price falls below one wei and every library's error with it, so relative digits there describe the format, not money.
- headline
- The Results page shows a single N = 10,000 per scenario; the ladder page shows every N.
- agree
- agree is the count of leading significant digits of the printed value (42 significant digits) that are literally equal to the printed truth. The demo page colours the rest of the value with it. It is a reading aid, not a measurement: a carry across 0.999… / 1.000… gives 0.
- gas
- gasTotal is measured inside the adapter around the scenario function (the parameter reads and the loop), after the runner has warmed the adapter and the BL127 object, so the call into the adapter and the ABI decoding are excluded. The BL127 (deployed) form includes one staticcall per op, and so does snekmate, a Vyper library that a Solidity adapter can only call; BL127Lib and the other libraries are internal calls. Aave, Morpho and Maker answer only the accrual scenarios their models describe, FraxLend and Euler only the adaptive rate, and OpenZeppelin and Uniswap FullMath, which have no exp, ln or real power (and FullMath no root), only the scenarios built from mul, div and their roots; each reports Unsupported elsewhere, which the tables and charts leave empty (a library with no model is not a revert). gasPerStep = gasTotal / N. Reverted cells carry no gas.
- live
- LadderRunner.run(scenario, form, n, p) on Sepolia executes any cell with one eth_call and returns (ok, raw, reason, gasPerStep, gasTotal). scripts/ladder/livecap.py sends every cell's floored parameters p and compares the returned raw word with the committed one bit for bit (or the revert selector for a reverted cell). liveMaxN is the largest N per form the public RPC completed within its gas limit, measured by scripts/ladder/livecap.py.
- reproduce
- make ladder regenerates ladder.json and ladder.md from the Foundry harness (test/ladder/Ladder.t.sol) and this script; make ladder-check fails CI when the committed dataset differs. Versions of every library and of forge are recorded in the dataset. Generated 2026-10-28; versions: aave aave-v3-origin@8305565ae342 (MathUtils, transcribed), abdk v3.2, balancer balancer-v3-monorepo@2b9ce4b1b8ad (LogExpMath.sol, vendored), bl127 6c2eeaf, euler evk-periphery@af436991e135 (IRMAdaptiveCurve, ExpLib, transcribed), forge forge Version: 1.7.1, fraxlend fraxlend@2bed49d4dcc6 (VariableInterestRate V2, transcribed), huff sepolia:0xfae694D0c2c44181791F838c54Ed64C3151FfE30@11857616, maker dss pot.sol rpow via solady v0.1.26, morpho morpho-blue@8e26ca6a8dbc (MathLib, transcribed), openzeppelin openzeppelin-contracts v5.7.0 (Math, SignedMath, vendored), prb-math v4.2.0, snekmate v0.1.2 (math module, vyper 0.4.3), solady v0.1.26, solmate solmate@89365b8 (no tag: v6 predates SignedWadMath), uniswap v4-core v4.0.0 (FullMath, vendored).
Daily compound interest
Step: b = b * (1 + r). Result: balance after N days.
Per-block or per-day accrual in every lending protocol: one mul per step, N steps.
Over all 10 inputs
Median correct digits over the inputs every library with a result at that N completed, each capped at what its format holds at that magnitude (BL19 71.3, binary128 34.0, the fixed grids by their last place), so no line passes its format's precision. The WAD libraries are the gold lines, labelled once. BL127Lib coincides with BL127 and is not drawn; Aave, Morpho and Maker appear only on the accrual scenarios their models describe. Hover a point for the library, the range over the inputs and N.
| Floating point | Fixed point | ||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| steps N | BL19 | Quad | BL127 | 64.64 | Solady | Solmate | PRB SD | PRB UD | snek | Balancer | OZ | Uniswap | Maker | Aave | Morpho | Frax | Euler |
| 1 | 71.3 | 33.9 | 38.8 | 19.5 | 18.8 | 18.8 | 18.8 | 18.8 | 18.8 | 18.8 | 18.8 | 18.8 | 27.4 | — | — | — | — |
| 2 | 71.2 | 33.6 | 38.5 | 19.3 | 18.5 | 18.5 | 18.5 | 18.5 | 18.5 | 18.5 | 18.5 | 18.5 | 26.9 | — | — | — | — |
| 5 | 70.7 | 33.2 | 38.1 | 18.8 | 18.1 | 18.1 | 18.1 | 18.1 | 18.1 | 18.1 | 18.1 | 18.1 | 26.6 | — | — | — | — |
| 10 | 70.4 | 32.9 | 37.8 | 18.5 | 17.8 | 17.8 | 17.8 | 17.8 | 17.8 | 17.8 | 17.8 | 17.8 | 26.3 | — | — | — | — |
| 20 | 70.1 | 32.6 | 37.5 | 18.2 | 17.5 | 17.5 | 17.5 | 17.5 | 17.5 | 17.5 | 17.5 | 17.5 | 26.0 | — | — | — | — |
| 50 | 69.7 | 32.2 | 37.1 | 17.8 | 17.1 | 17.1 | 17.1 | 17.1 | 17.1 | 17.1 | 17.1 | 17.1 | 25.6 | — | — | — | — |
| 100 | 69.4 | 31.9 | 36.8 | 17.5 | 16.8 | 16.8 | 16.8 | 16.8 | 16.8 | 16.8 | 16.8 | 16.8 | 25.3 | — | — | — | — |
| 365 | 68.8 | 31.3 | 36.2 | 17.0 | 16.3 | 16.3 | 16.3 | 16.3 | 16.3 | 16.3 | 16.3 | 16.3 | 24.8 | — | — | — | — |
| 1,000 | 68.4 | 30.9 | 35.8 | 16.6 | 15.8 | 15.8 | 15.8 | 15.8 | 15.8 | 15.8 | 15.8 | 15.8 | 24.3 | — | — | — | — |
| 10,000 | 67.4 | 29.9 | 34.8 | 15.6 | 14.8 | 14.8 | 14.8 | 14.8 | 14.8 | 14.8 | 14.8 | 14.8 | 23.3 | — | — | — | — |
| Floating point | Fixed point | ||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| steps N | BL19 | Quad | BL127 | 64.64 | Solady | Solmate | PRB SD | PRB UD | snek | Balancer | OZ | Uniswap | Maker | Aave | Morpho | Frax | Euler |
| 1 | 71.3 | 33.9 | 42.5 | 23.2 | 22.0 | 22.0 | 22.0 | 22.0 | 22.0 | 22.0 | 22.0 | 22.0 | 31.0 | — | — | — | — |
| 2 | 71.2 | 33.6 | 42.5 | 23.2 | 22.0 | 22.0 | 22.0 | 22.0 | 22.0 | 22.0 | 22.0 | 22.0 | 27.3 | — | — | — | — |
| 5 | 70.7 | 33.2 | 42.2 | 23.0 | 21.6 | 21.6 | 21.6 | 21.6 | 21.6 | 21.6 | 21.6 | 21.6 | 27.0 | — | — | — | — |
| 10 | 70.4 | 32.9 | 41.8 | 22.6 | 21.4 | 21.4 | 21.4 | 21.4 | 21.4 | 21.4 | 21.4 | 21.4 | 26.8 | — | — | — | — |
| 20 | 70.1 | 32.6 | 41.5 | 22.2 | 21.0 | 21.0 | 21.0 | 21.0 | 21.0 | 21.0 | 21.0 | 21.0 | 26.5 | — | — | — | — |
| 50 | 69.7 | 32.2 | 41.1 | 21.8 | 20.6 | 20.6 | 20.6 | 20.6 | 20.6 | 20.6 | 20.6 | 20.6 | 26.1 | — | — | — | — |
| 100 | 69.4 | 31.9 | 40.8 | 21.5 | 20.3 | 20.3 | 20.3 | 20.3 | 20.3 | 20.3 | 20.3 | 20.3 | 25.8 | — | — | — | — |
| 365 | 68.8 | 31.3 | 40.2 | 21.0 | 19.7 | 19.7 | 19.7 | 19.7 | 19.7 | 19.7 | 19.7 | 19.7 | 25.2 | — | — | — | — |
| 1,000 | 68.4 | 30.9 | 39.8 | 20.6 | 19.3 | 19.3 | 19.3 | 19.3 | 19.3 | 19.3 | 19.3 | 19.3 | 24.8 | — | — | — | — |
| 10,000 | 67.4 | 29.9 | 39.1 | 19.9 | 18.6 | 18.6 | 18.6 | 18.6 | 18.6 | 18.6 | 18.6 | 18.6 | 23.8 | — | — | — | — |
| Floating point | Fixed point | ||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| steps N | BL19 | Quad | BL127 | 64.64 | Solady | Solmate | PRB SD | PRB UD | snek | Balancer | OZ | Uniswap | Maker | Aave | Morpho | Frax | Euler |
| 1 | 67.6 | 30.4 | 35.2 | 16.1 | 16.0 | 16.0 | 16.0 | 16.0 | 16.0 | 16.0 | 16.0 | 16.0 | 24.0 | — | — | — | — |
| 2 | 67.8 | 30.4 | 35.2 | 16.1 | 15.9 | 15.9 | 15.9 | 15.9 | 15.9 | 15.9 | 15.9 | 15.9 | 23.7 | — | — | — | — |
| 5 | 68.0 | 30.4 | 35.2 | 16.1 | 15.9 | 15.9 | 15.9 | 15.9 | 15.9 | 15.9 | 15.9 | 15.9 | 23.7 | — | — | — | — |
| 10 | 68.0 | 30.4 | 35.2 | 16.1 | 15.9 | 15.9 | 15.9 | 15.9 | 15.9 | 15.9 | 15.9 | 15.9 | 23.7 | — | — | — | — |
| 20 | 67.9 | 30.4 | 35.2 | 16.1 | 15.9 | 15.9 | 15.9 | 15.9 | 15.9 | 15.9 | 15.9 | 15.9 | 23.8 | — | — | — | — |
| 50 | 68.0 | 30.4 | 35.2 | 16.1 | 15.9 | 15.9 | 15.9 | 15.9 | 15.9 | 15.9 | 15.9 | 15.9 | 23.8 | — | — | — | — |
| 100 | 68.0 | 30.3 | 35.2 | 16.1 | 15.9 | 15.9 | 15.9 | 15.9 | 15.9 | 15.9 | 15.9 | 15.9 | 23.8 | — | — | — | — |
| 365 | 67.9 | 30.3 | 35.2 | 16.1 | 15.8 | 15.8 | 15.8 | 15.8 | 15.8 | 15.8 | 15.8 | 15.8 | 23.7 | — | — | — | — |
| 1,000 | 67.9 | 30.2 | 35.2 | 16.0 | 15.7 | 15.7 | 15.7 | 15.7 | 15.7 | 15.7 | 15.7 | 15.7 | 23.7 | — | — | — | — |
| 10,000 | 67.4 | 29.9 | 34.8 | 15.3 | 14.8 | 14.8 | 14.8 | 14.8 | 14.8 | 14.8 | 14.8 | 14.8 | 23.3 | — | — | — | — |
Median correct digits over the inputs every library completed at that N (hover a cell for the range), each capped at what its format holds; "exact" when every one of them is exact. k/n: the library completed k of n inputs and the rest reverted; rev: every input reverted. —: no model for this scenario. BL127Lib equals BL127 and is left out.
The inputs and the ops
| input | parameters | why |
|---|---|---|
| reference | principal = 10000, rate = 0.1/365 | $10,000 at 10% APR, the headline cell |
| tiny-low | principal = 1, rate = 0.01/365 | one unit at 1%: the integer part is small, the fraction carries everything |
| tiny-high | principal = 1, rate = 0.5/365 | one unit at 50% |
| mid-1pct | principal = 10000, rate = 0.01/365 | a slow rate: the per-step factor is close to 1 |
| mid-5pct | principal = 10000, rate = 0.05/365 | a typical lending rate |
| mid-50pct | principal = 10000, rate = 0.5/365 | a high rate: the balance grows 150x by N = 10,000 |
| large | principal = 1000000, rate = 0.1/365 | a million-unit position |
| huge | principal = 100000000, rate = 0.1/365 | a hundred-million-unit pool |
| huge-high | principal = 100000000, rate = 0.5/365 | the largest balance the ladder reaches, near 10^14 |
| fraction | principal = 0.001, rate = 0.1/365 | a sub-unit balance: leading zeros in WAD |
Library calls per step: BL19 mul; Quad mul; BL127 mul; 64.64 mul; Solady sMulWad; Solmate wadMul; PRB SD mul; PRB UD mul; snek mul_div(a, b, 1e18); Balancer mulDown; OZ mulDiv(a, b, 1e18); Uniswap mulDiv(a, b, 1e18); Maker rpow, rmul; Aave unsupported; Morpho unsupported; Frax unsupported; Euler unsupported; BL127Lib mul. Parameters reach each adapter floored into its representation on the grids and rounded to nearest on the floats (ladder-inputs.json).
The reference input, step by step: principal = 10000, rate = 0.1/365
Correct digits against the exact truth at each N, capped at what the format holds. Hover a cell for the value itself, the digits against the format-rounded truth, of the interest, the error in units of the last place and the gas per step.
| Floating point | Fixed point | ||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| steps N | BL19 | Quad | BL127 | 64.64 | Solady | Solmate | PRB SD | PRB UD | snek | Balancer | OZ | Uniswap | Maker | Aave | Morpho | Frax | Euler |
| 1 | 71.3 | 33.9 | 38.8 | 19.7 | 19.5 | 19.5 | 19.5 | 19.5 | 19.5 | 19.5 | 19.5 | 19.5 | 27.5 | — | — | — | — |
| 2 | 71.3 | 33.5 | 38.5 | 19.4 | 19.2 | 19.2 | 19.2 | 19.2 | 19.2 | 19.2 | 19.2 | 19.2 | 26.9 | — | — | — | — |
| 5 | 70.9 | 33.1 | 38.1 | 19.0 | 18.8 | 18.8 | 18.8 | 18.8 | 18.8 | 18.8 | 18.8 | 18.8 | 26.6 | — | — | — | — |
| 10 | 70.6 | 32.9 | 37.8 | 18.7 | 18.5 | 18.5 | 18.5 | 18.5 | 18.5 | 18.5 | 18.5 | 18.5 | 26.3 | — | — | — | — |
| 20 | 70.1 | 32.6 | 37.5 | 18.4 | 18.2 | 18.2 | 18.2 | 18.2 | 18.2 | 18.2 | 18.2 | 18.2 | 26.0 | — | — | — | — |
| 50 | 69.8 | 32.2 | 37.1 | 18.0 | 17.8 | 17.8 | 17.8 | 17.8 | 17.8 | 17.8 | 17.8 | 17.8 | 25.6 | — | — | — | — |
| 100 | 69.6 | 31.9 | 36.8 | 17.7 | 17.5 | 17.5 | 17.5 | 17.5 | 17.5 | 17.5 | 17.5 | 17.5 | 25.3 | — | — | — | — |
| 365 | 68.9 | 31.3 | 36.2 | 17.1 | 16.9 | 16.9 | 16.9 | 16.9 | 16.9 | 16.9 | 16.9 | 16.9 | 24.8 | — | — | — | — |
| 1,000 | 68.5 | 30.9 | 35.8 | 16.7 | 16.5 | 16.5 | 16.5 | 16.5 | 16.5 | 16.5 | 16.5 | 16.5 | 24.3 | — | — | — | — |
| 10,000 | 67.5 | 29.9 | 34.8 | 15.7 | 15.5 | 15.5 | 15.5 | 15.5 | 15.5 | 15.5 | 15.5 | 15.5 | 23.3 | — | — | — | — |
Compound interest in one pow
Step: b0 * (1 + r)^N. Result: the same balance, computed with one real-exponent pow.
The clever way to skip the loop. pow is exp(N ln(1+r)) in every library, so its precision is bounded by ln and exp, and the error grows with N without any loop.
Over all 10 inputs
Median correct digits over the inputs every library with a result at that N completed, each capped at what its format holds at that magnitude (BL19 71.3, binary128 34.0, the fixed grids by their last place), so no line passes its format's precision. The WAD libraries are the gold lines, labelled once. BL127Lib coincides with BL127 and is not drawn; Aave, Morpho and Maker appear only on the accrual scenarios their models describe. Hover a point for the library, the range over the inputs and N.
| Floating point | Fixed point | ||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| steps N | BL19 | Quad | BL127 | 64.64 | Solady | Solmate | PRB SD | PRB UD | snek | Balancer | OZ | Uniswap | Maker | Aave | Morpho | Frax | Euler |
| 1 | 71.3 | 33.5 | 38.8 | 19.0 | 17.9 | 17.9 | 18.8 | 18.8 | 17.9 | 17.9 | — | — | — | — | — | — | — |
| 2 | 71.2 | 33.5 | 38.6 | 18.7 | 17.7 | 17.7 | 16.7 | 16.7 | 17.7 | 17.7 | — | — | — | — | — | — | — |
| 5 | 70.8 | 33.3 | 38.1 | 18.5 | 17.4 | 17.4 | 16.4 | 16.4 | 17.4 | 17.9 | — | — | — | — | — | — | — |
| 10 | 70.4 | 33.2 | 37.8 | 18.2 | 17.2 | 17.2 | 16.0 | 16.0 | 17.2 | 17.6 | — | — | — | — | — | — | — |
| 20 | 70.2 | 33.0 | 37.5 | 17.9 | 16.8 | 16.8 | 15.8 | 15.8 | 16.8 | 17.4 | — | — | — | — | — | — | — |
| 50 | 69.8 | 32.6 | 37.1 | 17.5 | 16.5 | 16.5 | 15.4 | 15.4 | 16.5 | 17.0 | — | — | — | — | — | — | — |
| 100 | 69.4 | 32.3 | 36.8 | 17.2 | 16.2 | 16.2 | 15.0 | 15.0 | 16.2 | 16.8 | — | — | — | — | — | — | — |
| 365 | 68.8 | 31.8 | 36.2 | 16.7 | 15.6 | 15.6 | 14.4 | 14.4 | 15.6 | 16.2 | — | — | — | — | — | — | — |
| 1,000 | 68.4 | 31.4 | 35.8 | 16.2 | 15.2 | 15.2 | 14.0 | 14.0 | 15.2 | 15.8 | — | — | — | — | — | — | — |
| 10,000 | 67.4 | 30.4 | 34.8 | 15.2 | 14.2 | 14.2 | 13.0 | 13.0 | 14.2 | 15.2 | — | — | — | — | — | — | — |
| Floating point | Fixed point | ||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| steps N | BL19 | Quad | BL127 | 64.64 | Solady | Solmate | PRB SD | PRB UD | snek | Balancer | OZ | Uniswap | Maker | Aave | Morpho | Frax | Euler |
| 1 | 71.3 | 33.5 | 42.5 | 19.2 | 18.0 | 18.0 | 22.0 | 22.0 | 18.0 | 18.0 | — | — | — | — | — | — | — |
| 2 | 71.2 | 33.5 | 38.8 | 19.0 | 17.8 | 17.8 | 16.7 | 16.7 | 17.8 | 17.8 | — | — | — | — | — | — | — |
| 5 | 70.8 | 33.3 | 38.9 | 18.7 | 17.5 | 17.5 | 16.4 | 16.4 | 17.5 | 18.0 | — | — | — | — | — | — | — |
| 10 | 70.4 | 33.2 | 39.3 | 18.5 | 17.3 | 17.3 | 16.0 | 16.0 | 17.3 | 18.0 | — | — | — | — | — | — | — |
| 20 | 70.2 | 33.0 | 39.2 | 18.2 | 16.9 | 16.9 | 15.8 | 15.8 | 16.9 | 18.0 | — | — | — | — | — | — | — |
| 50 | 69.8 | 32.6 | 38.9 | 17.8 | 16.6 | 16.6 | 15.4 | 15.4 | 16.6 | 17.9 | — | — | — | — | — | — | — |
| 100 | 69.4 | 32.3 | 39.3 | 17.5 | 16.3 | 16.3 | 15.0 | 15.0 | 16.3 | 17.9 | — | — | — | — | — | — | — |
| 365 | 68.8 | 31.8 | 39.0 | 17.0 | 15.7 | 15.7 | 14.4 | 14.4 | 15.7 | 18.0 | — | — | — | — | — | — | — |
| 1,000 | 68.4 | 31.4 | 39.5 | 16.6 | 15.3 | 15.3 | 14.0 | 14.0 | 15.3 | 18.2 | — | — | — | — | — | — | — |
| 10,000 | 67.4 | 30.4 | 40.3 | 15.6 | 14.3 | 14.3 | 13.0 | 13.0 | 14.3 | 18.0 | — | — | — | — | — | — | — |
| Floating point | Fixed point | ||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| steps N | BL19 | Quad | BL127 | 64.64 | Solady | Solmate | PRB SD | PRB UD | snek | Balancer | OZ | Uniswap | Maker | Aave | Morpho | Frax | Euler |
| 1 | 67.6 | 29.9 | 35.2 | 15.5 | 14.4 | 14.4 | 16.0 | 16.0 | 14.4 | 14.4 | — | — | — | — | — | — | — |
| 2 | 68.0 | 30.2 | 35.5 | 15.4 | 14.7 | 14.7 | 13.4 | 13.4 | 14.7 | 14.7 | — | — | — | — | — | — | — |
| 5 | 68.0 | 30.4 | 35.3 | 15.5 | 14.6 | 14.6 | 13.4 | 13.4 | 14.6 | 15.0 | — | — | — | — | — | — | — |
| 10 | 67.9 | 30.6 | 35.3 | 15.5 | 14.7 | 14.7 | 13.4 | 13.4 | 14.7 | 15.5 | — | — | — | — | — | — | — |
| 20 | 67.9 | 30.7 | 35.2 | 15.6 | 14.7 | 14.7 | 13.4 | 13.4 | 14.7 | 15.5 | — | — | — | — | — | — | — |
| 50 | 67.9 | 30.8 | 35.2 | 15.6 | 14.7 | 14.7 | 13.4 | 13.4 | 14.7 | 15.9 | — | — | — | — | — | — | — |
| 100 | 67.9 | 30.8 | 35.2 | 15.6 | 14.7 | 14.7 | 13.4 | 13.4 | 14.7 | 15.8 | — | — | — | — | — | — | — |
| 365 | 67.9 | 30.8 | 35.2 | 15.6 | 14.7 | 14.7 | 13.4 | 13.4 | 14.7 | 15.8 | — | — | — | — | — | — | — |
| 1,000 | 67.9 | 30.7 | 35.2 | 15.5 | 14.7 | 14.7 | 13.3 | 13.3 | 14.7 | 15.7 | — | — | — | — | — | — | — |
| 10,000 | 67.4 | 30.3 | 34.8 | 15.1 | 14.2 | 14.2 | 12.9 | 12.9 | 14.2 | 15.1 | — | — | — | — | — | — | — |
Median correct digits over the inputs every library completed at that N (hover a cell for the range), each capped at what its format holds; "exact" when every one of them is exact. k/n: the library completed k of n inputs and the rest reverted; rev: every input reverted. —: no model for this scenario. BL127Lib equals BL127 and is left out.
The inputs and the ops
| input | parameters | why |
|---|---|---|
| reference | principal = 10000, rate = 0.1/365 | $10,000 at 10% APR, the headline cell |
| tiny-low | principal = 1, rate = 0.01/365 | one unit at 1%: the integer part is small, the fraction carries everything |
| tiny-high | principal = 1, rate = 0.5/365 | one unit at 50% |
| mid-1pct | principal = 10000, rate = 0.01/365 | a slow rate: the per-step factor is close to 1 |
| mid-5pct | principal = 10000, rate = 0.05/365 | a typical lending rate |
| mid-50pct | principal = 10000, rate = 0.5/365 | a high rate: the balance grows 150x by N = 10,000 |
| large | principal = 1000000, rate = 0.1/365 | a million-unit position |
| huge | principal = 100000000, rate = 0.1/365 | a hundred-million-unit pool |
| huge-high | principal = 100000000, rate = 0.5/365 | the largest balance the ladder reaches, near 10^14 |
| fraction | principal = 0.001, rate = 0.1/365 | a sub-unit balance: leading zeros in WAD |
Library calls per step: BL19 pow, mul; Quad exp(y ln x), mul; BL127 pow, mul; 64.64 exp, mul, ln (pow = exp(y ln x)); Solady powWad, sMulWad; Solmate wadPow, wadMul; PRB SD pow, mul; PRB UD pow, mul; snek wad_exp(wad_ln(x) y), mul_div(a, b, 1e18); Balancer pow, mulDown; OZ unsupported; Uniswap unsupported; Maker unsupported; Aave unsupported; Morpho unsupported; Frax unsupported; Euler unsupported; BL127Lib pow, mul. Parameters reach each adapter floored into its representation on the grids and rounded to nearest on the floats (ladder-inputs.json).
The reference input, step by step: principal = 10000, rate = 0.1/365
Correct digits against the exact truth at each N, capped at what the format holds. Hover a cell for the value itself, the digits against the format-rounded truth, of the interest, the error in units of the last place and the gas per step.
| Floating point | Fixed point | ||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| steps N | BL19 | Quad | BL127 | 64.64 | Solady | Solmate | PRB SD | PRB UD | snek | Balancer | OZ | Uniswap | Maker | Aave | Morpho | Frax | Euler |
| 1 | 71.3 | 33.5 | 38.8 | 19.1 | 17.9 | 17.9 | 19.5 | 19.5 | 17.9 | 17.9 | — | — | — | — | — | — | — |
| 2 | 71.3 | 33.5 | 38.8 | 18.7 | 17.9 | 17.9 | 16.6 | 16.6 | 17.9 | 17.9 | — | — | — | — | — | — | — |
| 5 | 70.9 | 33.3 | 38.2 | 18.4 | 17.5 | 17.5 | 16.3 | 16.3 | 17.5 | 17.9 | — | — | — | — | — | — | — |
| 10 | 70.5 | 33.2 | 37.8 | 18.1 | 17.3 | 17.3 | 16.0 | 16.0 | 17.3 | 18.1 | — | — | — | — | — | — | — |
| 20 | 70.2 | 33.0 | 37.5 | 17.8 | 17.0 | 17.0 | 15.7 | 15.7 | 17.0 | 17.8 | — | — | — | — | — | — | — |
| 50 | 69.8 | 32.6 | 37.1 | 17.4 | 16.6 | 16.6 | 15.3 | 15.3 | 16.6 | 17.8 | — | — | — | — | — | — | — |
| 100 | 69.5 | 32.3 | 36.8 | 17.1 | 16.3 | 16.3 | 15.0 | 15.0 | 16.3 | 17.4 | — | — | — | — | — | — | — |
| 365 | 68.9 | 31.8 | 36.2 | 16.6 | 15.7 | 15.7 | 14.4 | 14.4 | 15.7 | 16.9 | — | — | — | — | — | — | — |
| 1,000 | 68.5 | 31.4 | 35.8 | 16.1 | 15.3 | 15.3 | 14.0 | 14.0 | 15.3 | 16.5 | — | — | — | — | — | — | — |
| 10,000 | 67.5 | 30.4 | 34.8 | 15.1 | 14.3 | 14.3 | 13.0 | 13.0 | 14.3 | 15.5 | — | — | — | — | — | — | — |
Square-root bonding curve
Step: cost += sqrt(s); s += 1. Result: total cost of N unit buys.
Bonding curves price each token at a root of the supply; the sum of N floors is where the digits go.
Over all 7 inputs
Median correct digits over the inputs every library with a result at that N completed, each capped at what its format holds at that magnitude (BL19 71.3, binary128 34.0, the fixed grids by their last place), so no line passes its format's precision. The WAD libraries are the gold lines, labelled once. BL127Lib coincides with BL127 and is not drawn; Aave, Morpho and Maker appear only on the accrual scenarios their models describe. Hover a point for the library, the range over the inputs and N.
| Floating point | Fixed point | ||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| steps N | BL19 | Quad | BL127 | 64.64 | Solady | Solmate | PRB SD | PRB UD | snek | Balancer | OZ | Uniswap | Maker | Aave | Morpho | Frax | Euler |
| 1 | 71.3 | 34.0 | 40.0 | 20.7 | 19.5 | 19.5 | 19.5 | 19.5 | 19.5 | 18.6 | 19.5 | — | — | — | — | — | — |
| 2 | 71.3 | 34.0 | 40.3 | 20.9 | 19.5 | 19.5 | 19.5 | 19.5 | 19.5 | 18.2 | 19.5 | — | — | — | — | — | — |
| 5 | 71.3 | 33.7 | 40.3 | 21.0 | 19.8 | 19.8 | 19.8 | 19.8 | 19.8 | 18.1 | 19.8 | — | — | — | — | — | — |
| 10 | 71.3 | 33.3 | 40.3 | 20.9 | 19.7 | 19.7 | 19.7 | 19.7 | 19.7 | 18.1 | 19.7 | — | — | — | — | — | — |
| 20 | 71.2 | 33.1 | 40.2 | 21.0 | 19.7 | 19.7 | 19.7 | 19.7 | 19.7 | 18.1 | 19.7 | — | — | — | — | — | — |
| 50 | 70.9 | 32.7 | 40.3 | 21.0 | 19.8 | 19.8 | 19.8 | 19.8 | 19.8 | 18.0 | 19.8 | — | — | — | — | — | — |
| 100 | 70.8 | 32.4 | 40.3 | 21.0 | 19.8 | 19.8 | 19.8 | 19.8 | 19.8 | 18.0 | 19.8 | — | — | — | — | — | — |
| 365 | 70.5 | 31.8 | 40.3 | 21.0 | 19.8 | 19.8 | 19.8 | 19.8 | 19.8 | 18.1 | 19.8 | — | — | — | — | — | — |
| 1,000 | 70.3 | 31.4 | 40.3 | 21.1 | 19.8 | 19.8 | 19.8 | 19.8 | 19.8 | 18.1 | 19.8 | — | — | — | — | — | — |
| 10,000 | 70.2 | 30.4 | 40.6 | 21.3 | 20.1 | 20.1 | 20.1 | 20.1 | 20.1 | 18.1 | 20.1 | — | — | — | — | — | — |
| Floating point | Fixed point | ||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| steps N | BL19 | Quad | BL127 | 64.64 | Solady | Solmate | PRB SD | PRB UD | snek | Balancer | OZ | Uniswap | Maker | Aave | Morpho | Frax | Euler |
| 1 | 71.3 | 34.0 | 40.0 | 20.7 | 19.5 | 19.5 | 19.5 | 19.5 | 19.5 | 18.6 | 19.5 | — | — | — | — | — | — |
| 2 | 71.3 | 34.0 | 40.3 | 20.9 | 19.5 | 19.5 | 19.5 | 19.5 | 19.5 | 18.2 | 19.5 | — | — | — | — | — | — |
| 5 | 71.3 | 33.7 | 40.3 | 21.0 | 19.8 | 19.8 | 19.8 | 19.8 | 19.8 | 18.1 | 19.8 | — | — | — | — | — | — |
| 10 | 71.3 | 33.3 | 40.3 | 20.9 | 19.7 | 19.7 | 19.7 | 19.7 | 19.7 | 18.1 | 19.7 | — | — | — | — | — | — |
| 20 | 71.2 | 33.1 | 40.2 | 21.0 | 19.7 | 19.7 | 19.7 | 19.7 | 19.7 | 18.1 | 19.7 | — | — | — | — | — | — |
| 50 | 70.9 | 32.7 | 40.3 | 21.0 | 19.8 | 19.8 | 19.8 | 19.8 | 19.8 | 18.0 | 19.8 | — | — | — | — | — | — |
| 100 | 70.8 | 32.4 | 40.3 | 21.0 | 19.8 | 19.8 | 19.8 | 19.8 | 19.8 | 18.0 | 19.8 | — | — | — | — | — | — |
| 365 | 70.5 | 31.8 | 40.3 | 21.0 | 19.8 | 19.8 | 19.8 | 19.8 | 19.8 | 18.1 | 19.8 | — | — | — | — | — | — |
| 1,000 | 70.3 | 31.4 | 40.3 | 21.1 | 19.8 | 19.8 | 19.8 | 19.8 | 19.8 | 18.1 | 19.8 | — | — | — | — | — | — |
| 10,000 | 70.2 | 30.4 | 40.6 | 21.3 | 20.1 | 20.1 | 20.1 | 20.1 | 20.1 | 18.1 | 20.1 | — | — | — | — | — | — |
Median correct digits over the inputs every library completed at that N (hover a cell for the range), each capped at what its format holds; "exact" when every one of them is exact. k/n: the library completed k of n inputs and the rest reverted; rev: every input reverted. —: no model for this scenario. BL127Lib equals BL127 and is left out.
The inputs and the ops
| input | parameters | why |
|---|---|---|
| reference | supply = 1000, unit = 1 | a thousand tokens out, unit buys |
| from-one | supply = 1, unit = 1 | the curve from its first token |
| half-units | supply = 1000, unit = 0.5 | buys that are not integers |
| deep | supply = 1000000, unit = 1 | a million out: sqrt is large, the sum is huge |
| micro | supply = 1, unit = 0.001 | thousandth-unit buys from the start |
| very-deep | supply = 1000000000, unit = 1000 | a billion out in thousand-token lots |
| small-steps | supply = 10, unit = 0.01 | hundredth-unit buys from ten |
Library calls per step: BL19 sqrt, add; Quad sqrt, add; BL127 sqrt, add; 64.64 sqrt, add; Solady sqrtWad, add; Solmate sqrt(x 1e18), add; PRB SD sqrt, add; PRB UD sqrt, add; snek isqrt(x 1e18) (Vyper built-in), add; Balancer pow(x, 1/2), add; OZ sqrt(x 1e18), add; Uniswap unsupported; Maker unsupported; Aave unsupported; Morpho unsupported; Frax unsupported; Euler unsupported; BL127Lib sqrt, add. Parameters reach each adapter floored into its representation on the grids and rounded to nearest on the floats (ladder-inputs.json).
The reference input, step by step: supply = 1000, unit = 1
Correct digits against the exact truth at each N, capped at what the format holds. Hover a cell for the value itself, the digits against the format-rounded truth, the error in units of the last place and the gas per step.
| Floating point | Fixed point | ||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| steps N | BL19 | Quad | BL127 | 64.64 | Solady | Solmate | PRB SD | PRB UD | snek | Balancer | OZ | Uniswap | Maker | Aave | Morpho | Frax | Euler |
| 1 | 71.3 | 34.0 | 40.0 | 20.7 | 19.5 | 19.5 | 19.5 | 19.5 | 19.5 | 18.6 | 19.5 | — | — | — | — | — | — |
| 2 | 71.3 | 33.8 | 40.3 | 21.0 | 19.7 | 19.7 | 19.7 | 19.7 | 19.7 | 18.2 | 19.7 | — | — | — | — | — | — |
| 5 | 71.3 | 33.7 | 40.3 | 21.0 | 19.8 | 19.8 | 19.8 | 19.8 | 19.8 | 18.2 | 19.8 | — | — | — | — | — | — |
| 10 | 71.3 | 33.4 | 40.3 | 21.0 | 19.7 | 19.7 | 19.7 | 19.7 | 19.7 | 18.1 | 19.7 | — | — | — | — | — | — |
| 20 | 71.3 | 33.1 | 40.3 | 21.0 | 19.7 | 19.7 | 19.7 | 19.7 | 19.7 | 18.1 | 19.7 | — | — | — | — | — | — |
| 50 | 71.1 | 32.7 | 40.3 | 21.0 | 19.8 | 19.8 | 19.8 | 19.8 | 19.8 | 18.0 | 19.8 | — | — | — | — | — | — |
| 100 | 70.9 | 32.4 | 40.3 | 21.0 | 19.8 | 19.8 | 19.8 | 19.8 | 19.8 | 17.8 | 19.8 | — | — | — | — | — | — |
| 365 | 71.3 | 31.8 | 40.3 | 21.1 | 19.8 | 19.8 | 19.8 | 19.8 | 19.8 | 18.1 | 19.8 | — | — | — | — | — | — |
| 1,000 | 70.9 | 31.4 | 40.4 | 21.1 | 19.8 | 19.8 | 19.8 | 19.8 | 19.8 | 18.1 | 19.8 | — | — | — | — | — | — |
| 10,000 | 70.4 | 30.5 | 40.7 | 21.4 | 20.1 | 20.1 | 20.1 | 20.1 | 20.1 | 18.1 | 20.1 | — | — | — | — | — | — |
exp(ln(x)) round trip
Step: x = exp(ln(x)). Result: x after N round trips; the answer is the input.
Isolates transcendental error. Every step should be the identity; what remains is the library's ln and exp error, compounded.
Over all 10 inputs
Median correct digits over the inputs every library with a result at that N completed, each capped at what its format holds at that magnitude (BL19 71.3, binary128 34.0, the fixed grids by their last place), so no line passes its format's precision. The WAD libraries are the gold lines, labelled once. BL127Lib coincides with BL127 and is not drawn; Aave, Morpho and Maker appear only on the accrual scenarios their models describe. Hover a point for the library, the range over the inputs and N.
| Floating point | Fixed point | ||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| steps N | BL19 | Quad | BL127 | 64.64 | Solady | Solmate | PRB SD | PRB UD | snek | Balancer | OZ | Uniswap | Maker | Aave | Morpho | Frax | Euler |
| 1 | 71.3 | 32.9 | 38.8 | 19.1 | 18.3 | 18.3 | 17.0 | 17.0 | 18.3 | 18.0 | — | — | — | — | — | — | — |
| 2 | 71.3 | 32.7 | 38.8 | 18.7 | 17.9 | 17.9 | 16.7 | 16.7 | 17.9 | 17.6 | — | — | — | — | — | — | — |
| 5 | 71.3 | 32.2 | 38.8 | 18.3 | 17.3 | 17.3 | 16.3 | 16.3 | 17.3 | 17.3 | — | — | — | — | — | — | — |
| 10 | 71.3 | 31.9 | 38.8 | 18.0 | 17.0 | 17.0 | 16.0 | 16.0 | 17.0 | 16.9 | — | — | — | — | — | — | — |
| 20 | 71.3 | 31.6 | 38.8 | 17.7 | 16.7 | 16.7 | 15.7 | 15.7 | 16.7 | 16.6 | — | — | — | — | — | — | — |
| 50 | 71.3 | 31.2 | 38.8 | 17.3 | 16.3 | 16.3 | 15.3 | 15.3 | 16.3 | 16.3 | — | — | — | — | — | — | — |
| 100 | 71.3 | 30.9 | 38.8 | 17.0 | 16.0 | 16.0 | 15.0 | 15.0 | 16.0 | 15.9 | — | — | — | — | — | — | — |
| 365 | 71.3 | 30.3 | 38.8 | 16.4 | 15.4 | 15.4 | 14.4 | 14.4 | 15.4 | 15.4 | — | — | — | — | — | — | — |
| 1,000 | 71.3 | 29.9 | 38.8 | 16.0 | 15.0 | 15.0 | 14.0 | 14.0 | 15.0 | 14.9 | — | — | — | — | — | — | — |
| 10,000 | 71.3 | 28.9 | 38.8 | 15.0 | 14.1 | 14.1 | 12.9 | 12.9 | 14.1 | 14.0 | — | — | — | — | — | — | — |
| Floating point | Fixed point | ||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| steps N | BL19 | Quad | BL127 | 64.64 | Solady | Solmate | PRB SD | PRB UD | snek | Balancer | OZ | Uniswap | Maker | Aave | Morpho | Frax | Euler |
| 1 | 71.3 | 32.9 | 38.8 | 19.1 | 18.3 | 18.3 | 17.0 | 17.0 | 18.3 | 18.0 | — | — | — | — | — | — | — |
| 2 | 71.3 | 32.7 | 38.8 | 18.7 | 17.9 | 17.9 | 16.7 | 16.7 | 17.9 | 17.6 | — | — | — | — | — | — | — |
| 5 | 71.3 | 32.2 | 38.8 | 18.3 | 17.3 | 17.3 | 16.3 | 16.3 | 17.3 | 17.3 | — | — | — | — | — | — | — |
| 10 | 71.3 | 31.9 | 38.8 | 18.0 | 17.0 | 17.0 | 16.0 | 16.0 | 17.0 | 17.0 | — | — | — | — | — | — | — |
| 20 | 71.3 | 31.6 | 38.8 | 17.7 | 16.7 | 16.7 | 15.7 | 15.7 | 16.7 | 16.6 | — | — | — | — | — | — | — |
| 50 | 71.3 | 31.2 | 38.8 | 17.3 | 16.3 | 16.3 | 15.3 | 15.3 | 16.3 | 16.3 | — | — | — | — | — | — | — |
| 100 | 71.3 | 30.9 | 38.8 | 17.0 | 16.0 | 16.0 | 15.0 | 15.0 | 16.0 | 16.0 | — | — | — | — | — | — | — |
| 365 | 71.3 | 30.3 | 38.8 | 16.4 | 15.4 | 15.4 | 14.4 | 14.4 | 15.4 | 15.4 | — | — | — | — | — | — | — |
| 1,000 | 71.3 | 29.9 | 38.8 | 16.0 | 15.0 | 15.0 | 14.0 | 14.0 | 15.0 | 15.0 | — | — | — | — | — | — | — |
| 10,000 | 71.3 | 28.9 | 38.8 | 15.0 | 14.1 | 14.1 | 12.9 | 12.9 | 14.1 | 14.0 | — | — | — | — | — | — | — |
Median correct digits over the inputs every library completed at that N (hover a cell for the range), each capped at what its format holds; "exact" when every one of them is exact. k/n: the library completed k of n inputs and the rest reverted; rev: every input reverted. —: no model for this scenario. BL127Lib equals BL127 and is left out.
The inputs and the ops
| input | parameters | why |
|---|---|---|
| reference | x0 = 1.5 | 1.5 is representable in every format, so a perfect library returns it exactly |
| hundredth | x0 = 0.01 | ln is large and negative |
| tenth | x0 = 0.1 | a typical price ratio |
| near-one-below | x0 = 0.7 | ln is small: cancellation territory |
| just-above-one | x0 = 1.0001 | ln is tiny: the log1p regime |
| two | x0 = 2 | the simplest non-trivial value |
| ten | x0 = 10 | a round decade |
| thousand | x0 = 1000 | three decades |
| million | x0 = 1000000 | six decades, near ABDK's comfortable range |
| awkward | x0 = 123456.789 | a value with no special structure |
Library calls per step: BL19 ln, exp; Quad ln, exp; BL127 ln, exp; 64.64 ln, exp; Solady lnWad, expWad; Solmate wadLn, wadExp; PRB SD ln, exp; PRB UD ln, exp; snek wad_ln, wad_exp; Balancer ln, exp; OZ unsupported; Uniswap unsupported; Maker unsupported; Aave unsupported; Morpho unsupported; Frax unsupported; Euler unsupported; BL127Lib ln, exp. Parameters reach each adapter floored into its representation on the grids and rounded to nearest on the floats (ladder-inputs.json).
The reference input, step by step: x0 = 1.5
Correct digits against the exact truth at each N, capped at what the format holds. Hover a cell for the value itself, the digits against the format-rounded truth, the error in units of the last place and the gas per step.
| Floating point | Fixed point | ||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| steps N | BL19 | Quad | BL127 | 64.64 | Solady | Solmate | PRB SD | PRB UD | snek | Balancer | OZ | Uniswap | Maker | Aave | Morpho | Frax | Euler |
| 1 | exact | 33.5 | 38.7 | 19.1 | exact | exact | 16.9 | 16.9 | exact | 17.8 | — | — | — | — | — | — | — |
| 2 | exact | 33.2 | 38.7 | 18.8 | exact | exact | 16.6 | 16.6 | exact | 17.5 | — | — | — | — | — | — | — |
| 5 | exact | 32.8 | 38.7 | 18.3 | exact | exact | 16.2 | 16.2 | exact | 17.2 | — | — | — | — | — | — | — |
| 10 | exact | 32.5 | 38.7 | 18.0 | exact | exact | 15.9 | 15.9 | exact | 16.9 | — | — | — | — | — | — | — |
| 20 | exact | 32.2 | 38.7 | 17.7 | exact | exact | 15.6 | 15.6 | exact | 16.6 | — | — | — | — | — | — | — |
| 50 | exact | 31.8 | 38.7 | 17.3 | exact | exact | 15.2 | 15.2 | exact | 16.2 | — | — | — | — | — | — | — |
| 100 | exact | 31.5 | 38.7 | 17.0 | exact | exact | 14.9 | 14.9 | exact | 15.9 | — | — | — | — | — | — | — |
| 365 | exact | 31.0 | 38.7 | 16.4 | exact | exact | 14.3 | 14.3 | exact | 15.4 | — | — | — | — | — | — | — |
| 1,000 | exact | 30.5 | 38.7 | 16.0 | exact | exact | 13.9 | 13.9 | exact | 14.9 | — | — | — | — | — | — | — |
| 10,000 | exact | 29.5 | 38.7 | 15.0 | exact | exact | 12.9 | 12.9 | exact | 13.9 | — | — | — | — | — | — | — |
Amortising loan
Step: b = b * (1 + r) - payment. Result: outstanding balance after N daily payments.
Subtracting nearly equal numbers. Every loan's term is past the ladder's end, so the balance stays positive on every cell; the term-10,001 loans retire one step past N = 10,000, where the balance is one payment and relative error is amplified thousands of times.
Over all 8 inputs
Median correct digits over the inputs every library with a result at that N completed, each capped at what its format holds at that magnitude (BL19 71.3, binary128 34.0, the fixed grids by their last place), so no line passes its format's precision. The WAD libraries are the gold lines, labelled once. BL127Lib coincides with BL127 and is not drawn; Aave, Morpho and Maker appear only on the accrual scenarios their models describe. Hover a point for the library, the range over the inputs and N.
| Floating point | Fixed point | ||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| steps N | BL19 | Quad | BL127 | 64.64 | Solady | Solmate | PRB SD | PRB UD | snek | Balancer | OZ | Uniswap | Maker | Aave | Morpho | Frax | Euler |
| 1 | 71.3 | 33.5 | 39.1 | 20.0 | 19.8 | 19.8 | 19.8 | 19.8 | 19.8 | 19.8 | 19.8 | 19.8 | — | — | — | — | — |
| 2 | 71.2 | 33.3 | 38.8 | 19.7 | 19.5 | 19.5 | 19.5 | 19.5 | 19.5 | 19.5 | 19.5 | 19.5 | — | — | — | — | — |
| 5 | 71.0 | 32.9 | 38.4 | 19.3 | 19.1 | 19.1 | 19.1 | 19.1 | 19.1 | 19.1 | 19.1 | 19.1 | — | — | — | — | — |
| 10 | 70.6 | 32.6 | 38.1 | 19.0 | 18.8 | 18.8 | 18.8 | 18.8 | 18.8 | 18.8 | 18.8 | 18.8 | — | — | — | — | — |
| 20 | 70.4 | 32.3 | 37.8 | 18.7 | 18.5 | 18.5 | 18.5 | 18.5 | 18.5 | 18.5 | 18.5 | 18.5 | — | — | — | — | — |
| 50 | 70.0 | 31.9 | 37.4 | 18.3 | 18.1 | 18.1 | 18.1 | 18.1 | 18.1 | 18.1 | 18.1 | 18.1 | — | — | — | — | — |
| 100 | 69.8 | 31.6 | 37.1 | 18.0 | 17.8 | 17.8 | 17.8 | 17.8 | 17.8 | 17.8 | 17.8 | 17.8 | — | — | — | — | — |
| 365 | 69.2 | 31.0 | 36.5 | 17.4 | 17.2 | 17.2 | 17.2 | 17.2 | 17.2 | 17.2 | 17.2 | 17.2 | — | — | — | — | — |
| 1,000 | 68.8 | 30.6 | 36.1 | 16.9 | 16.8 | 16.8 | 16.8 | 16.8 | 16.8 | 16.8 | 16.8 | 16.8 | — | — | — | — | — |
| 10,000 | 64.6 | 25.7 | 31.2 | 12.0 | 11.9 | 11.9 | 11.9 | 11.9 | 11.9 | 11.9 | 11.9 | 11.9 | — | — | — | — | — |
| Floating point | Fixed point | ||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| steps N | BL19 | Quad | BL127 | 64.64 | Solady | Solmate | PRB SD | PRB UD | snek | Balancer | OZ | Uniswap | Maker | Aave | Morpho | Frax | Euler |
| 1 | 71.3 | 33.5 | 44.0 | 24.7 | 23.4 | 23.4 | 23.4 | 23.4 | 23.4 | 23.4 | 23.4 | 23.4 | — | — | — | — | — |
| 2 | 71.2 | 33.3 | 44.0 | 24.7 | 23.4 | 23.4 | 23.4 | 23.4 | 23.4 | 23.4 | 23.4 | 23.4 | — | — | — | — | — |
| 5 | 71.0 | 32.9 | 43.6 | 24.3 | 23.2 | 23.2 | 23.2 | 23.2 | 23.2 | 23.2 | 23.2 | 23.2 | — | — | — | — | — |
| 10 | 70.6 | 32.6 | 43.3 | 24.0 | 22.9 | 22.9 | 22.9 | 22.9 | 22.9 | 22.9 | 22.9 | 22.9 | — | — | — | — | — |
| 20 | 70.4 | 32.3 | 43.0 | 23.7 | 22.5 | 22.5 | 22.5 | 22.5 | 22.5 | 22.5 | 22.5 | 22.5 | — | — | — | — | — |
| 50 | 70.0 | 31.9 | 42.6 | 23.2 | 22.1 | 22.1 | 22.1 | 22.1 | 22.1 | 22.1 | 22.1 | 22.1 | — | — | — | — | — |
| 100 | 69.8 | 31.6 | 42.3 | 23.0 | 21.7 | 21.7 | 21.7 | 21.7 | 21.7 | 21.7 | 21.7 | 21.7 | — | — | — | — | — |
| 365 | 69.2 | 31.0 | 41.7 | 22.4 | 21.1 | 21.1 | 21.1 | 21.1 | 21.1 | 21.1 | 21.1 | 21.1 | — | — | — | — | — |
| 1,000 | 68.8 | 30.6 | 41.2 | 21.9 | 20.6 | 20.6 | 20.6 | 20.6 | 20.6 | 20.6 | 20.6 | 20.6 | — | — | — | — | — |
| 10,000 | 64.6 | 25.7 | 36.1 | 16.8 | 15.6 | 15.6 | 15.6 | 15.6 | 15.6 | 15.6 | 15.6 | 15.6 | — | — | — | — | — |
Median correct digits over the inputs every library completed at that N (hover a cell for the range), each capped at what its format holds; "exact" when every one of them is exact. k/n: the library completed k of n inputs and the rest reverted; rev: every input reverted. —: no model for this scenario. BL127Lib equals BL127 and is left out.
The inputs and the ops
| input | parameters | why |
|---|---|---|
| reference | principal = 300000, rate = 0.05/365, term = 10001; payment = principal * rate / (1 - (1 + rate)^(-term)) | a mortgage-sized loan retiring one step past the ladder's end, so N = 10,000 is the one-payment cell |
| small | principal = 10000, rate = 0.05/365, term = 10001; payment = principal * rate / (1 - (1 + rate)^(-term)) | a small loan |
| high-rate | principal = 300000, rate = 0.1/365, term = 10001; payment = principal * rate / (1 - (1 + rate)^(-term)) | double the rate |
| thirty-year | principal = 300000, rate = 0.05/365, term = 10950; payment = principal * rate / (1 - (1 + rate)^(-term)) | a thirty-year mortgage paid daily: at N = 10,000, 950 payments remain |
| large-low | principal = 1000000, rate = 0.03/365, term = 10001; payment = principal * rate / (1 - (1 + rate)^(-term)) | a large loan at a low rate |
| very-high | principal = 300000, rate = 0.2/365, term = 10001; payment = principal * rate / (1 - (1 + rate)^(-term)) | 20% APR: the payment is barely above the interest |
| micro | principal = 500, rate = 0.05/365, term = 10001; payment = principal * rate / (1 - (1 + rate)^(-term)) | a tiny loan: the payment is nine hundredths of a unit |
| century | principal = 300000, rate = 0.05/365, term = 36500; payment = principal * rate / (1 - (1 + rate)^(-term)) | a hundred-year term: at N = 10,000 most of the balance remains |
Library calls per step: BL19 mul, sub; Quad mul, sub; BL127 mul, sub; 64.64 mul, sub; Solady sMulWad, sub; Solmate wadMul, sub; PRB SD mul, sub; PRB UD mul, sub; snek mul_div(a, b, 1e18), sub; Balancer mulDown, sub; OZ mulDiv(a, b, 1e18), sub; Uniswap mulDiv(a, b, 1e18), sub; Maker unsupported; Aave unsupported; Morpho unsupported; Frax unsupported; Euler unsupported; BL127Lib mul, sub. Parameters reach each adapter floored into its representation on the grids and rounded to nearest on the floats (ladder-inputs.json).
The reference input, step by step: principal = 300000, rate = 0.05/365, term = 10001
Correct digits against the exact truth at each N, capped at what the format holds. Hover a cell for the value itself, the digits against the format-rounded truth, the error in units of the last place and the gas per step.
| Floating point | Fixed point | ||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| steps N | BL19 | Quad | BL127 | 64.64 | Solady | Solmate | PRB SD | PRB UD | snek | Balancer | OZ | Uniswap | Maker | Aave | Morpho | Frax | Euler |
| 1 | 71.1 | 33.5 | 39.1 | 20.0 | 19.8 | 19.8 | 19.8 | 19.8 | 19.8 | 19.8 | 19.8 | 19.8 | — | — | — | — | — |
| 2 | 70.8 | 33.4 | 38.8 | 19.7 | 19.5 | 19.5 | 19.5 | 19.5 | 19.5 | 19.5 | 19.5 | 19.5 | — | — | — | — | — |
| 5 | 70.4 | 33.0 | 38.4 | 19.3 | 19.1 | 19.1 | 19.1 | 19.1 | 19.1 | 19.1 | 19.1 | 19.1 | — | — | — | — | — |
| 10 | 70.2 | 32.7 | 38.1 | 19.0 | 18.8 | 18.8 | 18.8 | 18.8 | 18.8 | 18.8 | 18.8 | 18.8 | — | — | — | — | — |
| 20 | 69.9 | 32.4 | 37.8 | 18.7 | 18.5 | 18.5 | 18.5 | 18.5 | 18.5 | 18.5 | 18.5 | 18.5 | — | — | — | — | — |
| 50 | 69.6 | 31.9 | 37.4 | 18.3 | 18.1 | 18.1 | 18.1 | 18.1 | 18.1 | 18.1 | 18.1 | 18.1 | — | — | — | — | — |
| 100 | 69.3 | 31.6 | 37.1 | 18.0 | 17.8 | 17.8 | 17.8 | 17.8 | 17.8 | 17.8 | 17.8 | 17.8 | — | — | — | — | — |
| 365 | 68.8 | 31.1 | 36.5 | 17.4 | 17.2 | 17.2 | 17.2 | 17.2 | 17.2 | 17.2 | 17.2 | 17.2 | — | — | — | — | — |
| 1,000 | 68.3 | 30.6 | 36.1 | 16.9 | 16.8 | 16.8 | 16.8 | 16.8 | 16.8 | 16.8 | 16.8 | 16.8 | — | — | — | — | — |
| 10,000 | 63.8 | 25.7 | 31.2 | 12.0 | 11.9 | 11.9 | 11.9 | 11.9 | 11.9 | 11.9 | 11.9 | 11.9 | — | — | — | — | — |
Running geometric mean
Step: L += ln(x_i); g = exp(L / N), x_i = (i + 2) / (i + 1). Result: geometric mean of N terms; truth telescopes to ((N + 2) / 2)^(1 / N).
Index and basket maths: a sum of logs, one division, one exp. The division by N and the final exp expose every accumulated ULP.
Over all 1 input
Median correct digits over the inputs every library with a result at that N completed, each capped at what its format holds at that magnitude (BL19 71.3, binary128 34.0, the fixed grids by their last place), so no line passes its format's precision. The WAD libraries are the gold lines, labelled once. BL127Lib coincides with BL127 and is not drawn; Aave, Morpho and Maker appear only on the accrual scenarios their models describe. Hover a point for the library, the range over the inputs and N.
| Floating point | Fixed point | ||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| steps N | BL19 | Quad | BL127 | 64.64 | Solady | Solmate | PRB SD | PRB UD | snek | Balancer | OZ | Uniswap | Maker | Aave | Morpho | Frax | Euler |
| 1 | exact | 33.5 | 38.7 | 19.1 | exact | exact | 16.9 | 16.9 | exact | 17.8 | — | — | — | — | — | — | — |
| 2 | 71.3 | 33.6 | 38.5 | 18.9 | 17.8 | 17.8 | 16.9 | 16.9 | 17.8 | 17.8 | — | — | — | — | — | — | — |
| 5 | 71.3 | 33.4 | 38.6 | 19.0 | 17.8 | 17.8 | 16.9 | 16.9 | 17.8 | 17.8 | — | — | — | — | — | — | — |
| 10 | 71.3 | 33.5 | 38.5 | 18.7 | 17.8 | 17.8 | 16.9 | 16.9 | 17.8 | 17.8 | — | — | — | — | — | — | — |
| 20 | 71.3 | 33.5 | 38.5 | 18.9 | 17.7 | 17.7 | 16.9 | 16.9 | 17.7 | 17.7 | — | — | — | — | — | — | — |
| 50 | 71.2 | 33.5 | 38.5 | 18.9 | 17.8 | 17.8 | 16.9 | 16.9 | 17.8 | 17.8 | — | — | — | — | — | — | — |
| 100 | 71.3 | 33.4 | 38.5 | 18.8 | 17.7 | 17.7 | 16.9 | 16.9 | 17.7 | 17.7 | — | — | — | — | — | — | — |
| 365 | 71.3 | 33.2 | 38.4 | 18.9 | 17.6 | 17.6 | 16.9 | 16.9 | 17.6 | 17.6 | — | — | — | — | — | — | — |
| 1,000 | 71.3 | 33.3 | 38.5 | 18.9 | 17.6 | 17.6 | 16.9 | 16.9 | 17.6 | 17.6 | — | — | — | — | — | — | — |
| 10,000 | 71.3 | 33.1 | 38.5 | 18.9 | 17.6 | 17.6 | 16.9 | 16.9 | 17.6 | 17.6 | — | — | — | — | — | — | — |
| Floating point | Fixed point | ||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| steps N | BL19 | Quad | BL127 | 64.64 | Solady | Solmate | PRB SD | PRB UD | snek | Balancer | OZ | Uniswap | Maker | Aave | Morpho | Frax | Euler |
| 1 | exact | 33.5 | 38.7 | 19.1 | exact | exact | 16.9 | 16.9 | exact | 17.8 | — | — | — | — | — | — | — |
| 2 | 71.3 | 33.6 | 38.5 | 18.9 | 17.8 | 17.8 | 16.9 | 16.9 | 17.8 | 17.8 | — | — | — | — | — | — | — |
| 5 | 71.3 | 33.4 | 38.6 | 19.0 | 17.8 | 17.8 | 16.9 | 16.9 | 17.8 | 17.8 | — | — | — | — | — | — | — |
| 10 | 71.3 | 33.5 | 38.5 | 18.7 | 17.8 | 17.8 | 16.9 | 16.9 | 17.8 | 17.8 | — | — | — | — | — | — | — |
| 20 | 71.3 | 33.5 | 38.5 | 18.9 | 17.7 | 17.7 | 16.9 | 16.9 | 17.7 | 17.7 | — | — | — | — | — | — | — |
| 50 | 71.2 | 33.5 | 38.5 | 18.9 | 17.8 | 17.8 | 16.9 | 16.9 | 17.8 | 17.8 | — | — | — | — | — | — | — |
| 100 | 71.3 | 33.4 | 38.5 | 18.8 | 17.7 | 17.7 | 16.9 | 16.9 | 17.7 | 17.7 | — | — | — | — | — | — | — |
| 365 | 71.3 | 33.2 | 38.4 | 18.9 | 17.6 | 17.6 | 16.9 | 16.9 | 17.6 | 17.6 | — | — | — | — | — | — | — |
| 1,000 | 71.3 | 33.3 | 38.5 | 18.9 | 17.6 | 17.6 | 16.9 | 16.9 | 17.6 | 17.6 | — | — | — | — | — | — | — |
| 10,000 | 71.3 | 33.1 | 38.5 | 18.9 | 17.6 | 17.6 | 16.9 | 16.9 | 17.6 | 17.6 | — | — | — | — | — | — | — |
Median correct digits over the inputs every library completed at that N (hover a cell for the range), each capped at what its format holds; "exact" when every one of them is exact. k/n: the library completed k of n inputs and the rest reverted; rev: every input reverted. —: no model for this scenario. BL127Lib equals BL127 and is left out.
The inputs and the ops
| input | parameters | why |
|---|---|---|
| reference | the scenario has no parameters; its inputs are the integers 1..N |
Library calls per step: BL19 div, ln, add, exp; Quad div, ln, add, exp; BL127 div, ln, add, exp; 64.64 div, ln, add, exp; Solady sDivWad, lnWad, add, expWad; Solmate wadDiv, wadLn, add, wadExp; PRB SD div, ln, add, exp; PRB UD div, ln, add, exp; snek mul_div(a, 1e18, b), wad_ln, add, wad_exp; Balancer divDown, ln, add, exp; OZ unsupported; Uniswap unsupported; Maker unsupported; Aave unsupported; Morpho unsupported; Frax unsupported; Euler unsupported; BL127Lib div, ln, add, exp. Parameters reach each adapter floored into its representation on the grids and rounded to nearest on the floats (ladder-inputs.json).
The reference input, step by step:
Correct digits against the exact truth at each N, capped at what the format holds. Hover a cell for the value itself, the digits against the format-rounded truth, the error in units of the last place and the gas per step.
| Floating point | Fixed point | ||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| steps N | BL19 | Quad | BL127 | 64.64 | Solady | Solmate | PRB SD | PRB UD | snek | Balancer | OZ | Uniswap | Maker | Aave | Morpho | Frax | Euler |
| 1 | exact | 33.5 | 38.7 | 19.1 | exact | exact | 16.9 | 16.9 | exact | 17.8 | — | — | — | — | — | — | — |
| 2 | 71.3 | 33.6 | 38.5 | 18.9 | 17.8 | 17.8 | 16.9 | 16.9 | 17.8 | 17.8 | — | — | — | — | — | — | — |
| 5 | 71.3 | 33.4 | 38.6 | 19.0 | 17.8 | 17.8 | 16.9 | 16.9 | 17.8 | 17.8 | — | — | — | — | — | — | — |
| 10 | 71.3 | 33.5 | 38.5 | 18.7 | 17.8 | 17.8 | 16.9 | 16.9 | 17.8 | 17.8 | — | — | — | — | — | — | — |
| 20 | 71.3 | 33.5 | 38.5 | 18.9 | 17.7 | 17.7 | 16.9 | 16.9 | 17.7 | 17.7 | — | — | — | — | — | — | — |
| 50 | 71.2 | 33.5 | 38.5 | 18.9 | 17.8 | 17.8 | 16.9 | 16.9 | 17.8 | 17.8 | — | — | — | — | — | — | — |
| 100 | 71.3 | 33.4 | 38.5 | 18.8 | 17.7 | 17.7 | 16.9 | 16.9 | 17.7 | 17.7 | — | — | — | — | — | — | — |
| 365 | 71.3 | 33.2 | 38.4 | 18.9 | 17.6 | 17.6 | 16.9 | 16.9 | 17.6 | 17.6 | — | — | — | — | — | — | — |
| 1,000 | 71.3 | 33.3 | 38.5 | 18.9 | 17.6 | 17.6 | 16.9 | 16.9 | 17.6 | 17.6 | — | — | — | — | — | — | — |
| 10,000 | 71.3 | 33.1 | 38.5 | 18.9 | 17.6 | 17.6 | 16.9 | 16.9 | 17.6 | 17.6 | — | — | — | — | — | — | — |
Black-Scholes d1 along a price path
Step: acc += d1(S); S += tick, with d1 = (ln(S / K) + (r + sigma^2 / 2) T) / (sigma sqrt(T)). Result: sum of d1 over N ticks.
The options-desk case: ln, div, sqrt and mul in one expression, re-evaluated as the spot moves and aggregated.
Over all 8 inputs
Median correct digits over the inputs every library with a result at that N completed, each capped at what its format holds at that magnitude (BL19 71.3, binary128 34.0, the fixed grids by their last place), so no line passes its format's precision. The WAD libraries are the gold lines, labelled once. BL127Lib coincides with BL127 and is not drawn; Aave, Morpho and Maker appear only on the accrual scenarios their models describe. Hover a point for the library, the range over the inputs and N.
| Floating point | Fixed point | ||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| steps N | BL19 | Quad | BL127 | 64.64 | Solady | Solmate | PRB SD | PRB UD | snek | Balancer | OZ | Uniswap | Maker | Aave | Morpho | Frax | Euler |
| 1 | 71.1 | 34.0 | 37.3 | 18.1 | 17.2 | 17.2 | 17.2 | 17.2 | 17.2 | 17.3 | — | — | — | — | — | — | — |
| 2 | 70.6 | 32.6 | 37.3 | 17.9 | 17.6 | 17.6 | 16.0 | 16.0 | 17.6 | 17.4 | — | — | — | — | — | — | — |
| 5 | 70.8 | 32.5 | 37.4 | 17.9 | 17.3 | 17.3 | 15.8 | 15.8 | 17.3 | 17.0 | — | — | — | — | — | — | — |
| 10 | 70.3 | 32.4 | 37.3 | 17.8 | 17.3 | 17.3 | 15.9 | 15.9 | 17.3 | 17.1 | — | — | — | — | — | — | — |
| 20 | 70.0 | 32.1 | 37.5 | 17.8 | 17.4 | 17.4 | 16.1 | 16.1 | 17.4 | 17.2 | — | — | — | — | — | — | — |
| 50 | 69.6 | 31.7 | 37.4 | 17.8 | 17.3 | 17.3 | 16.2 | 16.2 | 17.3 | 17.3 | — | — | — | — | — | — | — |
| 100 | 69.3 | 31.5 | 37.4 | 17.9 | 17.3 | 17.3 | 16.2 | 16.2 | 17.3 | 17.3 | — | — | — | — | — | — | — |
| 365 | 68.8 | 30.9 | 37.3 | 17.9 | 17.3 | 17.3 | 16.2 | 16.2 | 17.3 | 17.3 | — | — | — | — | — | — | — |
| 1,000 | 68.4 | 30.6 | 37.2 | 17.9 | 17.6 | 17.6 | 16.3 | 16.3 | 17.6 | 17.4 | — | — | — | — | — | — | — |
| 10,000 | 68.0 | 30.1 | 37.0 | 18.2 | 17.3 | 17.3 | 16.8 | 16.8 | 17.3 | 17.7 | — | — | — | — | — | — | — |
| Floating point | Fixed point | ||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| steps N | BL19 | Quad | BL127 | 64.64 | Solady | Solmate | PRB SD | PRB UD | snek | Balancer | OZ | Uniswap | Maker | Aave | Morpho | Frax | Euler |
| 1 | 71.2 | 34.0 | 37.3 | 18.6 | 17.2 | 17.2 | 17.2 | 17.2 | 17.2 | 17.3 | — | — | — | — | — | — | — |
| 2 | 70.6 | 32.6 | 37.3 | 18.1 | 17.6 | 17.6 | 16.0 | 16.0 | 17.6 | 17.4 | — | — | — | — | — | — | — |
| 5 | 70.8 | 32.5 | 37.4 | 18.0 | 17.3 | 17.3 | 15.8 | 15.8 | 17.3 | 17.0 | — | — | — | — | — | — | — |
| 10 | 70.3 | 32.4 | 37.7 | 18.1 | 17.3 | 17.3 | 15.9 | 15.9 | 17.3 | 17.1 | — | — | — | — | — | — | — |
| 20 | 70.0 | 32.1 | 37.7 | 18.1 | 17.4 | 17.4 | 16.1 | 16.1 | 17.4 | 17.2 | — | — | — | — | — | — | — |
| 50 | 69.6 | 31.7 | 37.9 | 18.1 | 17.3 | 17.3 | 16.2 | 16.2 | 17.3 | 17.3 | — | — | — | — | — | — | — |
| 100 | 69.3 | 31.5 | 38.0 | 18.1 | 17.3 | 17.3 | 16.2 | 16.2 | 17.3 | 17.3 | — | — | — | — | — | — | — |
| 365 | 68.8 | 30.9 | 37.7 | 18.2 | 17.3 | 17.3 | 16.2 | 16.2 | 17.3 | 17.3 | — | — | — | — | — | — | — |
| 1,000 | 68.4 | 30.6 | 38.1 | 18.3 | 17.6 | 17.6 | 16.3 | 16.3 | 17.6 | 17.4 | — | — | — | — | — | — | — |
| 10,000 | 68.0 | 30.1 | 38.2 | 18.9 | 17.3 | 17.3 | 16.8 | 16.8 | 17.3 | 17.7 | — | — | — | — | — | — | — |
Median correct digits over the inputs every library completed at that N (hover a cell for the range), each capped at what its format holds; "exact" when every one of them is exact. k/n: the library completed k of n inputs and the rest reverted; rev: every input reverted. —: no model for this scenario. BL127Lib equals BL127 and is left out.
The inputs and the ops
| input | parameters | why |
|---|---|---|
| reference | T = 0.5, r = 0.05, sigma = 0.2, spot = 100, strike = 100, tick = 0.01 | at the money, 20% vol, six months |
| low-vol | T = 0.5, r = 0.05, sigma = 0.05, spot = 100, strike = 100, tick = 0.01 | 5% vol: the denominator is small |
| high-vol | T = 0.5, r = 0.05, sigma = 0.8, spot = 100, strike = 100, tick = 0.01 | 80% vol |
| in-the-money | T = 0.5, r = 0.05, sigma = 0.2, spot = 120, strike = 100, tick = 0.01 | ln(S/K) is positive and not small |
| out-of-the-money | T = 0.5, r = 0.05, sigma = 0.2, spot = 80, strike = 100, tick = 0.01 | ln(S/K) is negative |
| short-dated | T = 0.01, r = 0.05, sigma = 0.2, spot = 100, strike = 100, tick = 0.01 | sqrt(T) is small |
| long-dated | T = 2, r = 0.05, sigma = 0.2, spot = 100, strike = 100, tick = 0.01 | two years |
| coarse-ticks | T = 0.5, r = 0.05, sigma = 0.2, spot = 100, strike = 100, tick = 1 | whole-unit ticks: S doubles by N = 100 and reaches 10,100 |
Library calls per step: BL19 div, ln, add, sqrt, mul; Quad div, ln, add, sqrt, mul; BL127 div, ln, add, sqrt, mul; 64.64 div, ln, add, sqrt, mul; Solady sDivWad, lnWad, add, sqrtWad, sMulWad; Solmate wadDiv, wadLn, add, sqrt(x 1e18), wadMul; PRB SD div, ln, add, sqrt, mul; PRB UD div, ln, add, sqrt, mul; snek mul_div(a, 1e18, b), wad_ln, add, isqrt(x 1e18) (Vyper built-in), mul_div(a, b, 1e18); Balancer divDown, ln, add, pow(x, 1/2), mulDown; OZ unsupported; Uniswap unsupported; Maker unsupported; Aave unsupported; Morpho unsupported; Frax unsupported; Euler unsupported; BL127Lib div, ln, add, sqrt, mul. Parameters reach each adapter floored into its representation on the grids and rounded to nearest on the floats (ladder-inputs.json).
The reference input, step by step: T = 0.5, r = 0.05, sigma = 0.2, spot = 100, strike = 100, tick = 0.01
Correct digits against the exact truth at each N, capped at what the format holds. Hover a cell for the value itself, the digits against the format-rounded truth, the error in units of the last place and the gas per step.
| Floating point | Fixed point | ||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| steps N | BL19 | Quad | BL127 | 64.64 | Solady | Solmate | PRB SD | PRB UD | snek | Balancer | OZ | Uniswap | Maker | Aave | Morpho | Frax | Euler |
| 1 | 71.0 | 34.0 | 37.1 | 18.1 | 17.2 | 17.2 | 17.2 | 17.2 | 17.2 | 17.3 | — | — | — | — | — | — | — |
| 2 | 70.6 | 32.5 | 37.0 | 17.7 | 17.6 | 17.6 | 16.0 | 16.0 | 17.6 | 17.0 | — | — | — | — | — | — | — |
| 5 | 70.1 | 32.1 | 37.0 | 17.6 | 17.1 | 17.1 | 15.7 | 15.7 | 17.1 | 16.8 | — | — | — | — | — | — | — |
| 10 | 69.7 | 31.9 | 36.9 | 17.5 | 17.1 | 17.1 | 15.6 | 15.6 | 17.1 | 16.8 | — | — | — | — | — | — | — |
| 20 | 69.4 | 31.6 | 36.9 | 17.5 | 17.1 | 17.1 | 15.6 | 15.6 | 17.1 | 16.8 | — | — | — | — | — | — | — |
| 50 | 69.0 | 31.2 | 36.9 | 17.5 | 17.0 | 17.0 | 15.6 | 15.6 | 17.0 | 16.7 | — | — | — | — | — | — | — |
| 100 | 68.7 | 30.9 | 36.9 | 17.5 | 17.0 | 17.0 | 15.6 | 15.6 | 17.0 | 16.8 | — | — | — | — | — | — | — |
| 365 | 68.3 | 30.5 | 36.8 | 17.6 | 17.3 | 17.3 | 15.7 | 15.7 | 17.3 | 16.9 | — | — | — | — | — | — | — |
| 1,000 | 68.1 | 30.3 | 36.8 | 17.8 | 18.1 | 18.1 | 15.9 | 15.9 | 18.1 | 17.1 | — | — | — | — | — | — | — |
| 10,000 | 67.9 | 30.0 | 36.9 | 18.1 | 17.3 | 17.3 | 16.8 | 16.8 | 17.3 | 17.6 | — | — | — | — | — | — | — |
Cumulative product of small factors
Step: p = p * (1 + eps_i), eps_i = +eps for odd i, -eps for even i. Result: product after N factors.
The general form of fee accrual, index levels and LP share accounting: many factors a basis point from one. The drift from 1 is where the digits are, and it is small.
Over all 5 inputs
Median correct digits over the inputs every library with a result at that N completed, each capped at what its format holds at that magnitude (BL19 71.3, binary128 34.0, the fixed grids by their last place), so no line passes its format's precision. The WAD libraries are the gold lines, labelled once. BL127Lib coincides with BL127 and is not drawn; Aave, Morpho and Maker appear only on the accrual scenarios their models describe. Hover a point for the library, the range over the inputs and N.
| Floating point | Fixed point | ||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| steps N | BL19 | Quad | BL127 | 64.64 | Solady | Solmate | PRB SD | PRB UD | snek | Balancer | OZ | Uniswap | Maker | Aave | Morpho | Frax | Euler |
| 1 | 71.3 | 34.0 | 38.5 | 19.2 | exact | exact | exact | exact | exact | exact | exact | exact | — | — | — | — | — |
| 2 | 71.3 | 33.8 | 38.5 | 19.2 | exact | exact | exact | exact | exact | exact | exact | exact | — | — | — | — | — |
| 5 | 71.1 | 33.2 | 38.1 | 18.9 | 18.0 | 18.0 | 18.0 | 18.0 | 18.0 | 18.0 | 18.0 | 18.0 | — | — | — | — | — |
| 10 | 71.3 | 32.9 | 37.9 | 18.6 | 17.9 | 17.9 | 17.9 | 17.9 | 17.9 | 17.9 | 17.9 | 17.9 | — | — | — | — | — |
| 20 | 70.8 | 32.6 | 37.5 | 18.3 | 17.1 | 17.1 | 17.1 | 17.1 | 17.1 | 17.1 | 17.1 | 17.1 | — | — | — | — | — |
| 50 | 70.7 | 32.2 | 37.1 | 17.8 | 16.6 | 16.6 | 16.6 | 16.6 | 16.6 | 16.6 | 16.6 | 16.6 | — | — | — | — | — |
| 100 | 70.3 | 31.8 | 36.8 | 17.5 | 16.3 | 16.3 | 16.3 | 16.3 | 16.3 | 16.3 | 16.3 | 16.3 | — | — | — | — | — |
| 365 | 69.9 | 31.3 | 36.2 | 16.9 | 15.7 | 15.7 | 15.7 | 15.7 | 15.7 | 15.7 | 15.7 | 15.7 | — | — | — | — | — |
| 1,000 | 69.9 | 30.9 | 35.8 | 16.5 | 15.2 | 15.2 | 15.2 | 15.2 | 15.2 | 15.2 | 15.2 | 15.2 | — | — | — | — | — |
| 10,000 | 69.0 | 29.9 | 34.8 | 15.5 | 14.2 | 14.2 | 14.2 | 14.2 | 14.2 | 14.2 | 14.2 | 14.2 | — | — | — | — | — |
| Floating point | Fixed point | ||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| steps N | BL19 | Quad | BL127 | 64.64 | Solady | Solmate | PRB SD | PRB UD | snek | Balancer | OZ | Uniswap | Maker | Aave | Morpho | Frax | Euler |
| 1 | 71.3 | 34.0 | 38.5 | 19.2 | exact | exact | exact | exact | exact | exact | exact | exact | — | — | — | — | — |
| 2 | 71.3 | 33.8 | 38.5 | 19.2 | exact | exact | exact | exact | exact | exact | exact | exact | — | — | — | — | — |
| 5 | 71.1 | 33.2 | 38.2 | 18.9 | 18.0 | 18.0 | 18.0 | 18.0 | 18.0 | 18.0 | 18.0 | 18.0 | — | — | — | — | — |
| 10 | 71.3 | 32.9 | 37.9 | 18.6 | 17.9 | 17.9 | 17.9 | 17.9 | 17.9 | 17.9 | 17.9 | 17.9 | — | — | — | — | — |
| 20 | 70.8 | 32.6 | 37.5 | 18.3 | 17.1 | 17.1 | 17.1 | 17.1 | 17.1 | 17.1 | 17.1 | 17.1 | — | — | — | — | — |
| 50 | 70.7 | 32.2 | 37.1 | 17.8 | 16.6 | 16.6 | 16.6 | 16.6 | 16.6 | 16.6 | 16.6 | 16.6 | — | — | — | — | — |
| 100 | 70.3 | 31.8 | 36.8 | 17.5 | 16.3 | 16.3 | 16.3 | 16.3 | 16.3 | 16.3 | 16.3 | 16.3 | — | — | — | — | — |
| 365 | 69.9 | 31.3 | 36.2 | 16.9 | 15.7 | 15.7 | 15.7 | 15.7 | 15.7 | 15.7 | 15.7 | 15.7 | — | — | — | — | — |
| 1,000 | 70.0 | 30.9 | 35.8 | 16.5 | 15.2 | 15.2 | 15.2 | 15.2 | 15.2 | 15.2 | 15.2 | 15.2 | — | — | — | — | — |
| 10,000 | 69.0 | 29.9 | 34.8 | 15.5 | 14.2 | 14.2 | 14.2 | 14.2 | 14.2 | 14.2 | 14.2 | 14.2 | — | — | — | — | — |
Median correct digits over the inputs every library completed at that N (hover a cell for the range), each capped at what its format holds; "exact" when every one of them is exact. k/n: the library completed k of n inputs and the rest reverted; rev: every input reverted. —: no model for this scenario. BL127Lib equals BL127 and is left out.
The inputs and the ops
| input | parameters | why |
|---|---|---|
| reference | eps = 0.0001 | a basis point |
| percent | eps = 0.01 | one percent |
| tenth-percent | eps = 0.001 | ten basis points |
| micro | eps = 0.000001 | a hundredth of a basis point: the factors are within WAD's last digits of one |
| five-percent | eps = 0.05 | large factors: the product falls to 4e-6 by N = 10,000 |
Library calls per step: BL19 mul; Quad mul; BL127 mul; 64.64 mul; Solady sMulWad; Solmate wadMul; PRB SD mul; PRB UD mul; snek mul_div(a, b, 1e18); Balancer mulDown; OZ mulDiv(a, b, 1e18); Uniswap mulDiv(a, b, 1e18); Maker unsupported; Aave unsupported; Morpho unsupported; Frax unsupported; Euler unsupported; BL127Lib mul. Parameters reach each adapter floored into its representation on the grids and rounded to nearest on the floats (ladder-inputs.json).
The reference input, step by step: eps = 0.0001
Correct digits against the exact truth at each N, capped at what the format holds. Hover a cell for the value itself, the digits against the format-rounded truth, the error in units of the last place and the gas per step.
| Floating point | Fixed point | ||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| steps N | BL19 | Quad | BL127 | 64.64 | Solady | Solmate | PRB SD | PRB UD | snek | Balancer | OZ | Uniswap | Maker | Aave | Morpho | Frax | Euler |
| 1 | 71.3 | 34.0 | 38.5 | 19.2 | exact | exact | exact | exact | exact | exact | exact | exact | — | — | — | — | — |
| 2 | 71.3 | 33.8 | 38.5 | 19.2 | exact | exact | exact | exact | exact | exact | exact | exact | — | — | — | — | — |
| 5 | 71.3 | 33.3 | 38.2 | 18.8 | 18.0 | 18.0 | 18.0 | 18.0 | 18.0 | 18.0 | 18.0 | 18.0 | — | — | — | — | — |
| 10 | 71.3 | 32.9 | 37.9 | 18.5 | 17.5 | 17.5 | 17.5 | 17.5 | 17.5 | 17.5 | 17.5 | 17.5 | — | — | — | — | — |
| 20 | 71.0 | 32.6 | 37.5 | 18.2 | 17.0 | 17.0 | 17.0 | 17.0 | 17.0 | 17.0 | 17.0 | 17.0 | — | — | — | — | — |
| 50 | 70.7 | 32.2 | 37.1 | 17.8 | 16.6 | 16.6 | 16.6 | 16.6 | 16.6 | 16.6 | 16.6 | 16.6 | — | — | — | — | — |
| 100 | 70.3 | 31.9 | 36.8 | 17.5 | 16.3 | 16.3 | 16.3 | 16.3 | 16.3 | 16.3 | 16.3 | 16.3 | — | — | — | — | — |
| 365 | 71.3 | 31.3 | 36.2 | 16.9 | 15.7 | 15.7 | 15.7 | 15.7 | 15.7 | 15.7 | 15.7 | 15.7 | — | — | — | — | — |
| 1,000 | 70.2 | 30.9 | 35.8 | 16.5 | 15.2 | 15.2 | 15.2 | 15.2 | 15.2 | 15.2 | 15.2 | 15.2 | — | — | — | — | — |
| 10,000 | 70.6 | 29.9 | 34.8 | 15.5 | 14.2 | 14.2 | 14.2 | 14.2 | 14.2 | 14.2 | 14.2 | 14.2 | — | — | — | — | — |
Annual compounding at 10% for 10,000 years
Step: b = b * 1.1. Result: balance after N years.
Ten thousand years of annual compounding grows $10,000 to about 10^418, past every fixed-point word: at 10% 64.64 overflows by N = 365, Solady, Balancer, Maker and BL127 by N = 1,000 and PRBMath by N = 10,000 (at 50%, 64.64 by N = 100 and the rest by N = 365); only binary128 and BL19 reach N = 10,000. Until about N = 20 the balances are short decimals that WAD and RAY hold exactly. The row began as a check of an old README claim ($25,937.42 true against $25,932.38 for Solady at N = 10); Solady returns $25,937.424601 exactly.
Over all 5 inputs
Median correct digits over the inputs every library with a result at that N completed, each capped at what its format holds at that magnitude (BL19 71.3, binary128 34.0, the fixed grids by their last place), so no line passes its format's precision. The WAD libraries are the gold lines, labelled once. BL127Lib coincides with BL127 and is not drawn; Aave, Morpho and Maker appear only on the accrual scenarios their models describe. Hover a point for the library, the range over the inputs and N.
| Floating point | Fixed point | ||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| steps N | BL19 | Quad | BL127 | 64.64 | Solady | Solmate | PRB SD | PRB UD | snek | Balancer | OZ | Uniswap | Maker | Aave | Morpho | Frax | Euler |
| 1 | 71.3 | 33.8 | 38.7 | 19.5 | exact | exact | exact | exact | exact | exact | exact | exact | exact | — | — | — | — |
| 2 | 71.3 | 33.4 | 38.4 | 19.2 | exact | exact | exact | exact | exact | exact | exact | exact | exact | — | — | — | — |
| 5 | 70.9 | 33.0 | 38.0 | 18.8 | exact | exact | exact | exact | exact | exact | exact | exact | exact | — | — | — | — |
| 10 | 70.5 | 32.7 | 37.7 | 18.5 | exact | exact | exact | exact | exact | exact | exact | exact | exact | — | — | — | — |
| 20 | 70.2 | 32.4 | 37.4 | 18.2 | 22.8 | 22.8 | 22.8 | 22.8 | 22.8 | 22.8 | 22.8 | 22.8 | 31.8 | — | — | — | — |
| 50 | 69.7 | 32.0 | 37.0 | 17.8 | 22.3 | 22.3 | 22.3 | 22.3 | 22.3 | 22.3 | 22.3 | 22.3 | 29.5 | — | — | — | — |
| 100 | 69.4 | 31.7 | 36.7 | 17.4 | 21.8 | 21.8 | 21.8 | 21.8 | 21.8 | 21.8 | 21.8 | 21.8 | 29.2 | — | — | — | — |
| 365 | 69.0 | 31.1 | 36.1 | 16.8 | 19.8 | 19.8 | 19.8 | 19.8 | 19.8 | 19.8 | 19.8 | 19.8 | 27.4 | — | — | — | — |
| 1,000 | 68.7 | 30.6 | 35.6 | 21.3 | 21.3 | 21.3 | 21.3 | 21.3 | 21.3 | 21.3 | 21.3 | — | — | — | — | ||
| 10,000 | 67.4 | 29.7 | — | — | — | — | |||||||||||
| Floating point | Fixed point | ||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| steps N | BL19 | Quad | BL127 | 64.64 | Solady | Solmate | PRB SD | PRB UD | snek | Balancer | OZ | Uniswap | Maker | Aave | Morpho | Frax | Euler |
| 1 | 71.3 | 33.8 | 42.5 | 23.3 | exact | exact | exact | exact | exact | exact | exact | exact | exact | — | — | — | — |
| 2 | 71.3 | 33.4 | 42.6 | 23.3 | exact | exact | exact | exact | exact | exact | exact | exact | exact | — | — | — | — |
| 5 | 70.9 | 33.0 | 42.7 | 23.4 | exact | exact | exact | exact | exact | exact | exact | exact | exact | — | — | — | — |
| 10 | 70.5 | 32.7 | 42.3 | 23.0 | exact | exact | exact | exact | exact | exact | exact | exact | exact | — | — | — | — |
| 20 | 70.2 | 32.4 | 42.0 | 22.8 | 22.8 | 22.8 | 22.8 | 22.8 | 22.8 | 22.8 | 22.8 | 22.8 | 31.8 | — | — | — | — |
| 50 | 69.8 | 32.0 | 41.9 | 22.7 | 22.3 | 22.3 | 22.3 | 22.3 | 22.3 | 22.3 | 22.3 | 22.3 | 29.5 | — | — | — | — |
| 100 | 69.5 | 31.7 | 41.8 | 22.5 | 21.8 | 21.8 | 21.8 | 21.8 | 21.8 | 21.8 | 21.8 | 21.8 | 29.2 | — | — | — | — |
| 365 | 69.0 | 31.1 | 39.7 | 20.4 | 19.8 | 19.8 | 19.8 | 19.8 | 19.8 | 19.8 | 19.8 | 19.8 | 27.4 | — | — | — | — |
| 1,000 | 68.8 | 30.6 | 41.6 | 21.3 | 21.3 | 21.3 | 21.3 | 21.3 | 21.3 | 21.3 | 21.3 | — | — | — | — | ||
| 10,000 | 67.5 | 29.7 | — | — | — | — | |||||||||||
| Floating point | Fixed point | ||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| steps N | BL19 | Quad | BL127 | 64.64 | Solady | Solmate | PRB SD | PRB UD | snek | Balancer | OZ | Uniswap | Maker | Aave | Morpho | Frax | Euler |
| 1 | 70.3 | 32.8 | 37.7 | 18.4 | 21.0 | 21.0 | 21.0 | 21.0 | 21.0 | 21.0 | 21.0 | 21.0 | 30.0 | — | — | — | — |
| 2 | 70.5 | 32.7 | 37.7 | 18.4 | 21.3 | 21.3 | 21.3 | 21.3 | 21.3 | 21.3 | 21.3 | 21.3 | 30.3 | — | — | — | — |
| 5 | 70.5 | 32.6 | 37.6 | 18.4 | 21.7 | 21.7 | 21.7 | 21.7 | 21.7 | 21.7 | 21.7 | 21.7 | 30.7 | — | — | — | — |
| 10 | 70.3 | 32.5 | 37.5 | 18.3 | 22.2 | 22.2 | 22.2 | 22.2 | 22.2 | 22.2 | 22.2 | 22.2 | 31.2 | — | — | — | — |
| 20 | 70.1 | 32.3 | 37.4 | 18.1 | 22.7 | 22.7 | 22.7 | 22.7 | 22.7 | 22.7 | 22.7 | 22.7 | 31.7 | — | — | — | — |
| 50 | 69.7 | 32.0 | 37.0 | 17.8 | 22.3 | 22.3 | 22.3 | 22.3 | 22.3 | 22.3 | 22.3 | 22.3 | 29.5 | — | — | — | — |
| 100 | 69.4 | 31.7 | 36.7 | 17.4 | 21.8 | 21.8 | 21.8 | 21.8 | 21.8 | 21.8 | 21.8 | 21.8 | 29.2 | — | — | — | — |
| 365 | 69.0 | 31.1 | 36.1 | 16.8 | 19.8 | 19.8 | 19.8 | 19.8 | 19.8 | 19.8 | 19.8 | 19.8 | 27.4 | — | — | — | — |
| 1,000 | 68.7 | 30.6 | 35.6 | 21.3 | 21.3 | 21.3 | 21.3 | 21.3 | 21.3 | 21.3 | 21.3 | — | — | — | — | ||
| 10,000 | 67.4 | 29.7 | — | — | — | — | |||||||||||
Median correct digits over the inputs every library completed at that N (hover a cell for the range), each capped at what its format holds; "exact" when every one of them is exact. k/n: the library completed k of n inputs and the rest reverted; rev: every input reverted. —: no model for this scenario. BL127Lib equals BL127 and is left out.
The inputs and the ops
| input | parameters | why |
|---|---|---|
| reference | principal = 10000, rate = 0.1 | the README claim |
| five-pct | principal = 10000, rate = 0.05 | 5% a year |
| unit | principal = 1, rate = 0.1 | one unit |
| million | principal = 1000000, rate = 0.1 | a million units: ABDK overflows sooner |
| fifty-pct | principal = 10000, rate = 0.5 | 50% a year: 64.64 overflows by N = 100; the WAD libraries, Maker and BL127 by N = 365; binary128 and BL19 reach 10,000 |
Library calls per step: BL19 mul; Quad mul; BL127 mul; 64.64 mul; Solady sMulWad; Solmate wadMul; PRB SD mul; PRB UD mul; snek mul_div(a, b, 1e18); Balancer mulDown; OZ mulDiv(a, b, 1e18); Uniswap mulDiv(a, b, 1e18); Maker rpow, rmul; Aave unsupported; Morpho unsupported; Frax unsupported; Euler unsupported; BL127Lib mul. Parameters reach each adapter floored into its representation on the grids and rounded to nearest on the floats (ladder-inputs.json).
The reference input, step by step: principal = 10000, rate = 0.1
Correct digits against the exact truth at each N, capped at what the format holds. Hover a cell for the value itself, the digits against the format-rounded truth, of the interest, the error in units of the last place and the gas per step.
| Floating point | Fixed point | ||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| steps N | BL19 | Quad | BL127 | 64.64 | Solady | Solmate | PRB SD | PRB UD | snek | Balancer | OZ | Uniswap | Maker | Aave | Morpho | Frax | Euler |
| 1 | exact | 33.8 | 38.7 | 19.5 | exact | exact | exact | exact | exact | exact | exact | exact | exact | — | — | — | — |
| 2 | 71.2 | 33.5 | 38.4 | 19.2 | exact | exact | exact | exact | exact | exact | exact | exact | exact | — | — | — | — |
| 5 | 70.7 | 33.1 | 38.0 | 18.8 | exact | exact | exact | exact | exact | exact | exact | exact | exact | — | — | — | — |
| 10 | 70.5 | 32.7 | 37.7 | 18.5 | exact | exact | exact | exact | exact | exact | exact | exact | exact | — | — | — | — |
| 20 | 70.1 | 32.4 | 37.4 | 18.2 | exact | exact | exact | exact | exact | exact | exact | exact | exact | — | — | — | — |
| 50 | 69.7 | 32.0 | 37.0 | 17.8 | 22.3 | 22.3 | 22.3 | 22.3 | 22.3 | 22.3 | 22.3 | 22.3 | 29.5 | — | — | — | — |
| 100 | 69.4 | 31.7 | 36.7 | 17.5 | 22.3 | 22.3 | 22.3 | 22.3 | 22.3 | 22.3 | 22.3 | 22.3 | 29.2 | — | — | — | — |
| 365 | 68.9 | 31.2 | 36.2 | reverts | 22.3 | 22.3 | 22.3 | 22.3 | 22.3 | 22.3 | 22.3 | 22.3 | 28.2 | — | — | — | — |
| 1,000 | 68.4 | 30.7 | reverts | reverts | reverts | reverts | 22.3 | 22.3 | 22.3 | reverts | 22.3 | 22.3 | reverts | — | — | — | — |
| 10,000 | 67.4 | 29.7 | reverts | reverts | reverts | reverts | reverts | reverts | reverts | reverts | reverts | reverts | reverts | — | — | — | — |
Revert reasons
- 64.64: bare revert (require without a reason, or out of gas) 0x00000000
- BL127: Overflow() 0x35278d12
- Solady: Solady SMulWadFailed() 0xedcd4dd4
- Solmate: bare revert (require without a reason, or out of gas) 0x00000000
- Balancer: Panic (checked arithmetic overflow or division by zero) 0x4e487b71
- Maker: Solady RPowOverflow() (Maker's rpow) 0x49f7642b
- PRB SD: PRBMath_SD59x18_Mul_Overflow 0x120b5b43
- PRB UD: Overflow() 0x35278d12
- snek: Overflow() 0x35278d12
- OZ: Overflow() 0x35278d12
- Uniswap: Overflow() 0x35278d12
Per-second accrual
Step: b = b0 * (1 + r/31536000)^(N * 86400). Result: balance after N days of per-second compounding.
How Maker's jug and pot accrue: the rate per second, compounded every second, N days at a time. The rate is 1.6e-9 at 5% APR, which an 18-decimal grid holds to ten digits before any arithmetic; BL127 and BL19 compute the power with compound, which never forms a rounded 1 + r; the WAD and 64.64 libraries as exp(n ln(1 + r)), Maker as rpow.
Over all 6 inputs
Median correct digits over the inputs every library with a result at that N completed, each capped at what its format holds at that magnitude (BL19 71.3, binary128 34.0, the fixed grids by their last place), so no line passes its format's precision. The WAD libraries are the gold lines, labelled once. BL127Lib coincides with BL127 and is not drawn; Aave, Morpho and Maker appear only on the accrual scenarios their models describe. Hover a point for the library, the range over the inputs and N.
| Floating point | Fixed point | ||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| steps N | BL19 | Quad | BL127 | 64.64 | Solady | Solmate | PRB SD | PRB UD | snek | Balancer | OZ | Uniswap | Maker | Aave | Morpho | Frax | Euler |
| 1 | 71.3 | 28.8 | 33.8 | 14.1 | 13.0 | 13.0 | 12.0 | 12.0 | 13.0 | 13.4 | — | — | 22.3 | — | — | — | — |
| 2 | 71.3 | 28.6 | 33.5 | 13.8 | 12.6 | 12.6 | 11.7 | 11.7 | 12.6 | 13.1 | — | — | 22.0 | — | — | — | — |
| 5 | 71.3 | 28.2 | 33.1 | 13.4 | 12.2 | 12.2 | 11.3 | 11.3 | 12.2 | 12.7 | — | — | 21.6 | — | — | — | — |
| 10 | 71.3 | 27.8 | 32.8 | 13.1 | 12.0 | 12.0 | 11.0 | 11.0 | 12.0 | 12.4 | — | — | 21.3 | — | — | — | — |
| 20 | 71.3 | 27.6 | 32.5 | 12.8 | 11.6 | 11.6 | 10.7 | 10.7 | 11.6 | 12.1 | — | — | 21.0 | — | — | — | — |
| 50 | 71.3 | 27.2 | 32.1 | 12.4 | 11.2 | 11.2 | 10.3 | 10.3 | 11.2 | 11.7 | — | — | 20.6 | — | — | — | — |
| 100 | 71.3 | 26.8 | 31.8 | 12.1 | 11.0 | 11.0 | 10.0 | 10.0 | 11.0 | 11.4 | — | — | 20.3 | — | — | — | — |
| 365 | 71.3 | 26.2 | 31.3 | 11.5 | 10.4 | 10.4 | 9.5 | 9.5 | 10.4 | 10.9 | — | — | 19.8 | — | — | — | — |
| 1,000 | 71.3 | 25.8 | 30.8 | 11.1 | 10.0 | 10.0 | 9.0 | 9.0 | 10.0 | 10.4 | — | — | 19.3 | — | — | — | — |
| 10,000 | 71.2 | 24.8 | 29.8 | 10.1 | 9.0 | 9.0 | 8.0 | 8.0 | 9.0 | 9.4 | — | — | 18.3 | — | — | — | — |
| Floating point | Fixed point | ||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| steps N | BL19 | Quad | BL127 | 64.64 | Solady | Solmate | PRB SD | PRB UD | snek | Balancer | OZ | Uniswap | Maker | Aave | Morpho | Frax | Euler |
| 1 | 71.3 | 28.8 | 39.0 | 14.4 | 13.1 | 13.1 | 12.1 | 12.1 | 13.1 | 18.0 | — | — | 22.7 | — | — | — | — |
| 2 | 71.3 | 28.6 | 38.8 | 14.1 | 12.8 | 12.8 | 11.8 | 11.8 | 12.8 | 17.8 | — | — | 22.4 | — | — | — | — |
| 5 | 71.3 | 28.2 | 39.2 | 13.7 | 12.4 | 12.4 | 11.4 | 11.4 | 12.4 | 18.0 | — | — | 22.0 | — | — | — | — |
| 10 | 71.3 | 27.8 | 39.0 | 13.4 | 12.1 | 12.1 | 11.1 | 11.1 | 12.1 | 18.0 | — | — | 21.7 | — | — | — | — |
| 20 | 71.3 | 27.6 | 38.8 | 13.1 | 11.8 | 11.8 | 10.8 | 10.8 | 11.8 | 18.0 | — | — | 21.4 | — | — | — | — |
| 50 | 71.3 | 27.2 | 39.0 | 12.7 | 11.4 | 11.4 | 10.4 | 10.4 | 11.4 | 18.0 | — | — | 21.0 | — | — | — | — |
| 100 | 71.3 | 26.8 | 39.2 | 12.4 | 11.1 | 11.1 | 10.1 | 10.1 | 11.1 | 18.0 | — | — | 20.7 | — | — | — | — |
| 365 | 71.3 | 26.2 | 39.4 | 11.8 | 10.6 | 10.6 | 9.5 | 9.5 | 10.6 | 18.0 | — | — | 20.2 | — | — | — | — |
| 1,000 | 71.3 | 25.8 | 39.0 | 11.4 | 10.1 | 10.1 | 9.1 | 9.1 | 10.1 | 18.1 | — | — | 19.7 | — | — | — | — |
| 10,000 | 71.3 | 24.8 | 40.0 | 10.4 | 9.1 | 9.1 | 8.1 | 8.1 | 9.1 | 18.3 | — | — | 18.7 | — | — | — | — |
| Floating point | Fixed point | ||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| steps N | BL19 | Quad | BL127 | 64.64 | Solady | Solmate | PRB SD | PRB UD | snek | Balancer | OZ | Uniswap | Maker | Aave | Morpho | Frax | Euler |
| 1 | 67.4 | 24.9 | 30.0 | 10.2 | 9.2 | 9.2 | 8.2 | 8.2 | 9.2 | 9.9 | — | — | 18.6 | — | — | — | — |
| 2 | 67.7 | 24.9 | 30.0 | 10.2 | 9.2 | 9.2 | 8.2 | 8.2 | 9.2 | 9.9 | — | — | 18.6 | — | — | — | — |
| 5 | 68.1 | 24.9 | 30.0 | 10.2 | 9.2 | 9.2 | 8.2 | 8.2 | 9.2 | 9.9 | — | — | 18.6 | — | — | — | — |
| 10 | 68.4 | 24.9 | 30.0 | 10.2 | 9.2 | 9.2 | 8.2 | 8.2 | 9.2 | 9.9 | — | — | 18.6 | — | — | — | — |
| 20 | 68.7 | 24.9 | 30.0 | 10.2 | 9.2 | 9.2 | 8.2 | 8.2 | 9.2 | 9.9 | — | — | 18.6 | — | — | — | — |
| 50 | 69.1 | 24.9 | 30.0 | 10.2 | 9.2 | 9.2 | 8.2 | 8.2 | 9.2 | 9.9 | — | — | 18.6 | — | — | — | — |
| 100 | 69.4 | 24.9 | 30.0 | 10.2 | 9.2 | 9.2 | 8.2 | 8.2 | 9.2 | 9.9 | — | — | 18.6 | — | — | — | — |
| 365 | 70.0 | 24.9 | 30.0 | 10.2 | 9.2 | 9.2 | 8.2 | 8.2 | 9.2 | 9.9 | — | — | 18.6 | — | — | — | — |
| 1,000 | 70.4 | 24.9 | 29.9 | 10.2 | 9.2 | 9.2 | 8.2 | 8.2 | 9.2 | 9.8 | — | — | 18.6 | — | — | — | — |
| 10,000 | 71.1 | 24.7 | 29.7 | 10.0 | 8.9 | 8.9 | 7.9 | 7.9 | 8.9 | 9.4 | — | — | 18.2 | — | — | — | — |
Median correct digits over the inputs every library completed at that N (hover a cell for the range), each capped at what its format holds; "exact" when every one of them is exact. k/n: the library completed k of n inputs and the rest reverted; rev: every input reverted. —: no model for this scenario. BL127Lib equals BL127 and is left out.
The inputs and the ops
| input | parameters | why |
|---|---|---|
| reference | principal = 10000, rateSec = 0.05/31536000 | $10,000 at 5% APR, the lending protocol's steady state |
| one-pct | principal = 10000, rateSec = 0.01/31536000 | a slow rate: 1% APR is 3.2e-10 a second |
| twenty-pct | principal = 10000, rateSec = 0.2/31536000 | 20% APR |
| fifty-pct | principal = 10000, rateSec = 0.5/31536000 | 50% APR, where the three-term expansions strain |
| unit | principal = 1, rateSec = 0.05/31536000 | one unit, the fraction carries everything |
| huge | principal = 100000000, rateSec = 0.05/31536000 | a hundred-million-unit pool |
Library calls per step: BL19 compound, mul; Quad ln, mul, exp; BL127 compound, mul; 64.64 ln, mul, exp; Solady powWad, sMulWad; Solmate wadPow, wadMul; PRB SD pow, mul; PRB UD pow, mul; snek wad_exp(wad_ln(x) y), mul_div(a, b, 1e18); Balancer pow, mulDown; OZ unsupported; Uniswap unsupported; Maker rpow, rmul; Aave unsupported; Morpho unsupported; Frax unsupported; Euler unsupported; BL127Lib compound, mul. Parameters reach each adapter floored into its representation on the grids and rounded to nearest on the floats (ladder-inputs.json).
The reference input, step by step: principal = 10000, rateSec = 0.05/31536000
Correct digits against the exact truth at each N, capped at what the format holds. Hover a cell for the value itself, the digits against the format-rounded truth, of the interest, the error in units of the last place and the gas per step.
| Floating point | Fixed point | ||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| steps N | BL19 | Quad | BL127 | 64.64 | Solady | Solmate | PRB SD | PRB UD | snek | Balancer | OZ | Uniswap | Maker | Aave | Morpho | Frax | Euler |
| 1 | 71.3 | 28.8 | 33.8 | 14.1 | 13.0 | 13.0 | 12.0 | 12.0 | 13.0 | 13.7 | — | — | 22.3 | — | — | — | — |
| 2 | 71.3 | 28.5 | 33.5 | 13.8 | 12.7 | 12.7 | 11.7 | 11.7 | 12.7 | 13.4 | — | — | 22.0 | — | — | — | — |
| 5 | 71.3 | 28.1 | 33.1 | 13.4 | 12.3 | 12.3 | 11.3 | 11.3 | 12.3 | 13.0 | — | — | 21.6 | — | — | — | — |
| 10 | 71.3 | 27.8 | 32.8 | 13.1 | 12.0 | 12.0 | 11.0 | 11.0 | 12.0 | 12.7 | — | — | 21.3 | — | — | — | — |
| 20 | 71.3 | 27.5 | 32.5 | 12.8 | 11.7 | 11.7 | 10.7 | 10.7 | 11.7 | 12.4 | — | — | 21.0 | — | — | — | — |
| 50 | 71.3 | 27.1 | 32.1 | 12.4 | 11.3 | 11.3 | 10.3 | 10.3 | 11.3 | 12.0 | — | — | 20.6 | — | — | — | — |
| 100 | 71.3 | 26.8 | 31.8 | 12.1 | 11.0 | 11.0 | 10.0 | 10.0 | 11.0 | 11.7 | — | — | 20.3 | — | — | — | — |
| 365 | 71.3 | 26.2 | 31.3 | 11.5 | 10.5 | 10.5 | 9.5 | 9.5 | 10.5 | 11.2 | — | — | 19.8 | — | — | — | — |
| 1,000 | 71.3 | 25.8 | 30.8 | 11.1 | 10.0 | 10.0 | 9.0 | 9.0 | 10.0 | 10.7 | — | — | 19.3 | — | — | — | — |
| 10,000 | 71.2 | 24.8 | 29.8 | 10.1 | 9.0 | 9.0 | 8.0 | 8.0 | 9.0 | 9.7 | — | — | 18.3 | — | — | — | — |
Continuous accrual
Step: b = b0 * e^(r * N / 365). Result: balance after N days of continuous accrual.
How Aave and Morpho accrue: the ideal is e^(rate * time), and both ship a three-term expansion of it (1 + x + x^2/2 + x^3/6), which Aave notes 'slightly underpays liquidity providers and undercharges borrowers'. Every library is judged against the exponential it approximates. The step here is one accrual spanning N days, which is what a market that nobody touched for N days computes on its next interaction; the expansion's error is x^4/24 with x = rate * years, so it is invisible at daily updates and the whole story at a year or more. Morpho holds the rate per second in WAD (1,585,489,599 wei at 5% APR), ten significant digits before any arithmetic; both digit counts show that loss, since the format truth is built from the annual rate the other libraries receive.
Over all 6 inputs
Median correct digits over the inputs every library with a result at that N completed, each capped at what its format holds at that magnitude (BL19 71.3, binary128 34.0, the fixed grids by their last place), so no line passes its format's precision. The WAD libraries are the gold lines, labelled once. BL127Lib coincides with BL127 and is not drawn; Aave, Morpho and Maker appear only on the accrual scenarios their models describe. Hover a point for the library, the range over the inputs and N.
| Floating point | Fixed point | ||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| steps N | BL19 | Quad | BL127 | 64.64 | Solady | Solmate | PRB SD | PRB UD | snek | Balancer | OZ | Uniswap | Maker | Aave | Morpho | Frax | Euler |
| 1 | 71.3 | 33.9 | 38.6 | 19.1 | 18.3 | 18.3 | 18.0 | 18.0 | 18.3 | 18.3 | — | — | — | 16.8 | 13.4 | — | — |
| 2 | 71.3 | 33.8 | 38.7 | 19.0 | 18.1 | 18.1 | 17.9 | 17.9 | 18.1 | 18.1 | — | — | — | 15.6 | 13.1 | — | — |
| 5 | 71.3 | 34.0 | 38.8 | 19.1 | 18.2 | 18.2 | 17.8 | 17.8 | 18.2 | 18.2 | — | — | — | 14.0 | 12.7 | — | — |
| 10 | 71.3 | 33.8 | 38.7 | 19.0 | 18.4 | 18.4 | 17.9 | 17.9 | 18.4 | 18.4 | — | — | — | 12.8 | 12.3 | — | — |
| 20 | 71.3 | 34.0 | 38.6 | 19.1 | 18.2 | 18.2 | 18.0 | 18.0 | 18.2 | 18.2 | — | — | — | 11.6 | 11.5 | — | — |
| 50 | 71.3 | 33.9 | 38.6 | 18.9 | 18.0 | 18.0 | 17.7 | 17.7 | 18.0 | 18.0 | — | — | — | 10.0 | 10.0 | — | — |
| 100 | 71.3 | 34.0 | 38.6 | 19.0 | 18.2 | 18.2 | 17.7 | 17.7 | 18.2 | 18.2 | — | — | — | 8.8 | 8.8 | — | — |
| 365 | 71.3 | 33.6 | 38.5 | 19.3 | 18.1 | 18.1 | 18.1 | 18.1 | 18.1 | 18.1 | — | — | — | 6.6 | 6.6 | — | — |
| 1,000 | 71.3 | 33.7 | 38.1 | 18.8 | 18.0 | 18.0 | 17.7 | 17.7 | 18.0 | 18.0 | — | — | — | 4.8 | 4.8 | — | — |
| 10,000 | 71.2 | 33.2 | 37.2 | 18.1 | 18.0 | 18.0 | 17.7 | 17.7 | 18.0 | 17.9 | — | — | — | 1.2 | 1.2 | — | — |
| Floating point | Fixed point | ||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| steps N | BL19 | Quad | BL127 | 64.64 | Solady | Solmate | PRB SD | PRB UD | snek | Balancer | OZ | Uniswap | Maker | Aave | Morpho | Frax | Euler |
| 1 | 71.3 | 33.9 | 38.6 | 19.1 | 18.3 | 18.3 | 18.0 | 18.0 | 18.3 | 18.3 | — | — | — | 16.8 | 13.4 | — | — |
| 2 | 71.3 | 33.8 | 38.7 | 19.0 | 18.1 | 18.1 | 17.9 | 17.9 | 18.1 | 18.1 | — | — | — | 15.6 | 13.1 | — | — |
| 5 | 71.3 | 34.0 | 38.8 | 19.1 | 18.2 | 18.2 | 17.8 | 17.8 | 18.2 | 18.2 | — | — | — | 14.0 | 12.7 | — | — |
| 10 | 71.3 | 33.8 | 38.7 | 19.0 | 18.4 | 18.4 | 17.9 | 17.9 | 18.4 | 18.4 | — | — | — | 12.8 | 12.3 | — | — |
| 20 | 71.3 | 34.0 | 38.6 | 19.1 | 18.2 | 18.2 | 18.0 | 18.0 | 18.2 | 18.2 | — | — | — | 11.6 | 11.5 | — | — |
| 50 | 71.3 | 33.9 | 38.6 | 18.9 | 18.0 | 18.0 | 17.7 | 17.7 | 18.0 | 18.0 | — | — | — | 10.0 | 10.0 | — | — |
| 100 | 71.3 | 34.0 | 38.7 | 19.0 | 18.2 | 18.2 | 17.7 | 17.7 | 18.2 | 18.2 | — | — | — | 8.8 | 8.8 | — | — |
| 365 | 71.3 | 33.6 | 39.0 | 19.4 | 18.1 | 18.1 | 18.1 | 18.1 | 18.1 | 18.1 | — | — | — | 6.6 | 6.6 | — | — |
| 1,000 | 71.3 | 33.6 | 38.6 | 19.2 | 18.0 | 18.0 | 17.7 | 17.7 | 18.0 | 18.0 | — | — | — | 4.8 | 4.8 | — | — |
| 10,000 | 71.3 | 33.2 | 38.8 | 19.2 | 18.0 | 18.0 | 17.7 | 17.7 | 18.0 | 17.9 | — | — | — | 1.2 | 1.2 | — | — |
| Floating point | Fixed point | ||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| steps N | BL19 | Quad | BL127 | 64.64 | Solady | Solmate | PRB SD | PRB UD | snek | Balancer | OZ | Uniswap | Maker | Aave | Morpho | Frax | Euler |
| 1 | 67.4 | 30.1 | 34.8 | 15.2 | 14.4 | 14.4 | 14.4 | 14.4 | 14.4 | 14.4 | — | — | — | 12.9 | 9.9 | — | — |
| 2 | 67.7 | 30.1 | 35.2 | 15.5 | 15.2 | 15.2 | 14.3 | 14.3 | 15.2 | 15.2 | — | — | — | 12.0 | 9.8 | — | — |
| 5 | 68.1 | 30.8 | 36.3 | 15.9 | 15.2 | 15.2 | 14.7 | 14.7 | 15.2 | 15.2 | — | — | — | 10.8 | 9.4 | — | — |
| 10 | 68.4 | 31.0 | 35.7 | 16.0 | 15.8 | 15.8 | 15.0 | 15.0 | 15.8 | 15.8 | — | — | — | 9.9 | 9.0 | — | — |
| 20 | 68.7 | 31.4 | 36.0 | 16.6 | 15.6 | 15.6 | 15.6 | 15.6 | 15.6 | 15.6 | — | — | — | 9.0 | 8.8 | — | — |
| 50 | 69.1 | 31.8 | 36.5 | 16.7 | 15.9 | 15.9 | 15.5 | 15.5 | 15.9 | 15.9 | — | — | — | 7.8 | 7.8 | — | — |
| 100 | 69.4 | 32.1 | 36.7 | 17.1 | 16.3 | 16.3 | 15.9 | 15.9 | 16.3 | 16.3 | — | — | — | 6.9 | 6.9 | — | — |
| 365 | 70.0 | 32.4 | 37.2 | 18.0 | 16.8 | 16.8 | 16.8 | 16.8 | 16.8 | 16.8 | — | — | — | 5.2 | 5.2 | — | — |
| 1,000 | 70.4 | 32.8 | 37.1 | 17.9 | 17.2 | 17.2 | 16.8 | 16.8 | 17.2 | 17.2 | — | — | — | 3.9 | 3.9 | — | — |
| 10,000 | 71.0 | 33.0 | 37.0 | 17.8 | 17.7 | 17.7 | 17.5 | 17.5 | 17.7 | 17.7 | — | — | — | 1.1 | 1.1 | — | — |
Median correct digits over the inputs every library completed at that N (hover a cell for the range), each capped at what its format holds; "exact" when every one of them is exact. k/n: the library completed k of n inputs and the rest reverted; rev: every input reverted. —: no model for this scenario. BL127Lib equals BL127 and is left out.
The inputs and the ops
| input | parameters | why |
|---|---|---|
| reference | principal = 10000, rateAnnual = 0.05; rateSec = rateAnnual / 31536000 | $10,000 at 5% APR, the lending protocol's steady state |
| one-pct | principal = 10000, rateAnnual = 0.01; rateSec = rateAnnual / 31536000 | a slow rate: 1% APR is 3.2e-10 a second |
| twenty-pct | principal = 10000, rateAnnual = 0.2; rateSec = rateAnnual / 31536000 | 20% APR |
| fifty-pct | principal = 10000, rateAnnual = 0.5; rateSec = rateAnnual / 31536000 | 50% APR, where the three-term expansions strain |
| unit | principal = 1, rateAnnual = 0.05; rateSec = rateAnnual / 31536000 | one unit, the fraction carries everything |
| huge | principal = 100000000, rateAnnual = 0.05; rateSec = rateAnnual / 31536000 | a hundred-million-unit pool |
Library calls per step: BL19 mul, div, exp; Quad mul, div, exp; BL127 mul, div, exp; 64.64 mul, div, exp; Solady sMulWad, sDivWad, expWad; Solmate wadMul, wadDiv, wadExp; PRB SD mul, div, exp; PRB UD mul, div, exp; snek mul_div(a, b, 1e18), mul_div(a, 1e18, b), wad_exp; Balancer mulDown, divDown, exp; OZ unsupported; Uniswap unsupported; Maker unsupported; Aave calculateCompoundedInterest, rayMul; Morpho wTaylorCompounded, wMulDown; Frax unsupported; Euler unsupported; BL127Lib mul, div, exp. Parameters reach each adapter floored into its representation on the grids and rounded to nearest on the floats (ladder-inputs.json).
The reference input, step by step: principal = 10000, rateAnnual = 0.05
Correct digits against the exact truth at each N, capped at what the format holds. Hover a cell for the value itself, the digits against the format-rounded truth, of the interest, the error in units of the last place and the gas per step.
| Floating point | Fixed point | ||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| steps N | BL19 | Quad | BL127 | 64.64 | Solady | Solmate | PRB SD | PRB UD | snek | Balancer | OZ | Uniswap | Maker | Aave | Morpho | Frax | Euler |
| 1 | 71.2 | 33.8 | 38.6 | 19.1 | 18.3 | 18.3 | 18.3 | 18.3 | 18.3 | 18.3 | — | — | — | 16.8 | 13.7 | — | — |
| 2 | 71.3 | 33.7 | 38.8 | 19.0 | 18.9 | 18.9 | 17.9 | 17.9 | 18.9 | 18.9 | — | — | — | 15.6 | 13.4 | — | — |
| 5 | 71.3 | 34.0 | 39.8 | 19.1 | 18.4 | 18.4 | 17.8 | 17.8 | 18.4 | 18.4 | — | — | — | 14.0 | 13.0 | — | — |
| 10 | 71.3 | 33.6 | 38.6 | 18.9 | 18.7 | 18.7 | 17.9 | 17.9 | 18.7 | 18.7 | — | — | — | 12.8 | 12.5 | — | — |
| 20 | 71.3 | 34.0 | 38.6 | 19.1 | 18.2 | 18.2 | 18.2 | 18.2 | 18.2 | 18.2 | — | — | — | 11.6 | 11.5 | — | — |
| 50 | 71.3 | 33.8 | 38.6 | 18.9 | 18.1 | 18.1 | 17.7 | 17.7 | 18.1 | 18.1 | — | — | — | 10.0 | 10.0 | — | — |
| 100 | 71.3 | 34.0 | 38.6 | 19.0 | 18.2 | 18.2 | 17.7 | 17.7 | 18.2 | 18.2 | — | — | — | 8.8 | 8.8 | — | — |
| 365 | 71.3 | 33.6 | 38.5 | 19.3 | 18.1 | 18.1 | 18.1 | 18.1 | 18.1 | 18.1 | — | — | — | 6.6 | 6.6 | — | — |
| 1,000 | 71.3 | 33.6 | 38.0 | 18.8 | 18.1 | 18.1 | 17.7 | 17.7 | 18.1 | 18.1 | — | — | — | 4.8 | 4.8 | — | — |
| 10,000 | 71.3 | 33.3 | 37.1 | 17.8 | 17.9 | 17.9 | 17.7 | 17.7 | 17.9 | 17.9 | — | — | — | 1.2 | 1.2 | — | — |
An option walking out of the money
Step: S = S (1 - tick); then C = S N(d1) - K e^(-rT) N(d2). Result: the Black-Scholes call price after N down-ticks of the spot.
Options protocols price with N(d), the normal distribution function, and the spot walks. Near the money every library agrees; past d = -8 an 18-decimal N(d) is zero and the price with it, and before that e^(-d^2/2) has lost most of its digits. BL127 and BL19 have normCdf as an op; the other libraries run the same series and continued fraction through their own exp, sqrt, mul and div, with pi by Ramanujan through the same ops, so each is judged on its primitives. Relative digits there say little about money: at N = 10,000 the true price of five of the six inputs is below 10^-15 wei of a $100 strike at 18 decimals, so every library is off by less than a wei; the slow walk's is 3.2 million wei ($3 × 10^-12), where the WAD libraries are off by about 94 wei. Up to N = 1,000 they are off by tens to ten thousand wei, BL127 by under 10^-16 (absErrWei in the data).
Over all 6 inputs
Median correct digits over the inputs every library with a result at that N completed, each capped at what its format holds at that magnitude (BL19 71.3, binary128 34.0, the fixed grids by their last place), so no line passes its format's precision. The WAD libraries are the gold lines, labelled once. BL127Lib coincides with BL127 and is not drawn; Aave, Morpho and Maker appear only on the accrual scenarios their models describe. Hover a point for the library, the range over the inputs and N.
| Floating point | Fixed point | ||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| steps N | BL19 | Quad | BL127 | 64.64 | Solady | Solmate | PRB SD | PRB UD | snek | Balancer | OZ | Uniswap | Maker | Aave | Morpho | Frax | Euler |
| 1 | 70.4 | 32.6 | 37.6 | 18.2 | 16.8 | 16.8 | 16.8 | 16.8 | 16.6 | — | — | — | — | — | — | — | |
| 2 | 70.5 | 32.4 | 37.6 | 17.8 | 16.8 | 16.8 | 16.7 | 16.8 | 16.8 | — | — | — | — | — | — | — | |
| 5 | 70.4 | 32.0 | 37.1 | 17.9 | 16.7 | 16.7 | 16.7 | 16.7 | 16.7 | — | — | — | — | — | — | — | |
| 10 | 70.0 | 31.8 | 36.8 | 17.6 | 16.6 | 16.6 | 16.6 | 16.6 | 16.8 | — | — | — | — | — | — | — | |
| 20 | 69.6 | 31.5 | 36.4 | 17.3 | 16.6 | 16.6 | 16.6 | 16.6 | 16.6 | — | — | — | — | — | — | — | |
| 50 | 69.2 | 31.1 | 36.0 | 16.8 | 16.5 | 16.5 | 16.6 | 16.5 | 16.6 | — | — | — | — | — | — | — | |
| 100 | 68.8 | 30.8 | 35.7 | 16.5 | 16.5 | 16.5 | 16.5 | 16.5 | 16.4 | — | — | — | — | — | — | — | |
| 365 | 68.2 | 30.1 | 35.0 | 15.8 | 16.4 | 16.4 | 16.2 | 16.4 | 16.0 | — | — | — | — | — | — | — | |
| 1,000 | 67.7 | 29.4 | 34.3 | 15.2 | 15.4 | 15.4 | 15.4 | 15.4 | 15.4 | — | — | — | — | — | — | — | |
| 10,000 | 66.2 | 28.0 | 25.2 | 6.6 | 4.5 | 4.5 | 4.5 | 4.5 | 4.5 | — | — | — | — | — | — | — | |
| Floating point | Fixed point | ||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| steps N | BL19 | Quad | BL127 | 64.64 | Solady | Solmate | PRB SD | PRB UD | snek | Balancer | OZ | Uniswap | Maker | Aave | Morpho | Frax | Euler |
| 1 | 70.4 | 32.6 | 37.6 | 18.2 | 16.8 | 16.8 | 16.8 | 16.8 | 16.6 | — | — | — | — | — | — | — | |
| 2 | 70.6 | 32.4 | 38.3 | 18.0 | 16.8 | 16.8 | 16.7 | 16.8 | 16.8 | — | — | — | — | — | — | — | |
| 5 | 70.4 | 32.0 | 38.2 | 17.9 | 16.7 | 16.7 | 16.7 | 16.7 | 16.7 | — | — | — | — | — | — | — | |
| 10 | 70.0 | 31.8 | 37.9 | 18.0 | 16.6 | 16.6 | 16.6 | 16.6 | 16.8 | — | — | — | — | — | — | — | |
| 20 | 69.6 | 31.5 | 38.2 | 18.3 | 16.6 | 16.6 | 16.6 | 16.6 | 16.6 | — | — | — | — | — | — | — | |
| 50 | 69.2 | 31.1 | 37.8 | 17.8 | 16.5 | 16.5 | 16.6 | 16.5 | 16.6 | — | — | — | — | — | — | — | |
| 100 | 68.8 | 30.8 | 37.8 | 17.6 | 16.5 | 16.5 | 16.5 | 16.5 | 16.4 | — | — | — | — | — | — | — | |
| 365 | 68.2 | 30.1 | 37.2 | 17.4 | 16.4 | 16.4 | 16.2 | 16.4 | 16.0 | — | — | — | — | — | — | — | |
| 1,000 | 67.7 | 29.4 | 36.2 | 16.6 | 15.4 | 15.4 | 15.4 | 15.4 | 15.4 | — | — | — | — | — | — | — | |
| 10,000 | 66.2 | 28.0 | 25.2 | 6.6 | 4.5 | 4.5 | 4.5 | 4.5 | 4.5 | — | — | — | — | — | — | — | |
Median correct digits over the inputs every library completed at that N (hover a cell for the range), each capped at what its format holds; "exact" when every one of them is exact. k/n: the library completed k of n inputs and the rest reverted; rev: every input reverted. —: no model for this scenario. BL127Lib equals BL127 and is left out.
The inputs and the ops
| input | parameters | why |
|---|---|---|
| reference | T = 0.5, r = 0.05, sigma = 0.2, spot = 100, strike = 100, tick = 0.000173 | at the money, 20% vol, six months; d1 reaches -12 at N = 10,000 |
| slow-walk | T = 0.5, r = 0.05, sigma = 0.2, spot = 100, strike = 100, tick = 0.0001 | a slower walk: d1 reaches -7 at N = 10,000, where an 18-decimal N(d) has a few digits left |
| fast-walk | T = 0.5, r = 0.05, sigma = 0.2, spot = 100, strike = 100, tick = 0.0005 | a faster walk: d1 passes -12 near N = 3,500; beyond it the price is below every grid |
| low-vol | T = 0.5, r = 0.05, sigma = 0.05, spot = 100, strike = 100, tick = 0.00005 | 5% vol: d moves four times faster per tick |
| high-vol | T = 0.5, r = 0.05, sigma = 0.8, spot = 100, strike = 100, tick = 0.0007 | 80% vol: a long way to the tail |
| short-dated | T = 0.01, r = 0.05, sigma = 0.2, spot = 100, strike = 100, tick = 0.00003 | ten days to expiry: sigma sqrt(T) is 0.02 and the tail comes fast |
Library calls per step: BL19 mul, sqrt, ln, div, add, exp, sub, normCdf; Quad mul, sqrt, ln, div, add, exp, sub, normCdf by the series/fraction through these; BL127 mul, sqrt, ln, div, add, exp, sub, normCdf; 64.64 mul, sqrt, ln, div, add, exp, sub, normCdf by the series/fraction through these; Solady sMulWad, sqrtWad, lnWad, sDivWad, expWad, normCdf by the series/fraction through these; Solmate wadMul, sqrt(x 1e18), wadLn, wadDiv, wadExp, normCdf by the series/fraction through these; PRB SD mul, sqrt, ln, div, exp, normCdf by the series/fraction through these; PRB UD mul, sqrt, ln, div, exp, normCdf by the series/fraction through these; snek mul_div(a, b, 1e18), isqrt(x 1e18) (Vyper built-in), wad_ln, mul_div(a, 1e18, b), wad_exp, normCdf by the series/fraction through these; Balancer mulDown, pow(x, 1/2), ln, divDown, exp, normCdf by the series/fraction through these; OZ unsupported; Uniswap unsupported; Maker unsupported; Aave unsupported; Morpho unsupported; Frax unsupported; Euler unsupported; BL127Lib mul, sqrt, ln, div, add, exp, sub, normCdf. Parameters reach each adapter floored into its representation on the grids and rounded to nearest on the floats (ladder-inputs.json).
The reference input, step by step: T = 0.5, r = 0.05, sigma = 0.2, spot = 100, strike = 100, tick = 0.000173
Correct digits against the exact truth at each N, capped at what the format holds. Hover a cell for the value itself, the digits against the format-rounded truth, the error in wei, the error in units of the last place and the gas per step.
| Floating point | Fixed point | ||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| steps N | BL19 | Quad | BL127 | 64.64 | Solady | Solmate | PRB SD | PRB UD | snek | Balancer | OZ | Uniswap | Maker | Aave | Morpho | Frax | Euler |
| 1 | 70.5 | 32.6 | 37.8 | 18.2 | 16.7 | 16.7 | 16.5 | reverts | 16.7 | 16.6 | — | — | — | — | — | — | — |
| 2 | 70.7 | 32.5 | 37.6 | 18.0 | 17.0 | 17.0 | 16.7 | reverts | 17.0 | 17.7 | — | — | — | — | — | — | — |
| 5 | 70.2 | 32.1 | 37.2 | 18.3 | 16.6 | 16.6 | 16.6 | reverts | 16.6 | 16.7 | — | — | — | — | — | — | — |
| 10 | 70.1 | 31.8 | 36.8 | 18.0 | 16.6 | 16.6 | 16.4 | reverts | 16.6 | 16.8 | — | — | — | — | — | — | — |
| 20 | 71.0 | 31.5 | 36.5 | 17.5 | 16.6 | 16.6 | 16.6 | reverts | 16.6 | 16.7 | — | — | — | — | — | — | — |
| 50 | 69.8 | 31.1 | 36.1 | 17.0 | 16.9 | 16.9 | 16.8 | reverts | 16.9 | 16.6 | — | — | — | — | — | — | — |
| 100 | 69.4 | 30.8 | 35.8 | 16.7 | 16.4 | 16.4 | 16.6 | reverts | 16.4 | 16.3 | — | — | — | — | — | — | — |
| 365 | 68.7 | 30.2 | 35.1 | 16.0 | 16.4 | 16.4 | 16.3 | reverts | 16.4 | 16.3 | — | — | — | — | — | — | — |
| 1,000 | 68.1 | 29.6 | 34.6 | 15.5 | 15.7 | 15.7 | 15.7 | reverts | 15.7 | 15.4 | — | — | — | — | — | — | — |
| 10,000 | 66.3 | 27.8 | 3.7 | 0.0 | 0.0 | 0.0 | 0.0 | reverts | 0.0 | reverts | — | — | — | — | — | — | — |
Revert reasons
- PRB UD: PRBMath_UD60x18_Log_InputTooSmall 0x36d32ef0
- Balancer: Balancer InvalidExponent() 0xd4794efd
Decay, the share released
Step: D = D e^(-eps); result 1 - D. Result: the share released after N steps of decay.
Vesting, TWAP weights and exponential moving averages multiply by e^(-dt/tau) every step. The factor is a hair below one, and on an 18-decimal grid eps and e^(-eps) both sit on a grid of spacing 1e-18, so the factor's distance from one keeps about 18 + log10(eps) digits, and the released share with it: six digits at eps = 1.06e-12, three at 1.06e-15, one at 1.06e-17, and below 1e-18 nothing is released at all. Each eps is dt/tau for a time constant in seconds, which no grid holds exactly; a power of ten sits on the WAD grid and flatters it (at eps = 1e-17 exactly, Solady kept 17 digits).
Over all 5 inputs
Median correct digits over the inputs every library with a result at that N completed, each capped at what its format holds at that magnitude (BL19 71.3, binary128 34.0, the fixed grids by their last place), so no line passes its format's precision. The WAD libraries are the gold lines, labelled once. BL127Lib coincides with BL127 and is not drawn; Aave, Morpho and Maker appear only on the accrual scenarios their models describe. Hover a point for the library, the range over the inputs and N.
| Floating point | Fixed point | ||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| steps N | BL19 | Quad | BL127 | 64.64 | Solady | Solmate | PRB SD | PRB UD | snek | Balancer | OZ | Uniswap | Maker | Aave | Morpho | Frax | Euler |
| 1 | 59.9 | 22.8 | 26.5 | 7.2 | 6.0 | 6.0 | 5.9 | 6.0 | 6.0 | — | — | — | — | — | — | — | |
| 2 | 60.3 | 22.3 | 26.8 | 7.5 | 6.3 | 6.3 | 5.9 | 6.3 | 6.3 | — | — | — | — | — | — | — | |
| 5 | 60.1 | 22.2 | 26.7 | 7.6 | 6.7 | 6.7 | 5.9 | 6.7 | 6.7 | — | — | — | — | — | — | — | |
| 10 | 60.0 | 22.2 | 26.7 | 7.6 | 7.0 | 7.0 | 5.9 | 7.0 | 7.0 | — | — | — | — | — | — | — | |
| 20 | 60.0 | 22.2 | 26.7 | 7.6 | 7.2 | 7.2 | 5.9 | 7.2 | 7.2 | — | — | — | — | — | — | — | |
| 50 | 59.9 | 22.2 | 26.7 | 7.6 | 7.2 | 7.2 | 5.9 | 7.2 | 7.2 | — | — | — | — | — | — | — | |
| 100 | 59.9 | 22.2 | 26.7 | 7.6 | 7.2 | 7.2 | 5.9 | 7.2 | 7.2 | — | — | — | — | — | — | — | |
| 365 | 59.9 | 22.2 | 26.7 | 7.6 | 7.2 | 7.2 | 5.9 | 7.2 | 7.2 | — | — | — | — | — | — | — | |
| 1,000 | 59.9 | 22.2 | 26.7 | 7.6 | 7.2 | 7.2 | 5.9 | 7.2 | 7.2 | — | — | — | — | — | — | — | |
| 10,000 | 59.9 | 22.2 | 26.7 | 7.5 | 7.2 | 7.2 | 5.9 | 7.2 | 7.2 | — | — | — | — | — | — | — | |
| Floating point | Fixed point | ||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| steps N | BL19 | Quad | BL127 | 64.64 | Solady | Solmate | PRB SD | PRB UD | snek | Balancer | OZ | Uniswap | Maker | Aave | Morpho | Frax | Euler |
| 1 | 59.9 | 22.8 | 26.5 | 7.2 | 6.0 | 6.0 | 6.0 | 6.0 | 6.0 | — | — | — | — | — | — | — | |
| 2 | 60.3 | 22.3 | 26.7 | 7.2 | 6.3 | 6.3 | 6.0 | 6.3 | 6.3 | — | — | — | — | — | — | — | |
| 5 | 60.1 | 22.2 | 26.6 | 7.2 | 6.7 | 6.7 | 6.0 | 6.7 | 6.7 | — | — | — | — | — | — | — | |
| 10 | 60.0 | 22.2 | 26.6 | 7.2 | 7.0 | 7.0 | 6.0 | 7.0 | 7.0 | — | — | — | — | — | — | — | |
| 20 | 60.0 | 22.2 | 26.6 | 7.2 | 7.3 | 7.3 | 6.0 | 7.3 | 7.3 | — | — | — | — | — | — | — | |
| 50 | 59.9 | 22.2 | 26.6 | 7.2 | 7.7 | 7.7 | 6.0 | 7.7 | 7.7 | — | — | — | — | — | — | — | |
| 100 | 59.9 | 22.2 | 26.6 | 7.2 | 8.0 | 8.0 | 6.0 | 8.0 | 8.0 | — | — | — | — | — | — | — | |
| 365 | 59.9 | 22.2 | 26.6 | 7.2 | 8.5 | 8.5 | 6.0 | 8.5 | 8.5 | — | — | — | — | — | — | — | |
| 1,000 | 59.9 | 22.2 | 26.6 | 7.2 | 8.9 | 8.9 | 6.0 | 8.9 | 9.0 | — | — | — | — | — | — | — | |
| 10,000 | 59.9 | 22.2 | 26.6 | 7.2 | 8.2 | 8.2 | 6.0 | 8.2 | 8.2 | — | — | — | — | — | — | — | |
Median correct digits over the inputs every library completed at that N (hover a cell for the range), each capped at what its format holds; "exact" when every one of them is exact. k/n: the library completed k of n inputs and the rest reverted; rev: every input reverted. —: no model for this scenario. BL127Lib equals BL127 and is left out.
The inputs and the ops
| input | parameters | why |
|---|---|---|
| reference | eps = 1/1036800 | a one-second step against a twelve-day time constant: eps = 9.6e-7 |
| nano | eps = 1/946080000 | a one-second step against a thirty-year time constant: eps = 1.06e-9 |
| pico | eps = 1/946080000000 | the thirty-year constant stepped every millisecond: eps = 1.06e-12 |
| femto | eps = 1/946080000000000 | stepped every microsecond: eps = 1.06e-15 |
| atto | eps = 1/94608000000000000 | stepped every ten nanoseconds: eps = 1.06e-17, ten and a half wei |
Library calls per step: BL19 exp, mul, sub; Quad exp, mul, sub; BL127 exp, mul, sub; 64.64 exp, mul, sub; Solady expWad, sMulWad; Solmate wadExp, wadMul; PRB SD exp, mul; PRB UD exp, mul; snek wad_exp, mul_div(a, b, 1e18); Balancer exp, mulDown; OZ unsupported; Uniswap unsupported; Maker unsupported; Aave unsupported; Morpho unsupported; Frax unsupported; Euler unsupported; BL127Lib exp, mul, sub. Parameters reach each adapter floored into its representation on the grids and rounded to nearest on the floats (ladder-inputs.json).
The reference input, step by step: eps = 1/1036800
Correct digits against the exact truth at each N, capped at what the format holds. Hover a cell for the value itself, the digits against the format-rounded truth, the error in units of the last place and the gas per step.
| Floating point | Fixed point | ||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| steps N | BL19 | Quad | BL127 | 64.64 | Solady | Solmate | PRB SD | PRB UD | snek | Balancer | OZ | Uniswap | Maker | Aave | Morpho | Frax | Euler |
| 1 | 65.8 | 28.1 | 32.4 | 13.2 | 11.9 | 11.9 | 11.7 | reverts | 11.9 | 11.9 | — | — | — | — | — | — | — |
| 2 | 65.9 | 27.9 | 32.4 | 13.5 | 12.2 | 12.2 | 11.8 | reverts | 12.2 | 12.2 | — | — | — | — | — | — | — |
| 5 | 66.0 | 27.9 | 32.6 | 13.6 | 12.1 | 12.1 | 11.8 | reverts | 12.1 | 12.5 | — | — | — | — | — | — | — |
| 10 | 65.9 | 27.9 | 32.6 | 13.5 | 12.0 | 12.0 | 11.9 | reverts | 12.0 | 12.7 | — | — | — | — | — | — | — |
| 20 | 65.8 | 27.9 | 32.7 | 13.5 | 12.0 | 12.0 | 11.9 | reverts | 12.0 | 12.9 | — | — | — | — | — | — | — |
| 50 | 65.8 | 27.8 | 32.7 | 13.5 | 12.0 | 12.0 | 11.9 | reverts | 12.0 | 12.9 | — | — | — | — | — | — | — |
| 100 | 65.8 | 27.8 | 32.7 | 13.5 | 12.0 | 12.0 | 11.9 | reverts | 12.0 | 13.0 | — | — | — | — | — | — | — |
| 365 | 65.8 | 27.8 | 32.7 | 13.5 | 12.0 | 12.0 | 11.9 | reverts | 12.0 | 13.0 | — | — | — | — | — | — | — |
| 1,000 | 65.8 | 27.8 | 32.7 | 13.5 | 12.0 | 12.0 | 11.9 | reverts | 12.0 | 13.1 | — | — | — | — | — | — | — |
| 10,000 | 65.8 | 27.8 | 32.7 | 13.5 | 12.0 | 12.0 | 11.9 | reverts | 12.0 | 13.1 | — | — | — | — | — | — | — |
Revert reasons
- PRB UD: Negative(): a negative value where the library is unsigned (Balancer pow, PRBMath UD60x18, the WAD roots) 0x34d81929
An adaptive rate after an idle period
Step: r = r0 * e^(speed * err * N * step). Result: the adaptive rate after N idle steps and one update.
FraxLend and Euler v2 move a rate up while utilisation sits above a target and down while it sits below, and both document the move as exponential in time. FraxLend's documentation states it as a half-life: at 100% utilisation 'the increase will be 100% per half-life', at 0% the rates 'decrease by 50% each half-life', the model 2^(t/H). Its VariableInterestRate V2 computes one update after an interval dt as F (1 + d^2 dt / H) above the target band and F H / (H + d^2 dt) below it, d the normalised distance from the band, which equals 2^(t/H) at dt = H only. The comment on Euler's IRMAdaptiveCurve._newRateAtTarget states rateAtTarget = startRateAtTarget * e^linearAdaptation, where the code forms linearAdaptation = ADJUSTMENT_SPEED * err * elapsed, and it computes e^x with Morpho's ExpLib.wExp, a second-order Taylor polynomial of e^r after reducing x by ln 2. Both models are r0 e^(speed err t) with speed = ln 2 / H; at the three utilisations here (100%, 0%, 92.5%) FraxLend's signed d^2 and Euler's err are equal (1, -1, 0.25), so each input is one documented model that both protocols compute from their own inputs. The market is idle for N steps and updated once, which is what a market nobody touched computes on its next interaction; the result is the adaptive state (FraxLend's full-utilisation rate, Euler's rate at target), from which each protocol derives the borrow rate. Every other library computes rate0 e^(x N) with its own mul and exp. The rate is per second, as both protocols hold it, so the 18-decimal grid keeps about ten digits of it before any arithmetic. The protocol adapters run with the rate bounds set wide so they do not bind; the deployed contracts clamp the rate (FraxLend to [MIN_FULL_UTIL_RATE, MAX_FULL_UTIL_RATE], Euler to [MIN_RATE_AT_TARGET, MAX_RATE_AT_TARGET]), which would stop the large-N cells at a bound.
Over all 11 inputs
Median correct digits over the inputs every library with a result at that N completed, each capped at what its format holds at that magnitude (BL19 71.3, binary128 34.0, the fixed grids by their last place), so no line passes its format's precision. The WAD libraries are the gold lines, labelled once. BL127Lib coincides with BL127 and is not drawn; Aave, Morpho and Maker appear only on the accrual scenarios their models describe. Hover a point for the library, the range over the inputs and N.
| Floating point | Fixed point | ||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| steps N | BL19 | Quad | BL127 | 64.64 | Solady | Solmate | PRB SD | PRB UD | snek | Balancer | OZ | Uniswap | Maker | Aave | Morpho | Frax | Euler |
| 1 | 71.3 | 33.8 | 29.5 | 10.3 | 9.1 | 9.1 | 9.1 | 9.1 | 9.1 | 9.1 | — | — | — | — | — | 1.4 | 3.9 |
| 2 | 71.3 | 33.7 | 29.5 | 10.4 | 9.1 | 9.1 | 9.1 | 9.1 | 9.1 | 9.1 | — | — | — | — | — | 1.4 | 5.4 |
| 5 | 71.3 | 33.7 | 29.6 | 10.5 | 9.2 | 9.2 | 9.2 | 9.2 | 9.2 | 9.2 | — | — | — | — | — | 1.2 | 3.5 |
| 10 | 71.3 | 33.7 | 29.7 | 10.7 | 9.3 | 9.3 | 9.3 | 9.3 | 9.3 | 9.3 | — | — | — | — | — | 1.2 | 7.0 |
| 20 | 71.2 | 33.6 | 29.8 | 10.8 | 9.4 | 9.4 | 9.4 | 9.4 | 9.4 | 9.4 | — | — | — | — | — | 0.5 | 5.2 |
| 50 | 70.8 | 33.8 | 29.8 | 11.0 | 9.5 | 9.5 | 9.5 | 9.5 | 9.5 | 9.5 | — | — | — | — | — | 0.0 | 5.4 |
| 100 | 70.5 | 33.6 | 29.8 | 11.0 | 9.5 | 9.5 | 9.5 | 9.5 | 9.5 | 9.5 | — | — | — | — | — | 0.0 | 4.5 |
| 365 | 71.1 | 32.8 | 29.8 | 11.0 | 9.5 | 9.5 | 9.5 | 9.5 | 9.5 | 9.5 | — | — | — | — | — | 0.0 | 4.7 |
| 1,000 | 71.2 | 34.0 | 29.6 | 10.3 | 9.1 | 9.1 | 9.1 | 9.1 | 9.1 | 9.1 | — | — | — | — | — | 1.7 | 4.7 |
| 10,000 | 71.3 | 33.8 | 29.6 | 10.5 | 9.2 | 9.2 | 9.2 | 9.2 | 9.2 | 9.2 | — | — | — | — | — | 1.2 | 2.4 |
| Floating point | Fixed point | ||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| steps N | BL19 | Quad | BL127 | 64.64 | Solady | Solmate | PRB SD | PRB UD | snek | Balancer | OZ | Uniswap | Maker | Aave | Morpho | Frax | Euler |
| 1 | 71.3 | 33.6 | 29.6 | 10.4 | 9.1 | 9.1 | 9.1 | 9.1 | 9.1 | 9.1 | — | — | — | — | — | 1.4 | 3.9 |
| 2 | 71.3 | 33.6 | 29.7 | 10.4 | 9.1 | 9.1 | 9.1 | 9.1 | 9.1 | 9.1 | — | — | — | — | — | 1.4 | 5.4 |
| 5 | 71.3 | 33.5 | 29.8 | 10.5 | 9.2 | 9.2 | 9.2 | 9.2 | 9.2 | 9.2 | — | — | — | — | — | 1.2 | 3.5 |
| 10 | 71.3 | 33.6 | 30.0 | 10.7 | 9.4 | 9.4 | 9.4 | 9.4 | 9.4 | 9.4 | — | — | — | — | — | 1.2 | 7.0 |
| 20 | 71.3 | 33.4 | 30.2 | 11.0 | 9.7 | 9.7 | 9.7 | 9.7 | 9.7 | 9.7 | — | — | — | — | — | 0.5 | 5.2 |
| 50 | 71.2 | 33.4 | 31.1 | 11.8 | 10.5 | 10.5 | 10.5 | 10.5 | 10.5 | 10.5 | — | — | — | — | — | 0.0 | 5.4 |
| 100 | 70.9 | 33.1 | 32.6 | 13.3 | 12.0 | 12.0 | 12.0 | 12.0 | 12.0 | 12.0 | — | — | — | — | — | 0.0 | 4.5 |
| 365 | 71.3 | 32.8 | 31.9 | 12.6 | 11.3 | 11.3 | 11.3 | 11.3 | 11.3 | 11.3 | — | — | — | — | — | 0.0 | 4.7 |
| 1,000 | 71.3 | 33.9 | 29.6 | 10.3 | 9.1 | 9.1 | 9.1 | 9.1 | 9.1 | 9.1 | — | — | — | — | — | 1.7 | 4.7 |
| 10,000 | 71.3 | 33.6 | 29.8 | 10.5 | 9.2 | 9.2 | 9.2 | 9.2 | 9.2 | 9.2 | — | — | — | — | — | 1.2 | 2.4 |
Median correct digits over the inputs every library completed at that N (hover a cell for the range), each capped at what its format holds; "exact" when every one of them is exact. k/n: the library completed k of n inputs and the rest reverted; rev: every input reverted. —: no model for this scenario. BL127Lib equals BL127 and is left out.
The inputs and the ops
| input | parameters | why |
|---|---|---|
| reference | halfLife = 172800, rateAnnual = 0.04, step = 86400, util = 1; halfLife = ln 2 / speed when the input gives speedAnnualrate0 = rateAnnual / 31536000, the rate per secondspeed = ln 2 / halfLife, or speedAnnual / 31536000x = speed * err * step, err the documented deviation at util (1 at 100%, -1 at 0%, 0.25 at 92.5%) | 100% utilisation, a day per step, FraxLend's deployed half-life of two days (rate contract 0x18500cB1...F261); Euler at the same speed, ln 2 / 2 days, 126 per year |
| halving | halfLife = 172800, rateAnnual = 0.04, step = 86400, util = 0; halfLife = ln 2 / speed when the input gives speedAnnualrate0 = rateAnnual / 31536000, the rate per secondspeed = ln 2 / halfLife, or speedAnnual / 31536000x = speed * err * step, err the documented deviation at util (1 at 100%, -1 at 0%, 0.25 at 92.5%) | 0% utilisation at the same half-life: the documented rate halves every two days |
| realistic | halfLife = 172800, rateAnnual = 0.04, step = 86400, util = 0.925; halfLife = ln 2 / speed when the input gives speedAnnualrate0 = rateAnnual / 31536000, the rate per secondspeed = ln 2 / halfLife, or speedAnnual / 31536000x = speed * err * step, err the documented deviation at util (1 at 100%, -1 at 0%, 0.25 at 92.5%) | 92.5% utilisation: FraxLend d = 0.5 above its 85% band (d^2 = 0.25), Euler err = 0.25 above its 90% target |
| block | halfLife = 172800, rateAnnual = 0.04, step = 12, util = 1; halfLife = ln 2 / speed when the input gives speedAnnualrate0 = rateAnnual / 31536000, the rate per secondspeed = ln 2 / halfLife, or speedAnnual / 31536000x = speed * err * step, err the documented deviation at util (1 at 100%, -1 at 0%, 0.25 at 92.5%) | a 12-second block per step, from one block to 33 hours idle (N = 10,000) |
| hourly | halfLife = 172800, rateAnnual = 0.04, step = 3600, util = 1; halfLife = ln 2 / speed when the input gives speedAnnualrate0 = rateAnnual / 31536000, the rate per secondspeed = ln 2 / halfLife, or speedAnnual / 31536000x = speed * err * step, err the documented deviation at util (1 at 100%, -1 at 0%, 0.25 at 92.5%) | an hour per step, from one hour to 417 days idle |
| weekly | halfLife = 172800, rateAnnual = 0.04, step = 604800, util = 1; halfLife = ln 2 / speed when the input gives speedAnnualrate0 = rateAnnual / 31536000, the rate per secondspeed = ln 2 / halfLife, or speedAnnual / 31536000x = speed * err * step, err the documented deviation at util (1 at 100%, -1 at 0%, 0.25 at 92.5%) | a week per step |
| euler-speed | rateAnnual = 0.04, speedAnnual = 100, step = 86400, util = 1; halfLife = ln 2 / speed when the input gives speedAnnualrate0 = rateAnnual / 31536000, the rate per secondspeed = ln 2 / halfLife, or speedAnnual / 31536000x = speed * err * step, err the documented deviation at util (1 at 100%, -1 at 0%, 0.25 at 92.5%) | Euler's deployed ADJUSTMENT_SPEED, 100 per 365-day year (3170979198376 wei per second at 0xC9A0109D...C23D); FraxLend at the same speed, a half-life of ln 2 / 100 years, 2.53 days |
| euler-halving | rateAnnual = 0.04, speedAnnual = 100, step = 86400, util = 0; halfLife = ln 2 / speed when the input gives speedAnnualrate0 = rateAnnual / 31536000, the rate per secondspeed = ln 2 / halfLife, or speedAnnual / 31536000x = speed * err * step, err the documented deviation at util (1 at 100%, -1 at 0%, 0.25 at 92.5%) | 0% utilisation at Euler's speed |
| euler-realistic | rateAnnual = 0.04, speedAnnual = 100, step = 86400, util = 0.925; halfLife = ln 2 / speed when the input gives speedAnnualrate0 = rateAnnual / 31536000, the rate per secondspeed = ln 2 / halfLife, or speedAnnual / 31536000x = speed * err * step, err the documented deviation at util (1 at 100%, -1 at 0%, 0.25 at 92.5%) | 92.5% utilisation at Euler's speed |
| euler-weekly | rateAnnual = 0.04, speedAnnual = 100, step = 604800, util = 1; halfLife = ln 2 / speed when the input gives speedAnnualrate0 = rateAnnual / 31536000, the rate per secondspeed = ln 2 / halfLife, or speedAnnual / 31536000x = speed * err * step, err the documented deviation at util (1 at 100%, -1 at 0%, 0.25 at 92.5%) | a week per step at Euler's speed |
| euler-block | rateAnnual = 0.04, speedAnnual = 100, step = 12, util = 1; halfLife = ln 2 / speed when the input gives speedAnnualrate0 = rateAnnual / 31536000, the rate per secondspeed = ln 2 / halfLife, or speedAnnual / 31536000x = speed * err * step, err the documented deviation at util (1 at 100%, -1 at 0%, 0.25 at 92.5%) | a 12-second block per step at Euler's speed |
Library calls per step: BL19 mul, div, exp; Quad mul, div, exp; BL127 mul, div, exp; 64.64 mul, div, exp; Solady sMulWad, sDivWad, expWad; Solmate wadMul, wadDiv, wadExp; PRB SD mul, div, exp; PRB UD mul, div, exp; snek mul_div(a, b, 1e18), mul_div(a, 1e18, b), wad_exp; Balancer mulDown, divDown, exp; OZ unsupported; Uniswap unsupported; Maker unsupported; Aave unsupported; Morpho unsupported; Frax getFullUtilizationInterest; Euler _calcErr, _newRateAtTarget, ExpLib.wExp; BL127Lib mul, div, exp. Parameters reach each adapter floored into its representation on the grids and rounded to nearest on the floats (ladder-inputs.json).
The reference input, step by step: halfLife = 172800, rateAnnual = 0.04, step = 86400, util = 1
Correct digits against the exact truth at each N, capped at what the format holds. Hover a cell for the value itself, the digits against the format-rounded truth, the error in units of the last place and the gas per step.
| Floating point | Fixed point | ||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| steps N | BL19 | Quad | BL127 | 64.64 | Solady | Solmate | PRB SD | PRB UD | snek | Balancer | OZ | Uniswap | Maker | Aave | Morpho | Frax | Euler |
| 1 | 71.3 | 34.0 | 29.7 | 10.4 | 9.1 | 9.1 | 9.1 | 9.1 | 9.1 | 9.1 | — | — | — | — | — | 1.2 | 2.2 |
| 2 | 71.3 | 34.0 | 29.5 | 10.5 | 9.1 | 9.1 | 9.1 | 9.1 | 9.1 | 9.1 | — | — | — | — | — | 9.4 | 9.1 |
| 5 | 71.0 | 33.4 | 29.8 | 10.8 | 9.4 | 9.4 | 9.4 | 9.4 | 9.4 | 9.4 | — | — | — | — | — | 0.4 | 2.2 |
| 10 | 70.9 | 33.1 | 29.8 | 10.9 | 9.5 | 9.5 | 9.5 | 9.5 | 9.5 | 9.5 | — | — | — | — | — | 0.0 | 9.5 |
| 20 | 70.6 | 32.9 | 29.8 | 11.0 | 9.5 | 9.5 | 9.5 | 9.5 | 9.5 | 9.5 | — | — | — | — | — | 0.0 | 9.5 |
| 50 | 70.0 | 32.3 | 29.8 | 11.0 | 9.5 | 9.5 | 9.5 | 9.5 | 9.5 | 9.5 | — | — | — | — | — | 0.0 | 9.5 |
| 100 | 69.6 | 32.0 | 29.8 | 11.0 | 9.5 | 9.5 | 9.5 | 9.5 | 9.5 | 9.5 | — | — | — | — | — | 0.0 | 9.5 |
| 365 | 69.7 | 31.4 | reverts | reverts | reverts | reverts | 9.5 | 9.5 | 9.5 | reverts | — | — | — | — | — | 0.0 | 0.0 |
| 1,000 | 68.8 | 31.1 | reverts | reverts | reverts | reverts | reverts | reverts | reverts | reverts | — | — | — | — | — | 0.0 | 0.0 |
| 10,000 | 67.8 | 30.2 | reverts | reverts | reverts | reverts | reverts | reverts | reverts | reverts | — | — | — | — | — | 0.0 | 0.0 |
Revert reasons
- BL127: Overflow() 0x35278d12
- 64.64: bare revert (require without a reason, or out of gas) 0x00000000
- Solady: Solady SMulWadFailed() 0xedcd4dd4
- Solmate: bare revert (require without a reason, or out of gas) 0x00000000
- Balancer: Panic (checked arithmetic overflow or division by zero) 0x4e487b71
- Solady: Solady ExpOverflow() 0xa37bfec9
- Solmate: Error(string): a require with a message (Solmate's wadLn and snekmate's wad_ln below zero) 0x08c379a0
- PRB SD: PRBMath_SD59x18_Exp_InputTooBig 0xca7ec0c5
- PRB UD: PRBMath_UD60x18_Exp_InputTooBig 0x1af63aca
- snek: Error(string): a require with a message (Solmate's wadLn and snekmate's wad_ln below zero) 0x08c379a0
- Balancer: Balancer InvalidExponent() 0xd4794efd
Full dataset: ladder.json. Regenerate with make ladder.