Ladder
13 scenarios, 87 inputs, N from 1 to 10,000, every cell against 200-digit arithmetic.
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.
9,384 cells checked live on Sepolia at block 11,928,247, 0 mismatches. 2026-10-16, runner 0xfcdf2f18…. 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 and the decay); the bonding curve, the amortising loan and the Black-Scholes chain are stepped.
- rounding
- Each library receives the parameters floored into its own representation (2^-128, 2^-64, 10^-18 or 10^-27 units, or the nearest float for ABDKMathQuad and FP256; scripts/ladder/inputs.json). truthFormat is the exact loop started from those floored 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.
- digits
- digits = floor(-log10 |v - t| / |t|), the number of correct leading significant digits by relative error, capped at 100, which is reported as exact. 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.
- 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 FP127 object, so the call into the adapter and the ABI decoding are excluded. The FP127 (deployed) form includes one staticcall per op; FP127Lib and the other libraries are internal calls. Aave, Morpho and Maker answer only the accrual scenarios their models describe and report Unsupported elsewhere, which the tables show as 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-15; versions: aave aave-v3-origin@8305565ae342 (MathUtils, transcribed), abdk v3.2, balancer balancer-v3-monorepo@2b9ce4b1b8ad (LogExpMath.sol, vendored), forge forge Version: 1.7.1, fp127 60e7ec3, huff sepolia:0xfae694D0c2c44181791F838c54Ed64C3151FfE30@11857616, maker dss pot.sol rpow via solady v0.1.26, morpho morpho-blue@8e26ca6a8dbc (MathLib, transcribed), prb-math v4.2.0, solady v0.1.26.
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
| N | FP127 | FP127Lib | ABDK | Solady | PRBMath | Quad | Balancer | Aave | Morpho | Maker | FP256 | |||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 1 | 38 | 80 | 38 | 80 | 19 | 80 | 18 | 80 | 18 | 80 | 33 | 33 | 18 | 80 | — | — | — | — | 27 | 80 | 71 | 71 |
| 2 | 38 | 42 | 38 | 42 | 19 | 23 | 18 | 22 | 18 | 22 | 33 | 33 | 18 | 22 | — | — | — | — | 26 | 27 | 71 | 71 |
| 5 | 38 | 42 | 38 | 42 | 18.5 | 22.5 | 18 | 21 | 18 | 21 | 33 | 33 | 18 | 21 | — | — | — | — | 26 | 27 | 70 | 70 |
| 10 | 37 | 41 | 37 | 41 | 18 | 22 | 17 | 21 | 17 | 21 | 32 | 32 | 17 | 21 | — | — | — | — | 26 | 26 | 70 | 70 |
| 20 | 37 | 41 | 37 | 41 | 18 | 22 | 17 | 21 | 17 | 21 | 32 | 32 | 17 | 21 | — | — | — | — | 26 | 26 | 70 | 70 |
| 50 | 37 | 41 | 37 | 41 | 17.5 | 21 | 17 | 20 | 17 | 20 | 32 | 32 | 17 | 20 | — | — | — | — | 25 | 26 | 69 | 69 |
| 100 | 36 | 40 | 36 | 40 | 17 | 21 | 16 | 20 | 16 | 20 | 31 | 31 | 16 | 20 | — | — | — | — | 25 | 25 | 69 | 69 |
| 365 | 36 | 40 | 36 | 40 | 16.5 | 21 | 16 | 19 | 16 | 19 | 31 | 31 | 16 | 19 | — | — | — | — | 24 | 25 | 68 | 68 |
| 1000 | 35 | 39 | 35 | 39 | 16 | 20 | 15 | 19 | 15 | 19 | 30 | 30 | 15 | 19 | — | — | — | — | 24 | 24 | 68 | 68 |
| 10000 | 34 | 39 | 34 | 39 | 15 | 19.5 | 14 | 18 | 14 | 18 | 29 | 29 | 14 | 18 | — | — | — | — | 23 | 23 | 67 | 67 |
Median (min–max) correct digits over the inputs, capped at 80; "rev" counts inputs that reverted at that N and are excluded.
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: FP127 mul; FP127Lib mul; ABDK mul; Solady sMulWad; PRBMath mul; Quad mul; Balancer mulDown; Aave unsupported; Morpho unsupported; Maker rpow, rmul; FP256 mul. Parameters reach each adapter floored into its representation (ladder-inputs.json).
The reference input in full: principal = 10000, rate = 0.1/365
Each cell: the value with the digits that agree with the truth in ink and the rest in red; below it, correct digits against the exact truth, against the format-rounded truth, the signed error in units of the last place, and gas per step.
| N | truth | FP127 (deployed, staticcall) | FP127Lib (inline) | ABDKMath64x64 | Solady FixedPointMathLib | PRBMath SD59x18 | ABDKMathQuad (binary128) | Balancer LogExpMath | Aave v3 MathUtils (RAY) | Morpho Blue MathLib | Maker rpow (RAY) | FP256 (float, inline) |
|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 1 | 10002.7397260273972602739726027397260273973 | 10002.7397260273972602739726027397260273831 |
10002.7397260273972602739726027397260273831 |
10002.7397260273972600785191700012433102529 |
10002.73972602739726 |
10002.73972602739726 |
10002.7397260273972602739726027397248603154 |
10002.73972602739726 |
reverts | reverts | 10002.7397260273972602739726 |
10002.7397260273972602739726027397260273973 |
| 2 | 10005.4802026646650403452805404391067742541 | 10005.4802026646650403452805404391067742258 |
10005.4802026646650403452805404391067742258 |
10005.4802026646650399542451230494588543252 |
10005.480202664665039797 |
10005.480202664665039797 |
10005.480202664665040345280540439104093104 |
10005.480202664665039797 |
reverts | reverts | 10005.48020266466504034528053 |
10005.4802026646650403452805404391067742541 |
| 5 | 10013.7061382924386210524857642965155424808 | 10013.7061382924386210524857642965155424101 |
10013.7061382924386210524857642965155424101 |
10013.7061382924386200740608440784562560566 |
10013.706138292438619679 |
10013.706138292438619679 |
10013.7061382924386210524857642965089797718 |
10013.706138292438619679 |
reverts | reverts | 10013.70613829243862105248574 |
10013.7061382924386210524857642965155424808 |
| 10 | 10027.4310624075663873328585783270357249574 | 10027.4310624075663873328585783270357248157 |
10027.4310624075663873328585783270357248157 |
10027.4310624075663853733086060271428863189 |
10027.431062407566384582 |
10027.431062407566384582 |
10027.43106240756638733285857832702353373 |
10027.431062407566384582 |
reverts | reverts | 10027.43106240756638733285853 |
10027.4310624075663873328585783270357249574 |
| 20 | 10054.9373711336135548503369243222913751056 | 10054.9373711336135548503369243222913748213 |
10054.9373711336135548503369243222913748213 |
10054.937371133613550920398935217825453492 |
10054.937371133613549333 |
10054.937371133613549333 |
10054.9373711336135548503369243222684323598 |
10054.937371133613549333 |
reverts | reverts | 10054.93737113361355485033684 |
10054.9373711336135548503369243222913751056 |
| 50 | 10137.9098421416552959332725454243516547326 | 10137.909842141655295933272545424351654016 |
10137.909842141655295933272545424351654016 |
10137.9098421416552860271844023476450757926 |
10137.909842141655282022 |
10137.909842141655282022 |
10137.9098421416552959332725454242952441686 |
10137.909842141655282022 |
reverts | reverts | 10137.90984214165529593327234 |
10137.9098421416552959332725454243516547326 |
| 100 | 10277.721596739264220164675884991779643531 | 10277.7215967392642201646758849917796420782 |
10277.7215967392642201646758849917796420782 |
10277.7215967392642000792805576092625585716 |
10277.721596739264191958 |
10277.721596739264191958 |
10277.7215967392642201646758849916676515892 |
10277.721596739264191958 |
reverts | reverts | 10277.72159673926422016467546 |
10277.721596739264220164675884991779643531 |
| 365 | 11051.5578161626437393801159668054461177946 | 11051.5578161626437393801159668054461120925 |
11051.5578161626437393801159668054461120925 |
11051.5578161626436605492209384882240641446 |
11051.557816162643628692 |
11051.557816162643628692 |
11051.5578161626437393801159668049905361029 |
11051.557816162643628692 |
reverts | reverts | 11051.5578161626437393801143 |
11051.5578161626437393801159668054461177946 |
| 1000 | 13151.2942008121758666272801482974151894245 | 13151.2942008121758666272801482974151708344 |
13151.2942008121758666272801482974151708344 |
13151.294200812175609621539323218497585799 |
13151.294200812175505839 |
13151.294200812175505839 |
13151.2942008121758666272801482960083685618 |
13151.294200812175505839 |
reverts | reverts | 13151.29420081217586662727473 |
13151.2942008121758666272801482974151894245 |
| 10000 | 154769.34069144112806190764064318746174622 | 154769.340691441128061907640643187459558592 |
154769.340691441128061907640643187459558592 |
154769.340691441097818583337575315539424992 |
154769.340691441085644663 |
154769.340691441085644663 |
154769.340691441128061907640643019251346999 |
154769.340691441085644663 |
reverts | reverts | 154769.34069144112806190700363 |
154769.34069144112806190764064318746174622 |
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
| N | FP127 | FP127Lib | ABDK | Solady | PRBMath | Quad | Balancer | Aave | Morpho | Maker | FP256 | |||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 1 | 38 | 80 | 38 | 80 | 19 | 19 | 17 | 18 | 18 | 80 | 33 | 33 | 17 | 18 | — | — | — | — | — | — | 71 | 71 |
| 2 | 38 | 38 | 38 | 38 | 18 | 18.5 | 17 | 17 | 16 | 16 | 33 | 33 | 17 | 17 | — | — | — | — | — | — | 71 | 71 |
| 5 | 38 | 38 | 38 | 38 | 18 | 18 | 17 | 17 | 16 | 16 | 33 | 33 | 17 | 18 | — | — | — | — | — | — | 70 | 70 |
| 10 | 37 | 39 | 37 | 39 | 18 | 18 | 17 | 17 | 16 | 16 | 33 | 33 | 17 | 18 | — | — | — | — | — | — | 70 | 70 |
| 20 | 37 | 39 | 37 | 39 | 17 | 18 | 16 | 16 | 15 | 15 | 33 | 33 | 17 | 18 | — | — | — | — | — | — | 70 | 70 |
| 50 | 37 | 39 | 37 | 39 | 17 | 17 | 16 | 16 | 15 | 15 | 32 | 32 | 17 | 17 | — | — | — | — | — | — | 69 | 69 |
| 100 | 36 | 39 | 36 | 39 | 17 | 17 | 16 | 16 | 15 | 15 | 32 | 32 | 16 | 17 | — | — | — | — | — | — | 69 | 69 |
| 365 | 36 | 39 | 36 | 39 | 16 | 16.5 | 15 | 15 | 14 | 14 | 31 | 31 | 16 | 17.5 | — | — | — | — | — | — | 68 | 68 |
| 1000 | 35 | 39 | 35 | 39 | 16 | 16 | 15 | 15 | 14 | 14 | 31 | 31 | 15 | 18 | — | — | — | — | — | — | 68 | 68 |
| 10000 | 34 | 40 | 34 | 40 | 15 | 15 | 14 | 14 | 13 | 13 | 30 | 30 | 14.5 | 18 | — | — | — | — | — | — | 67 | 67 |
Median (min–max) correct digits over the inputs, capped at 80; "rev" counts inputs that reverted at that N and are excluded.
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: FP127 pow, mul; FP127Lib pow, mul; ABDK exp, mul, ln (pow = exp(y ln x)); Solady powWad, sMulWad; PRBMath pow, mul; Quad exp(y ln x), mul; Balancer pow, mulDown; Aave unsupported; Morpho unsupported; Maker unsupported; FP256 pow, mul. Parameters reach each adapter floored into its representation (ladder-inputs.json).
The reference input in full: principal = 10000, rate = 0.1/365
Each cell: the value with the digits that agree with the truth in ink and the rest in red; below it, correct digits against the exact truth, against the format-rounded truth, the signed error in units of the last place, and gas per step.
| N | truth | FP127 (deployed, staticcall) | FP127Lib (inline) | ABDKMath64x64 | Solady FixedPointMathLib | PRBMath SD59x18 | ABDKMathQuad (binary128) | Balancer LogExpMath | Aave v3 MathUtils (RAY) | Morpho Blue MathLib | Maker rpow (RAY) | FP256 (float, inline) |
|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 1 | 10002.7397260273972602739726027397260273973 | 10002.7397260273972602739726027397260273831 |
10002.7397260273972602739726027397260273831 |
10002.7397260273972595364180837584910932492 |
10002.73972602739725 |
10002.73972602739726 |
10002.7397260273972602739726027397232825936 |
10002.73972602739725 |
reverts | reverts | reverts | 10002.7397260273972602739726027397260273973 |
| 2 | 10005.4802026646650403452805404391067742541 | 10005.4802026646650403452805404391067742095 |
10005.4802026646650403452805404391067742095 |
10005.4802026646650383841577469645756082173 |
10005.48020266466503 |
10005.48020266466484 |
10005.480202664665040345280540439104093104 |
10005.48020266466503 |
reverts | reverts | reverts | 10005.4802026646650403452805404391067742541 |
| 5 | 10013.7061382924386210524857642965155424808 | 10013.7061382924386210524857642965155424218 |
10013.7061382924386210524857642965155424218 |
10013.7061382924386174642777946885985329573 |
10013.70613829243859 |
10013.70613829243812 |
10013.7061382924386210524857642965105574936 |
10013.70613829243861 |
reverts | reverts | reverts | 10013.7061382924386210524857642965155424808 |
| 10 | 10027.4310624075663873328585783270357249574 | 10027.4310624075663873328585783270357248201 |
10027.4310624075663873328585783270357248201 |
10027.4310624075663802559285620041862330254 |
10027.43106240756634 |
10027.4310624075654 |
10027.4310624075663873328585783270298446172 |
10027.43106240756638 |
reverts | reverts | reverts | 10027.4310624075663873328585783270357249574 |
| 20 | 10054.9373711336135548503369243222913751056 | 10054.9373711336135548503369243222913748266 |
10054.9373711336135548503369243222913748266 |
10054.9373711336135415973444540149728254619 |
10054.93737113361346 |
10054.93737113361157 |
10054.937371133613554850336924322282631856 |
10054.93737113361354 |
reverts | reverts | reverts | 10054.9373711336135548503369243222913751056 |
| 50 | 10137.9098421416552959332725454243516547326 | 10137.9098421416552959332725454243516540042 |
10137.9098421416552959332725454243516540042 |
10137.9098421416552629724383560727574149496 |
10137.90984214165505 |
10137.90984214165031 |
10137.9098421416552959332725454243299540485 |
10137.90984214165528 |
reverts | reverts | reverts | 10137.9098421416552959332725454243516547326 |
| 100 | 10277.721596739264220164675884991779643531 | 10277.7215967392642201646758849917796420803 |
10277.7215967392642201646758849917796420803 |
10277.7215967392641536234942911676171206636 |
10277.72159673926373 |
10277.72159673925412 |
10277.7215967392642201646758849917370713488 |
10277.72159673926418 |
reverts | reverts | reverts | 10277.721596739264220164675884991779643531 |
| 365 | 11051.5578161626437393801159668054461177946 | 11051.5578161626437393801159668054461120828 |
11051.5578161626437393801159668054461120828 |
11051.5578161626434791067405405406987028982 |
11051.55781616264184 |
11051.55781616260411 |
11051.5578161626437393801159668052855700814 |
11051.55781616264362 |
reverts | reverts | reverts | 11051.5578161626437393801159668054461177946 |
| 1000 | 13151.2942008121758666272801482974151894245 | 13151.2942008121758666272801482974151708376 |
13151.2942008121758666272801482974151708376 |
13151.294200812175020048715168297093214278 |
13151.29420081216967 |
13151.29420081204668 |
13151.2942008121758666272801482968934704975 |
13151.2942008121755 |
reverts | reverts | reverts | 13151.2942008121758666272801482974151894245 |
| 10000 | 154769.34069144112806190764064318746174622 | 154769.340691441128061907640643187459558676 |
154769.340691441128061907640643187459558676 |
154769.340691441028485565711836358104847022 |
154769.34069144039984 |
154769.34069142592578 |
154769.340691441128061907640643126283994619 |
154769.34069144108545 |
reverts | reverts | reverts | 154769.34069144112806190764064318746174622 |
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
| N | FP127 | FP127Lib | ABDK | Solady | PRBMath | Quad | Balancer | Aave | Morpho | Maker | FP256 | |||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 1 | 43 | 43 | 43 | 43 | 23 | 23 | 22 | 22 | 22 | 22 | 34 | 34 | 18 | 18 | — | — | — | — | — | — | 72 | 72 |
| 2 | 40 | 40 | 40 | 40 | 20 | 20 | 19 | 19 | 19 | 19 | 34 | 34 | 18 | 18 | — | — | — | — | — | — | 71 | 71 |
| 5 | 40 | 40 | 40 | 40 | 21 | 21 | 19 | 19 | 19 | 19 | 33 | 33 | 18 | 18 | — | — | — | — | — | — | 71 | 71 |
| 10 | 40 | 40 | 40 | 40 | 20 | 20 | 19 | 19 | 19 | 19 | 33 | 33 | 18 | 18 | — | — | — | — | — | — | 71 | 71 |
| 20 | 40 | 40 | 40 | 40 | 21 | 21 | 19 | 19 | 19 | 19 | 33 | 33 | 18 | 18 | — | — | — | — | — | — | 71 | 71 |
| 50 | 40 | 40 | 40 | 40 | 21 | 21 | 19 | 19 | 19 | 19 | 32 | 32 | 18 | 18 | — | — | — | — | — | — | 70 | 70 |
| 100 | 40 | 40 | 40 | 40 | 21 | 21 | 19 | 19 | 19 | 19 | 32 | 32 | 18 | 18 | — | — | — | — | — | — | 70 | 70 |
| 365 | 40 | 40 | 40 | 40 | 21 | 21 | 19 | 19 | 19 | 19 | 31 | 31 | 18 | 18 | — | — | — | — | — | — | 70 | 70 |
| 1000 | 40 | 40 | 40 | 40 | 21 | 21 | 19 | 19 | 19 | 19 | 31 | 31 | 18 | 18 | — | — | — | — | — | — | 70 | 70 |
| 10000 | 40 | 40 | 40 | 40 | 21 | 21 | 20 | 20 | 20 | 20 | 30 | 30 | 18 | 18 | — | — | — | — | — | — | 70 | 70 |
Median (min–max) correct digits over the inputs, capped at 80; "rev" counts inputs that reverted at that N and are excluded.
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: FP127 sqrt, add; FP127Lib sqrt, add; ABDK sqrt, add; Solady sqrtWad, add; PRBMath sqrt, add; Quad sqrt, add; Balancer pow(x, 1/2), add; Aave unsupported; Morpho unsupported; Maker unsupported; FP256 sqrt, add. Parameters reach each adapter floored into its representation (ladder-inputs.json).
The reference input in full: supply = 1000, unit = 1
Each cell: the value with the digits that agree with the truth in ink and the rest in red; below it, correct digits against the exact truth, against the format-rounded truth, the signed error in units of the last place, and gas per step.
| N | truth | FP127 (deployed, staticcall) | FP127Lib (inline) | ABDKMath64x64 | Solady FixedPointMathLib | PRBMath SD59x18 | ABDKMathQuad (binary128) | Balancer LogExpMath | Aave v3 MathUtils (RAY) | Morpho Blue MathLib | Maker rpow (RAY) | FP256 (float, inline) |
|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 1 | 31.6227766016837933199889354443271853371956 | 31.6227766016837933199889354443271853371954 |
31.6227766016837933199889354443271853371954 |
31.6227766016837933199458594846209535944581 |
31.622776601683793319 |
31.622776601683793319 |
31.6227766016837933199889354443271822760817 |
31.622776601683793313 |
reverts | reverts | reverts | 31.6227766016837933199889354443271853371956 |
| 2 | 63.2613606407965424630952270291281684242756 | 63.2613606407965424630952270291281684242738 |
63.2613606407965424630952270291281684242738 |
63.2613606407965424630393536098438289627666 |
63.261360640796542462 |
63.261360640796542462 |
63.2613606407965424630952270291281601345083 |
63.26136064079654243 |
reverts | reverts | reverts | 63.2613606407965424630952270291281684242756 |
| 5 | 158.271878503221320234300570350652186729491 | 158.271878503221320234300570350652186729484 |
158.271878503221320234300570350652186729484 |
158.271878503221320234157706852151648035942 |
158.271878503221320232 |
158.271878503221320232 |
158.271878503221320234300570350652157047843 |
158.271878503221320149 |
reverts | reverts | reverts | 158.271878503221320234300570350652186729491 |
| 10 | 316.938155912380578582534163023823506795788 | 316.938155912380578582534163023823506795773 |
316.938155912380578582534163023823506795773 |
316.938155912380578582243466356782590764851 |
316.938155912380578577 |
316.938155912380578577 |
316.938155912380578582534163023823397966508 |
316.938155912380578369 |
reverts | reverts | reverts | 316.938155912380578582534163023823506795788 |
| 20 | 635.450002940208176168731350846033723899844 | 635.450002940208176168731350846033723899815 |
635.450002940208176168731350846033723899815 |
635.450002940208176168183050458448946073986 |
635.450002940208176158 |
635.450002940208176158 |
635.450002940208176168731350846033258920681 |
635.450002940208175685 |
reverts | reverts | reverts | 635.450002940208176168731350846033723899844 |
| 50 | 1600.35088143869734634844272805794430858922 | 1600.35088143869734634844272805794430858915 |
1600.35088143869734634844272805794430858915 |
1600.35088143869734634698901928895331536751 |
1600.350881438697346324 |
1600.350881438697346324 |
1600.35088143869734634844272805794137163294 |
1600.350881438697344991 |
reverts | reverts | reverts | 1600.35088143869734634844272805794430858922 |
| 100 | 3239.29226451438240670571916593133108873454 | 3239.2922645143824067057191659313310887344 |
3239.2922645143824067057191659313310887344 |
3239.29226451438240670297179918390995112532 |
3239.292264514382406656 |
3239.292264514382406656 |
3239.29226451438240670571916593132005776791 |
3239.292264514382402598 |
reverts | reverts | reverts | 3239.29226451438240670571916593133108873454 |
| 365 | 12536.2620049472952153455284521422191448628 | 12536.2620049472952153455284521422191448622 |
12536.2620049472952153455284521422191448622 |
12536.2620049472952153357631008279149398277 |
12536.262004947295215169 |
12536.262004947295215169 |
12536.2620049472952153455284521420603831495 |
12536.262004947295205758 |
reverts | reverts | reverts | 12536.2620049472952153455284521422191448628 |
| 1000 | 38540.0786548103528040149168003592993412283 | 38540.0786548103528040149168003592993412268 |
38540.0786548103528040149168003592993412268 |
38540.0786548103528039883598592385549608252 |
38540.078654810352803518 |
38540.078654810352803518 |
38540.078654810352804014916800358010846558 |
38540.078654810352774145 |
reverts | reverts | reverts | 38540.0786548103528040149168003592993412283 |
| 10000 | 748008.007615874676777707582886478609217336 | 748008.007615874676777707582886478609217321 |
748008.007615874676777707582886478609217321 |
748008.007615874676777438468874836807742668 |
748008.007615874676772695 |
748008.007615874676772695 |
748008.007615874676777707582886253357595001 |
748008.00761587467625955 |
reverts | reverts | reverts | 748008.007615874676777707582886478609217336 |
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
| N | FP127 | FP127Lib | ABDK | Solady | PRBMath | Quad | Balancer | Aave | Morpho | Maker | FP256 | |||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 1 | 38 | 39 | 38 | 39 | 19 | 19 | 18 | 18 | 17 | 17 | 32.5 | 32.5 | 18 | 18 | — | — | — | — | — | — | 71.5 | 80 |
| 2 | 38 | 39 | 38 | 39 | 18 | 18 | 17 | 17 | 16 | 16 | 32 | 32 | 17 | 17 | — | — | — | — | — | — | 71.5 | 80 |
| 5 | 38 | 39 | 38 | 39 | 18 | 18 | 17 | 17 | 16 | 16 | 32 | 32 | 17 | 17 | — | — | — | — | — | — | 71.5 | 80 |
| 10 | 38 | 39 | 38 | 39 | 17.5 | 17.5 | 17 | 17 | 16 | 16 | 31.5 | 31.5 | 17 | 17 | — | — | — | — | — | — | 71.5 | 80 |
| 20 | 38 | 39 | 38 | 39 | 17 | 17 | 16 | 16 | 15 | 15 | 31 | 31 | 16 | 16 | — | — | — | — | — | — | 71.5 | 80 |
| 50 | 38 | 39 | 38 | 39 | 17 | 17 | 16 | 16 | 15 | 15 | 31 | 31 | 16 | 16 | — | — | — | — | — | — | 71.5 | 80 |
| 100 | 38 | 39 | 38 | 39 | 17 | 17 | 16 | 16 | 15 | 15 | 30.5 | 30.5 | 16 | 16 | — | — | — | — | — | — | 71.5 | 80 |
| 365 | 38 | 39 | 38 | 39 | 16 | 16 | 15 | 15 | 14 | 14 | 30 | 30 | 15 | 15 | — | — | — | — | — | — | 71.5 | 80 |
| 1000 | 38 | 39 | 38 | 39 | 16 | 16 | 15 | 15 | 14 | 14 | 29.5 | 29.5 | 15 | 15 | — | — | — | — | — | — | 71.5 | 80 |
| 10000 | 38 | 39 | 38 | 39 | 15 | 15 | 14 | 14 | 13 | 13 | 28.5 | 28.5 | 14 | 14 | — | — | — | — | — | — | 71.5 | 80 |
Median (min–max) correct digits over the inputs, capped at 80; "rev" counts inputs that reverted at that N and are excluded.
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: FP127 ln, exp; FP127Lib ln, exp; ABDK ln, exp; Solady lnWad, expWad; PRBMath ln, exp; Quad ln, exp; Balancer ln, exp; Aave unsupported; Morpho unsupported; Maker unsupported; FP256 ln, exp. Parameters reach each adapter floored into its representation (ladder-inputs.json).
The reference input in full: x0 = 1.5
Each cell: the value with the digits that agree with the truth in ink and the rest in red; below it, correct digits against the exact truth, against the format-rounded truth, the signed error in units of the last place, and gas per step.
| N | truth | FP127 (deployed, staticcall) | FP127Lib (inline) | ABDKMath64x64 | Solady FixedPointMathLib | PRBMath SD59x18 | ABDKMathQuad (binary128) | Balancer LogExpMath | Aave v3 MathUtils (RAY) | Morpho Blue MathLib | Maker rpow (RAY) | FP256 (float, inline) |
|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 1 | 1.5 | 1.49999999999999999999999999999999999999706 |
1.49999999999999999999999999999999999999706 |
1.49999999999999999989157978275144955659925 |
1.5 |
1.499999999999999982 |
1.49999999999999999999999999999999961481401 |
1.499999999999999998 |
reverts | reverts | reverts | 1.5 |
| 2 | 1.5 | 1.49999999999999999999999999999999999999706 |
1.49999999999999999999999999999999999999706 |
1.49999999999999999978315956550289911319851 |
1.5 |
1.499999999999999966 |
1.49999999999999999999999999999999922962802 |
1.499999999999999996 |
reverts | reverts | reverts | 1.5 |
| 5 | 1.5 | 1.49999999999999999999999999999999999999706 |
1.49999999999999999999999999999999999999706 |
1.49999999999999999934947869650869733959553 |
1.5 |
1.499999999999999919 |
1.49999999999999999999999999999999807407006 |
1.499999999999999992 |
reverts | reverts | reverts | 1.5 |
| 10 | 1.5 | 1.49999999999999999999999999999999999999706 |
1.49999999999999999999999999999999999999706 |
1.49999999999999999864474728439311945749068 |
1.5 |
1.499999999999999834 |
1.49999999999999999999999999999999614814011 |
1.499999999999999984 |
reverts | reverts | reverts | 1.5 |
| 20 | 1.5 | 1.49999999999999999999999999999999999999706 |
1.49999999999999999999999999999999999999706 |
1.49999999999999999718107435153768847158062 |
1.5 |
1.499999999999999678 |
1.49999999999999999999999999999999229628022 |
1.499999999999999969 |
reverts | reverts | reverts | 1.5 |
| 50 | 1.5 | 1.49999999999999999999999999999999999999706 |
1.49999999999999999999999999999999999999706 |
1.49999999999999999279005555297139551385044 |
1.5 |
1.499999999999999206 |
1.49999999999999999999999999999998074070056 |
1.499999999999999924 |
reverts | reverts | reverts | 1.5 |
| 100 | 1.5 | 1.49999999999999999999999999999999999999706 |
1.49999999999999999999999999999999999999706 |
1.49999999999999998552590099731851580600051 |
1.5 |
1.499999999999998394 |
1.49999999999999999999999999999996148140111 |
1.499999999999999849 |
reverts | reverts | reverts | 1.5 |
| 365 | 1.5 | 1.49999999999999999999999999999999999999706 |
1.49999999999999999999999999999999999999706 |
1.49999999999999994681988343958600751193444 |
1.5 |
1.499999999999994003 |
1.49999999999999999999999999999985940711406 |
1.499999999999999452 |
reverts | reverts | reverts | 1.5 |
| 1000 | 1.5 | 1.49999999999999999999999999999999999999706 |
1.49999999999999999999999999999999999999706 |
1.4999999999999998541748078006996536259976 |
1.5 |
1.49999999999998402 |
1.49999999999999999999999999999961481401112 |
1.499999999999998499 |
reverts | reverts | reverts | 1.5 |
| 10000 | 1.5 | 1.49999999999999999999999999999999999999706 |
1.49999999999999999999999999999999999999706 |
1.49999999999999854104334659488095837787114 |
1.5 |
1.499999999999839112 |
1.49999999999999999999999999999614814011123 |
1.499999999999984999 |
reverts | reverts | reverts | 1.5 |
Amortising loan
Step: b = b * (1 + r) - payment. Result: outstanding balance after N daily payments.
Subtracting nearly equal numbers. The payment retires the loan at step 366, so at N = 365 the balance is one payment and relative error is amplified several hundred times.
Over all 8 inputs
| N | FP127 | FP127Lib | ABDK | Solady | PRBMath | Quad | Balancer | Aave | Morpho | Maker | FP256 | |||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 1 | 39 | 80 | 39 | 80 | 20 | 80 | 19 | 80 | 19 | 80 | 33 | 33 | 19 | 80 | — | — | — | — | — | — | 71 | 71 |
| 2 | 38 | 44 | 38 | 44 | 19 | 24 | 19 | 23 | 19 | 23 | 33 | 33 | 19 | 23 | — | — | — | — | — | — | 71 | 71 |
| 5 | 38 | 43 | 38 | 43 | 19 | 24 | 19 | 23 | 19 | 23 | 32 | 32 | 19 | 23 | — | — | — | — | — | — | 70 | 70 |
| 10 | 38 | 43 | 38 | 43 | 19 | 24 | 18 | 22 | 18 | 22 | 32 | 32 | 18 | 22 | — | — | — | — | — | — | 70 | 70 |
| 20 | 37 | 42.5 | 37 | 42.5 | 18 | 23 | 18 | 22 | 18 | 22 | 32 | 32 | 18 | 22 | — | — | — | — | — | — | 70 | 70 |
| 50 | 37 | 42 | 37 | 42 | 18 | 23 | 18 | 22 | 18 | 22 | 31 | 31 | 18 | 22 | — | — | — | — | — | — | 69 | 69 |
| 100 | 37 | 42 | 37 | 42 | 17 | 22 | 17 | 21 | 17 | 21 | 31 | 31 | 17 | 21 | — | — | — | — | — | — | 69 | 69 |
| 365 | 34 | 39 | 34 | 39 | 15 | 19 | 14.5 | 18 | 14.5 | 18 | 28 | 28 | 14.5 | 18 | — | — | — | — | — | — | 66 | 66 |
| 1000 | 36 | 41 | 36 | 41 | 17 | 21.5 | 16.5 | 20.5 | 16.5 | 20.5 | 31 | 31 | 16.5 | 20.5 | — | — | — | — | — | — | 69 | 69 |
| 10000 | 35 | 40.5 | 35 | 40.5 | 15.5 | 21.5 | 15.5 | 21 | 15.5 | 21 | 29 | 29 | 15.5 | 21 | — | — | — | — | — | — | 67 | 67 |
Median (min–max) correct digits over the inputs, capped at 80; "rev" counts inputs that reverted at that N and are excluded.
The inputs and the ops
| input | parameters | why |
|---|---|---|
| reference | principal = 300000, rate = 0.05/365, term = 366; payment = principal * rate / (1 - (1 + rate)^(-term)) | a mortgage-sized loan retiring at step 366 |
| small | principal = 10000, rate = 0.05/365, term = 366; payment = principal * rate / (1 - (1 + rate)^(-term)) | a small loan |
| high-rate | principal = 300000, rate = 0.1/365, term = 366; payment = principal * rate / (1 - (1 + rate)^(-term)) | double the rate |
| ten-year | principal = 300000, rate = 0.05/365, term = 3650; payment = principal * rate / (1 - (1 + rate)^(-term)) | a ten-year term: at N = 365 nine tenths remain |
| large-low | principal = 1000000, rate = 0.03/365, term = 366; payment = principal * rate / (1 - (1 + rate)^(-term)) | a large loan at a low rate |
| very-high | principal = 300000, rate = 0.2/365, term = 366; payment = principal * rate / (1 - (1 + rate)^(-term)) | 20% APR |
| micro | principal = 500, rate = 0.05/365, term = 366; payment = principal * rate / (1 - (1 + rate)^(-term)) | a tiny loan: the payment is a few units |
| retires-at-10001 | principal = 300000, rate = 0.05/365, term = 10001; payment = principal * rate / (1 - (1 + rate)^(-term)) | retires one step past the ladder's end, so N = 10,000 is the one-payment cell |
Library calls per step: FP127 mul, sub; FP127Lib mul, sub; ABDK mul, sub; Solady sMulWad, sub; PRBMath mul, sub; Quad mul, sub; Balancer mulDown, sub; Aave unsupported; Morpho unsupported; Maker unsupported; FP256 mul, sub. Parameters reach each adapter floored into its representation (ladder-inputs.json).
The reference input in full: principal = 300000, rate = 0.05/365, term = 366
Each cell: the value with the digits that agree with the truth in ink and the rest in red; below it, correct digits against the exact truth, against the format-rounded truth, the signed error in units of the last place, and gas per step.
| N | truth | FP127 (deployed, staticcall) | FP127Lib (inline) | ABDKMath64x64 | Solady FixedPointMathLib | PRBMath SD59x18 | ABDKMathQuad (binary128) | Balancer LogExpMath | Aave v3 MathUtils (RAY) | Morpho Blue MathLib | Maker rpow (RAY) | FP256 (float, inline) |
|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 1 | 299200.647990355892260602435720377950399328 | 299200.647990355892260602435720377950399116 |
299200.647990355892260602435720377950399116 |
299200.647990355892257670659354490405590354 |
299200.647990355892256493 |
299200.647990355892256493 |
299200.647990355892260602435720377827909005 |
299200.647990355892256493 |
reverts | reverts | reverts | 299200.647990355892260602435720377950399328 |
| 2 | 298401.186480436490807815912870306637504191 | 298401.186480436490807815912870306637503767 |
298401.186480436490807815912870306637503767 |
298401.186480436490801959744604415769586581 |
298401.186480436490799607 |
298401.186480436490799607 |
298401.186480436490807815912870306394512417 |
298401.186480436490799607 |
reverts | reverts | reverts | 298401.186480436490807815912870306637504191 |
| 5 | 296002.14479901587277453479645551265335414 | 296002.144799015872774534796455512653353085 |
296002.144799015872774534796455512653353085 |
296002.144799015872759949917492061643997658 |
296002.14479901587275409 |
296002.14479901587275409 |
296002.14479901587277453479645551210093214 |
296002.14479901587275409 |
reverts | reverts | reverts | 296002.14479901587277453479645551265335414 |
| 10 | 292001.550590734601252336129721761763542342 | 292001.550590734601252336129721761763540245 |
292001.550590734601252336129721761763540245 |
292001.55059073460122335180776456664553109 |
292001.550590734601211706 |
292001.550590734601211706 |
292001.550590734601252336129721760665355576 |
292001.550590734601211706 |
reverts | reverts | reverts | 292001.550590734601252336129721761763542342 |
| 20 | 283992.137644809178562284250368709832406964 | 283992.137644809178562284250368709832402825 |
283992.137644809178562284250368709832402825 |
283992.137644809178505058517780201832181319 |
283992.137644809178482065 |
283992.137644809178482065 |
283992.137644809178562284250368707754318788 |
283992.137644809178482065 |
reverts | reverts | reverts | 283992.137644809178562284250368709832406964 |
| 50 | 259897.967206003300994908944979016288932429 | 259897.967206003300994908944979016288922485 |
259897.967206003300994908944979016288922485 |
259897.96720600330085743730115094285437749 |
259897.967206003300802194 |
259897.967206003300802194 |
259897.967206003300994908944979011264557986 |
259897.967206003300802194 |
reverts | reverts | reverts | 259897.967206003300994908944979016288932429 |
| 100 | 219520.339088217564302677320754471630738482 | 219520.339088217564302677320754471630719953 |
219520.339088217564302677320754471630719953 |
219520.339088217564046516289567173574326375 |
219520.339088217563943577 |
219520.339088217563943577 |
219520.339088217564302677320754463555623545 |
219520.339088217563943577 |
reverts | reverts | reverts | 219520.339088217564302677320754471630738482 |
| 365 | 840.332785974796123490236849916581575798202 | 840.332785974796123490236849916581535234713 |
840.332785974796123490236849916581535234713 |
840.332785974795562720213691620951834693187 |
840.332785974795337317 |
840.332785974795337317 |
840.332785974796123490236849899778912354514 |
840.332785974795337317 |
reverts | reverts | reverts | 840.332785974796123490236849916581575798202 |
| 1000 | -556627.388400841571518712768710676765307471 | -556627.388400841571518712768710676765225396 |
-556627.388400841571518712768710676765225396 |
-556627.388400841570384060383227392554417179 |
-556627.388400841569927932 |
-556627.388400841569927932 |
-556627.388400841571518712768710656833355199 |
-556627.388400841569927932 |
reverts | reverts | reverts | -556627.388400841571518712768710676765307471 |
| 10000 | -16823263.3532103472394141655896251577011087 | -16823263.3532103472394141655896251576317416 |
-16823263.3532103472394141655896251576317416 |
-16823263.3532103462804450766778299741766034 |
-16823263.353210345895187359 |
-16823263.353210345895187359 |
-16823263.3532103472394141655896036031306915 |
-16823263.353210345895187359 |
reverts | reverts | reverts | -16823263.3532103472394141655896251577011087 |
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
| N | FP127 | FP127Lib | ABDK | Solady | PRBMath | Quad | Balancer | Aave | Morpho | Maker | FP256 | |||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 1 | 38 | 38 | 38 | 38 | 19 | 19 | 80 | 80 | 16 | 16 | 33 | 33 | 17 | 17 | — | — | — | — | — | — | 80 | 80 |
| 2 | 38 | 38 | 38 | 38 | 18 | 18 | 17 | 17 | 16 | 16 | 33 | 33 | 17 | 17 | — | — | — | — | — | — | 71 | 71 |
| 5 | 38 | 38 | 38 | 38 | 19 | 19 | 17 | 17 | 16 | 16 | 33 | 33 | 17 | 17 | — | — | — | — | — | — | 71 | 71 |
| 10 | 38 | 38 | 38 | 38 | 18 | 18 | 17 | 17 | 16 | 16 | 33 | 33 | 17 | 17 | — | — | — | — | — | — | 71 | 71 |
| 20 | 38 | 38 | 38 | 38 | 18 | 18 | 17 | 17 | 16 | 16 | 33 | 33 | 17 | 17 | — | — | — | — | — | — | 72 | 72 |
| 50 | 38 | 38 | 38 | 38 | 18 | 18 | 17 | 17 | 16 | 16 | 33 | 33 | 17 | 17 | — | — | — | — | — | — | 71 | 71 |
| 100 | 39 | 39 | 39 | 39 | 18 | 18 | 17 | 17 | 16 | 16 | 33 | 33 | 17 | 17 | — | — | — | — | — | — | 71 | 71 |
| 365 | 38 | 38 | 38 | 38 | 18 | 18 | 17 | 17 | 16 | 16 | 33 | 33 | 17 | 17 | — | — | — | — | — | — | 71 | 71 |
| 1000 | 39 | 39 | 39 | 39 | 18 | 18 | 17 | 17 | 16 | 16 | 33 | 33 | 17 | 17 | — | — | — | — | — | — | 72 | 72 |
| 10000 | 38 | 38 | 38 | 38 | 18 | 18 | 17 | 17 | 16 | 16 | 33 | 33 | 17 | 17 | — | — | — | — | — | — | 71 | 71 |
Median (min–max) correct digits over the inputs, capped at 80; "rev" counts inputs that reverted at that N and are excluded.
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: FP127 div, ln, add, exp; FP127Lib div, ln, add, exp; ABDK div, ln, add, exp; Solady sDivWad, lnWad, add, expWad; PRBMath div, ln, add, exp; Quad div, ln, add, exp; Balancer divDown, ln, add, exp; Aave unsupported; Morpho unsupported; Maker unsupported; FP256 div, ln, add, exp. Parameters reach each adapter floored into its representation (ladder-inputs.json).
The reference input in full:
Each cell: the value with the digits that agree with the truth in ink and the rest in red; below it, correct digits against the exact truth, against the format-rounded truth, the signed error in units of the last place, and gas per step.
| N | truth | FP127 (deployed, staticcall) | FP127Lib (inline) | ABDKMath64x64 | Solady FixedPointMathLib | PRBMath SD59x18 | ABDKMathQuad (binary128) | Balancer LogExpMath | Aave v3 MathUtils (RAY) | Morpho Blue MathLib | Maker rpow (RAY) | FP256 (float, inline) |
|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 1 | 1.5 | 1.49999999999999999999999999999999999999706 |
1.49999999999999999999999999999999999999706 |
1.49999999999999999989157978275144955659925 |
1.5 |
1.499999999999999982 |
1.49999999999999999999999999999999961481401 |
1.499999999999999998 |
reverts | reverts | reverts | 1.5 |
| 2 | 1.41421356237309504880168872420969807856967 | 1.41421356237309504880168872420969807856606 |
1.41421356237309504880168872420969807856606 |
1.41421356237309504865536785578328249357583 |
1.414213562373095047 |
1.414213562373095034 |
1.41421356237309504880168872420969779175425 |
1.414213562373095047 |
reverts | reverts | reverts | 1.41421356237309504880168872420969807856967 |
| 5 | 1.28473515712343933867943306541867483181504 | 1.28473515712343933867943306541867483181363 |
1.28473515712343933867943306541867483181363 |
1.28473515712343933856945041305230859052244 |
1.284735157123439337 |
1.284735157123439324 |
1.28473515712343933867943306541867435790427 |
1.284735157123439337 |
reverts | reverts | reverts | 1.28473515712343933867943306541867483181504 |
| 10 | 1.19623119885131548973381914341377367153755 | 1.19623119885131548973381914341377367153437 |
1.19623119885131548973381914341377367153437 |
1.19623119885131548953026078829786627011345 |
1.196231198851315488 |
1.196231198851315477 |
1.19623119885131548973381914341377331359046 |
1.196231198851315488 |
reverts | reverts | reverts | 1.19623119885131548973381914341377367153755 |
| 20 | 1.12737820415783302414307801981343475345086 | 1.12737820415783302414307801981343475344916 |
1.12737820415783302414307801981343475344916 |
1.12737820415783302402173635115012473306706 |
1.127378204157833022 |
1.127378204157833012 |
1.12737820415783302414307801981343445385091 |
1.127378204157833022 |
reverts | reverts | reverts | 1.12737820415783302414307801981343475345086 |
| 50 | 1.06733184424855890455496508133611557432867 | 1.06733184424855890455496508133611557432543 |
1.06733184424855890455496508133611557432543 |
1.06733184424855890443106787301985605154186 |
1.067331844248558903 |
1.067331844248558893 |
1.06733184424855890455496508133611529688231 |
1.067331844248558903 |
reverts | reverts | reverts | 1.06733184424855890455496508133611557432867 |
| 100 | 1.04010144984871012198554698020468702744746 | 1.04010144984871012198554698020468702744667 |
1.04010144984871012198554698020468702744667 |
1.04010144984871012182421276537347409885115 |
1.04010144984871012 |
1.040101449848710111 |
1.04010144984871012198554698020468666440993 |
1.04010144984871012 |
reverts | reverts | reverts | 1.04010144984871012198554698020468702744746 |
| 365 | 1.01438248702624022745474729116356250455137 | 1.01438248702624022745474729116356250454769 |
1.01438248702624022745474729116356250454769 |
1.0143824870262402273362115079358147795574 |
1.014382487026240225 |
1.014382487026240217 |
1.01438248702624022745474729116356196091094 |
1.014382487026240225 |
reverts | reverts | reverts | 1.01438248702624022745474729116356250455137 |
| 1000 | 1.00623596930045890152123699191085464878457 | 1.00623596930045890152123699191085464878384 |
1.00623596930045890152123699191085464878384 |
1.00623596930045890141761782965446059279202 |
1.006235969300458899 |
1.006235969300458891 |
1.00623596930045890152123699191085417921205 |
1.006235969300458899 |
reverts | reverts | reverts | 1.00623596930045890152123699191085464878457 |
| 10000 | 1.00085210215007978718759617264671502942782 | 1.00085210215007978718759617264671502942658 |
1.00085210215007978718759617264671502942658 |
1.00085210215007978706630228926677261824807 |
1.000852102150079785 |
1.000852102150079776 |
1.00085210215007978718759617264671431263658 |
1.000852102150079785 |
reverts | reverts | reverts | 1.00085210215007978718759617264671502942782 |
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
| N | FP127 | FP127Lib | ABDK | Solady | PRBMath | Quad | Balancer | Aave | Morpho | Maker | FP256 | |||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 1 | 37 | 37 | 37 | 37 | 18 | 18 | 17 | 17 | 17 | 17 | 34 | 34 | 17 | 17 | — | — | — | — | — | — | 71 | 71 |
| 2 | 37 | 37 | 37 | 37 | 17.5 | 18 | 17.5 | 17.5 | 16 | 16 | 32.5 | 32.5 | 17 | 17 | — | — | — | — | — | — | 70 | 70 |
| 5 | 37 | 37 | 37 | 37 | 17 | 18 | 17 | 17 | 15.5 | 15.5 | 32 | 32 | 17 | 17 | — | — | — | — | — | — | 70 | 70 |
| 10 | 37 | 37 | 37 | 37 | 17 | 18 | 17 | 17 | 15.5 | 15.5 | 32 | 32 | 17 | 17 | — | — | — | — | — | — | 70 | 70 |
| 20 | 37 | 37 | 37 | 37 | 17.5 | 18 | 17 | 17 | 16 | 16 | 32 | 32 | 17 | 17 | — | — | — | — | — | — | 70 | 70 |
| 50 | 37 | 37 | 37 | 37 | 17.5 | 18 | 17 | 17 | 16 | 16 | 31 | 31 | 17 | 17 | — | — | — | — | — | — | 69 | 69 |
| 100 | 37 | 37.5 | 37 | 37.5 | 17.5 | 18 | 17 | 17 | 16 | 16 | 31 | 31 | 17 | 17 | — | — | — | — | — | — | 69 | 69 |
| 365 | 37 | 37 | 37 | 37 | 17.5 | 18 | 17 | 17 | 16 | 16 | 30.5 | 30.5 | 17 | 17 | — | — | — | — | — | — | 68 | 68 |
| 1000 | 37 | 37.5 | 37 | 37.5 | 17 | 18 | 17 | 17 | 16 | 16 | 30 | 30 | 17 | 17 | — | — | — | — | — | — | 68 | 68 |
| 10000 | 37 | 38 | 37 | 38 | 18 | 18 | 17 | 17 | 16 | 16 | 30 | 30 | 17 | 17 | — | — | — | — | — | — | 67.5 | 67.5 |
Median (min–max) correct digits over the inputs, capped at 80; "rev" counts inputs that reverted at that N and are excluded.
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: FP127 div, ln, add, sqrt, mul; FP127Lib div, ln, add, sqrt, mul; ABDK div, ln, add, sqrt, mul; Solady sDivWad, lnWad, add, sqrtWad, sMulWad; PRBMath div, ln, add, sqrt, mul; Quad div, ln, add, sqrt, mul; Balancer divDown, ln, add, pow(x, 1/2), mulDown; Aave unsupported; Morpho unsupported; Maker unsupported; FP256 div, ln, add, sqrt, mul. Parameters reach each adapter floored into its representation (ladder-inputs.json).
The reference input in full: T = 0.5, r = 0.05, sigma = 0.2, spot = 100, strike = 100, tick = 0.01
Each cell: the value with the digits that agree with the truth in ink and the rest in red; below it, correct digits against the exact truth, against the format-rounded truth, the signed error in units of the last place, and gas per step.
| N | truth | FP127 (deployed, staticcall) | FP127Lib (inline) | ABDKMath64x64 | Solady FixedPointMathLib | PRBMath SD59x18 | ABDKMathQuad (binary128) | Balancer LogExpMath | Aave v3 MathUtils (RAY) | Morpho Blue MathLib | Maker rpow (RAY) | FP256 (float, inline) |
|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 1 | 0.247487373415291633540295526736697163749693 | 0.247487373415291633540295526736697163730619 |
0.247487373415291633540295526736697163730619 |
0.247487373415291633360190565182890054529707 |
0.247487373415291635 |
0.247487373415291635 |
0.247487373415291633540295526736697176149717 |
0.247487373415291633 |
reverts | reverts | reverts | 0.247487373415291633540295526736697163749693 |
| 2 | 0.495681818258787601119016496784504841607013 | 0.49568181825878760111901649678450484156673 |
0.49568181825878760111901649678450484156673 |
0.495681818258787600290932867652671234282025 |
0.495681818258787601 |
0.495681818258787559 |
0.495681818258787601119016496784503462509083 |
0.495681818258787597 |
reverts | reverts | reverts | 0.495681818258787601119016496784504841607013 |
| 5 | 1.24450687446379156294859558697855008088958 | 1.24450687446379156294859558697855008077686 |
1.24450687446379156294859558697855008077686 |
1.24450687446379155986792702792698150915385 |
1.244506874463791555 |
1.244506874463791342 |
1.24450687446379156294859558697854168099986 |
1.244506874463791545 |
reverts | reverts | reverts | 1.24450687446379156294859558697855008088958 |
| 10 | 2.50668346780494102921027404289032901502747 | 2.50668346780494102921027404289032901475369 |
2.50668346780494102921027404289032901475369 |
2.50668346780494102210437926125941032751143 |
2.50668346780494101 |
2.506683467804940505 |
2.50668346780494102921027404289029780119392 |
2.50668346780494099 |
reverts | reverts | reverts | 2.50668346780494102921027404289032901502747 |
| 20 | 5.08401051403297891352661479689167511150537 | 5.08401051403297891352661479689167511088225 |
5.08401051403297891352661479689167511088225 |
5.08401051403297889923552088653480041102739 |
5.084010514032978876 |
5.084010514032977814 |
5.0840105140329789135266147968915545422869 |
5.084010514032978836 |
reverts | reverts | reverts | 5.08401051403297891352661479689167511150537 |
| 50 | 13.2391487646747260018911032773984733598061 | 13.2391487646747260018911032773984733581989 |
13.2391487646747260018911032773984733581989 |
13.23914876467472596450114172283996083479 |
13.239148764674725887 |
13.239148764674722973 |
13.2391487646747260018911032773977398443755 |
13.239148764674725785 |
reverts | reverts | reverts | 13.2391487646747260018911032773984733598061 |
| 100 | 28.237364393266085066216191925904648830649 | 28.2373643932660850662161919259046488271773 |
28.2373643932660850662161919259046488271773 |
28.2373643932660849925468139753892415910741 |
28.23736439326608483 |
28.237364393266079006 |
28.2373643932660850662161919259017616314702 |
28.237364393266084623 |
reverts | reverts | reverts | 28.237364393266085066216191925904648830649 |
| 365 | 136.745450883799826897439024462329942560739 | 136.745450883799826897439024462329942542832 |
136.745450883799826897439024462329942542832 |
136.745450883799826610829741130315184705069 |
136.745450883799826231 |
136.745450883799804954 |
136.745450883799826897439024462292089304604 |
136.745450883799825305 |
reverts | reverts | reverts | 136.745450883799826897439024462329942560739 |
| 1000 | 589.474773952864477005737983804430862752872 | 589.474773952864477005737983804430862672337 |
589.474773952864477005737983804430862672337 |
589.474773952864476086858664533041363142729 |
589.474773952864476583 |
589.474773952864417545 |
589.474773952864477005737983804151811806625 |
589.474773952864472524 |
reverts | reverts | reverts | 589.474773952864477005737983804430862752872 |
| 10000 | 29787.5592875314291664765495822016511063025 | 29787.5592875314291664765495822016511027086 |
29787.5592875314291664765495822016511027086 |
29787.5592875314291460913610626315417562182 |
29787.559287531429310994 |
29787.559287531428723829 |
29787.5592875314291664765495821771299686063 |
29787.559287531429097595 |
reverts | reverts | reverts | 29787.5592875314291664765495822016511063025 |
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
| N | FP127 | FP127Lib | ABDK | Solady | PRBMath | Quad | Balancer | Aave | Morpho | Maker | FP256 | |||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 1 | 38 | 80 | 38 | 80 | 19 | 80 | 80 | 80 | 80 | 80 | 34 | 34 | 80 | 80 | — | — | — | — | — | — | 71 | 71 |
| 2 | 38 | 38 | 38 | 38 | 19 | 19 | 80 | 80 | 80 | 80 | 33 | 33 | 80 | 80 | — | — | — | — | — | — | 71 | 71 |
| 5 | 38 | 38 | 38 | 38 | 18 | 18 | 80 | 80 | 80 | 80 | 33 | 33 | 80 | 80 | — | — | — | — | — | — | 71 | 71 |
| 10 | 37 | 37 | 37 | 37 | 18 | 18 | 18 | 18 | 18 | 18 | 32 | 32 | 18 | 18 | — | — | — | — | — | — | 71 | 71 |
| 20 | 37 | 37 | 37 | 37 | 18 | 18 | 17 | 17 | 17 | 17 | 32 | 32 | 17 | 17 | — | — | — | — | — | — | 70 | 70 |
| 50 | 37 | 37 | 37 | 37 | 17 | 17 | 16 | 16 | 16 | 16 | 32 | 32 | 16 | 16 | — | — | — | — | — | — | 70 | 70 |
| 100 | 36 | 36 | 36 | 36 | 17 | 17 | 16 | 16 | 16 | 16 | 31 | 31 | 16 | 16 | — | — | — | — | — | — | 70 | 70 |
| 365 | 36 | 36 | 36 | 36 | 16 | 16 | 15 | 15 | 15 | 15 | 31 | 31 | 15 | 15 | — | — | — | — | — | — | 69 | 69 |
| 1000 | 35 | 35 | 35 | 35 | 16 | 16 | 15 | 15 | 15 | 15 | 30 | 30 | 15 | 15 | — | — | — | — | — | — | 69 | 70 |
| 10000 | 34 | 34 | 34 | 34 | 15 | 15 | 14 | 14 | 14 | 14 | 29 | 29 | 14 | 14 | — | — | — | — | — | — | 69 | 69 |
Median (min–max) correct digits over the inputs, capped at 80; "rev" counts inputs that reverted at that N and are excluded.
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: FP127 mul; FP127Lib mul; ABDK mul; Solady sMulWad; PRBMath mul; Quad mul; Balancer mulDown; Aave unsupported; Morpho unsupported; Maker unsupported; FP256 mul. Parameters reach each adapter floored into its representation (ladder-inputs.json).
The reference input in full: eps = 0.0001
Each cell: the value with the digits that agree with the truth in ink and the rest in red; below it, correct digits against the exact truth, against the format-rounded truth, the signed error in units of the last place, and gas per step.
| N | truth | FP127 (deployed, staticcall) | FP127Lib (inline) | ABDKMath64x64 | Solady FixedPointMathLib | PRBMath SD59x18 | ABDKMathQuad (binary128) | Balancer LogExpMath | Aave v3 MathUtils (RAY) | Morpho Blue MathLib | Maker rpow (RAY) | FP256 (float, inline) |
|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 1 | 1.0001 | 1.00009999999999999999999999999999999999957 |
1.00009999999999999999999999999999999999957 |
1.00009999999999999999123964644631712417322 |
1.0001 |
1.0001 |
1.00009999999999999999999999999999999815111 |
1.0001 |
reverts | reverts | reverts | 1.0001 |
| 2 | 0.99999999 | 0.999999989999999999999999999999999999999066 |
0.999999989999999999999999999999999999999066 |
0.999999989999999999950967832784698430259596 |
0.99999999 |
0.99999999 |
0.999999989999999999999999999999999863682863 |
0.99999999 |
reverts | reverts | reverts | 0.99999999 |
| 5 | 1.00009997999800010001 | 1.00009997999800010000999999999999999999409 |
1.00009997999800010000999999999999999999409 |
1.00009997999800009986460722077872276258859 |
1.0000999799980001 |
1.0000999799980001 |
1.0000999799980001000099999999999995066009 |
1.0000999799980001 |
reverts | reverts | reverts | 1.00009997999800010001 |
| 10 | 0.9999999500000009999999900000000499999999 | 0.999999950000000999999990000000049999988515 |
0.999999950000000999999990000000049999988515 |
0.999999950000000999714502847304231636371696 |
0.999999950000000997 |
0.999999950000000997 |
0.999999950000000999999990000000048779719584 |
0.999999950000000997 |
reverts | reverts | reverts | 0.9999999500000009999999900000000499999999 |
| 20 | 0.9999999000000044999998800000020999999748 | 0.9999999000000044999998800000020999999476 |
0.9999999000000044999998800000020999999476 |
0.999999900000004499382375011684587207128061 |
0.999999900000004492 |
0.999999900000004492 |
0.999999900000004499999880000002097764127958 |
0.999999900000004492 |
reverts | reverts | reverts | 0.9999999000000044999998800000020999999748 |
| 50 | 0.999999750000029999997700000126499994687 | 0.99999975000002999999770000012649999461417 |
0.99999975000002999999770000012649999461417 |
0.9999997500000299984314680590280488559074 |
0.999999750000029977 |
0.999999750000029977 |
0.99999975000002999999770000012649392197215 |
0.999999750000029977 |
reverts | reverts | reverts | 0.999999750000029999997700000126499994687 |
| 100 | 0.999999500000122499980400002302999788124016 | 0.999999500000122499980400002302999787978012 |
0.999999500000122499980400002302999787978012 |
0.999999500000122497052421760566076613940822 |
0.999999500000122452 |
0.999999500000122452 |
0.999999500000122499980400002302988171046357 |
0.999999500000122452 |
reverts | reverts | reverts | 0.999999500000122499980400002302999788124016 |
| 365 | 1.00009817981964726372164161629041717960188 | 1.00009817981964726372164161629041717909031 |
1.00009817981964726372164161629041717909031 |
1.00009817981964725354870546225605210111098 |
1.000098179819647083 |
1.000098179819647083 |
1.00009817981964726372164161629037401189909 |
1.000098179819647083 |
reverts | reverts | reverts | 1.00009817981964726372164161629041717960188 |
| 1000 | 0.999995000012474979291525730285725552297672 | 0.999995000012474979291525730285725550870416 |
0.999995000012474979291525730285725550870416 |
0.999995000012474951939407674661453029330005 |
0.999995000012474475 |
0.999995000012474475 |
0.999995000012474979291525730285603759470012 |
0.999995000012474475 |
reverts | reverts | reverts | 0.999995000012474979291525730285725552297672 |
| 10000 | 0.999950001249729179425101682297158079008892 | 0.999950001249729179425101682297158064279421 |
0.999950001249729179425101682297158064279421 |
0.999950001249728906329693883803244602859195 |
0.999950001249724158 |
0.999950001249724158 |
0.999950001249729179425101682295945149558818 |
0.999950001249724158 |
reverts | reverts | reverts | 0.999950001249729179425101682297158079008892 |
Annual compounding at 10% (README claim check)
Step: b = b * 1.1. Result: balance after N years.
The old README asserted $25,937.42 true against $25,932.38 for Solady at N = 10 with no source. This row regenerates that number.
Over all 5 inputs
| N | FP127 | FP127Lib | ABDK | Solady | PRBMath | Quad | Balancer | Aave | Morpho | Maker | FP256 | |||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 1 | 38 | 80 | 38 | 80 | 19 | 80 | 80 | 80 | 80 | 80 | 33 | 33 | 80 | 80 | — | — | — | — | 80 | 80 | 80 | 72 |
| 2 | 38 | 77 | 38 | 77 | 19 | 39 | 80 | 80 | 80 | 80 | 33 | 33 | 80 | 80 | — | — | — | — | 80 | 80 | 80 | 72 |
| 5 | 38 | 42 | 38 | 42 | 18 | 23 | 80 | 80 | 80 | 80 | 33 | 33 | 80 | 80 | — | — | — | — | 80 | 80 | 70 | 70 |
| 10 | 37 | 42 | 37 | 42 | 18 | 23 | 80 | 80 | 80 | 80 | 32 | 32 | 80 | 80 | — | — | — | — | 80 | 80 | 70 | 70 |
| 20 | 37 | 42 | 37 | 42 | 18 | 22 | 80 | 80 | 80 | 80 | 32 | 32 | 80 | 80 | — | — | — | — | 80 | 80 | 70 | 70 |
| 50 | 37 | 41 | 37 | 41 | 17 | 22 | 22 | 22 | 22 | 22 | 32 | 32 | 22 | 22 | — | — | — | — | 29 | 29 | 69 | 69 |
| 100 | 36 | 41 | 36 | 41 | 17 | 22 | 22 | 22 | 22 | 22 | 31 | 31 | 22 | 22 | — | — | — | — | 29 | 29 | 69 | 69 |
| 365 | 36 | 41 | 36 | 41 | 16 | 20 | 21.5 | 21.5 | 21.5 | 21.5 | 31 | 31 | 21.5 | 21.5 | — | — | — | — | 28 | 28 | 68 | 68 |
| 1000 | 35 | 41 | 35 | 41 | — | — | 21 | 21 | 21.5 | 21.5 | 30 | 30 | 21 | 21 | — | — | — | — | — | — | 68 | 68 |
| 10000 | — | — | — | — | — | — | — | — | — | — | 29 | 29 | — | — | — | — | — | — | — | — | 67 | 67 |
Median (min–max) correct digits over the inputs, capped at 80; "rev" counts inputs that reverted at that N and are excluded.
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: every library overflows before N = 100 |
Library calls per step: FP127 mul; FP127Lib mul; ABDK mul; Solady sMulWad; PRBMath mul; Quad mul; Balancer mulDown; Aave unsupported; Morpho unsupported; Maker rpow, rmul; FP256 mul. Parameters reach each adapter floored into its representation (ladder-inputs.json).
The reference input in full: principal = 10000, rate = 0.1
Each cell: the value with the digits that agree with the truth in ink and the rest in red; below it, correct digits against the exact truth, against the format-rounded truth, the signed error in units of the last place, and gas per step.
| N | truth | FP127 (deployed, staticcall) | FP127Lib (inline) | ABDKMath64x64 | Solady FixedPointMathLib | PRBMath SD59x18 | ABDKMathQuad (binary128) | Balancer LogExpMath | Aave v3 MathUtils (RAY) | Morpho Blue MathLib | Maker rpow (RAY) | FP256 (float, inline) |
|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 1 | 11000.0 | 10999.9999999999999999999999999999999999824 |
10999.9999999999999999999999999999999999824 |
10999.9999999999999996747393482543486697978 |
11000.0 |
11000.0 |
10999.9999999999999999999999999999984222782 |
11000.0 |
reverts | reverts | 11000.0 |
11000.0 |
| 2 | 12100.0 | 12099.9999999999999999999999999999999999612 |
12099.9999999999999999999999999999999999612 |
12099.9999999999999992844265661595670735551 |
12100.0 |
12100.0 |
12099.9999999999999999999999999999968445564 |
12100.0 |
reverts | reverts | 12100.0 |
12100.0 |
| 5 | 16105.1 | 16105.0999999999999999999999999999999998709 |
16105.0999999999999999999999999999999998709 |
16105.0999999999999976188968728307848721215 |
16105.1 |
16105.1 |
16105.0999999999999999999999999999876937699 |
16105.1 |
reverts | reverts | 16105.1 |
16105.1 |
| 10 | 25937.424601 | 25937.4246009999999999999999999999999995842 |
25937.4246009999999999999999999999999995842 |
25937.4246009999999923303156020015780569565 |
25937.424601 |
25937.424601 |
25937.4246009999999999999999999999543604713 |
25937.424601 |
reverts | reverts | 25937.424601 |
25937.424601 |
| 20 | 67274.9994932560009201 | 67274.9994932560009200999999999999999978432 |
67274.9994932560009200999999999999999978432 |
67274.9994932560008803138352877215577763081 |
67274.9994932560009201 |
67274.9994932560009201 |
67274.9994932560009200999999999997671187464 |
67274.9994932560009201 |
reverts | reverts | 67274.9994932560009201 |
67274.9994932560009201 |
| 50 | 1173908.52879695316506666495990358319938982 | 1173908.52879695316506666495990358319929573 |
1173908.52879695316506666495990358319929573 |
1173908.52879695316333107199969348899415422 |
1173908.528796953165066617 |
1173908.528796953165066617 |
1173908.52879695316506666495990357292852018 |
1173908.528796953165066617 |
reverts | reverts | 1173908.5287969531650666649599 |
1173908.52879695316506666495990358319938982 |
| 100 | 137806123.398222701841183371720896367762643 | 137806123.398222701841183371720896367740554 |
137806123.398222701841183371720896367740554 |
137806123.398222701433700108702637421309589 |
137806123.398222701841177177 |
137806123.398222701841177177 |
137806123.39822270184118337172089399648371 |
137806123.398222701841177177 |
reverts | reverts | 137806123.39822270184118337172017 |
137806123.398222701841183371720896367762643 |
| 365 | 12833055803133526968.9944800789796565545148 | 12833055803133526968.9944800789796565470065 |
12833055803133526968.9944800789796565470065 |
reverts | 12833055803133526968.993902795476311067 |
12833055803133526968.993902795476311067 |
12833055803133526968.9944800789788530437363 |
12833055803133526968.993902795476311067 |
reverts | reverts | 12833055803133526968.9944800782719799783126 |
12833055803133526968.9944800789796565545148 |
| 1000 | 2.46993291800582633412408838508522147770973e+45 | reverts | reverts | reverts | reverts | 2.46993291800582633412397727736857096657984e+45 |
2.46993291800582633412408838508478949012537e+45 |
reverts | reverts | reverts | reverts | 2.46993291800582633412408838508522147770973e+45 |
| 10000 | 8.44990025120034795728149043293472294488798e+417 | reverts | reverts | reverts | reverts | reverts | 8.44990025120034795728149043291992031813128e+417 |
reverts | reverts | reverts | reverts | 8.44990025120034795728149043293472294488798e+417 |
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; FP127 computes the power as one exact integer power (compound), the WAD and 64.64 libraries as exp(n ln(1 + r)), Maker as rpow.
Over all 6 inputs
| N | FP127 | FP127Lib | ABDK | Solady | PRBMath | Quad | Balancer | Aave | Morpho | Maker | FP256 | |||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 1 | 33 | 39 | 33 | 39 | 14 | 14 | 12.5 | 13 | 12 | 12 | 28 | 28 | 13 | 17.5 | — | — | — | — | 22 | 22 | 66 | 66 |
| 2 | 33 | 38 | 33 | 38 | 13 | 14 | 12 | 12 | 11 | 11 | 28 | 28 | 12.5 | 17 | — | — | — | — | 22 | 22 | 66 | 66 |
| 5 | 33 | 39 | 33 | 39 | 13 | 13 | 12 | 12 | 11 | 11 | 28 | 28 | 12.5 | 17.5 | — | — | — | — | 21 | 21.5 | 65 | 65 |
| 10 | 32 | 39 | 32 | 39 | 13 | 13 | 11.5 | 12 | 11 | 11 | 27 | 27 | 12 | 17.5 | — | — | — | — | 21 | 21 | 65 | 65 |
| 20 | 32 | 38 | 32 | 38 | 12 | 13 | 11 | 11 | 10 | 10 | 27 | 27 | 11.5 | 18 | — | — | — | — | 21 | 21 | 65 | 65 |
| 50 | 32 | 39 | 32 | 39 | 12 | 12 | 11 | 11 | 10 | 10 | 27 | 27 | 11.5 | 18 | — | — | — | — | 20 | 20.5 | 64 | 64 |
| 100 | 31 | 39 | 31 | 39 | 12 | 12 | 10.5 | 11 | 10 | 10 | 26 | 26 | 11 | 18 | — | — | — | — | 20 | 20 | 64 | 64 |
| 365 | 31 | 39 | 31 | 39 | 11 | 11 | 10 | 10 | 9 | 9 | 26 | 26 | 10.5 | 18 | — | — | — | — | 19 | 20 | 63.5 | 63.5 |
| 1000 | 30 | 38.5 | 30 | 38.5 | 11 | 11 | 9.5 | 10 | 9 | 9 | 25 | 25 | 10 | 18 | — | — | — | — | 19 | 19 | 63 | 63 |
| 10000 | 29 | 40 | 29 | 40 | 10 | 10 | 8.5 | 9 | 8 | 8 | 24 | 24 | 9 | 18 | — | — | — | — | 18 | 18 | 62 | 62 |
Median (min–max) correct digits over the inputs, capped at 80; "rev" counts inputs that reverted at that N and are excluded.
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: FP127 compound, mul; FP127Lib compound, mul; ABDK ln, mul, exp; Solady powWad, sMulWad; PRBMath pow, mul; Quad ln, mul, exp; Balancer pow, mulDown; Aave unsupported; Morpho unsupported; Maker rpow, rmul; FP256 pow, mul. Parameters reach each adapter floored into its representation (ladder-inputs.json).
The reference input in full: principal = 10000, rateSec = 0.05/31536000
Each cell: the value with the digits that agree with the truth in ink and the rest in red; below it, correct digits against the exact truth, against the format-rounded truth, the signed error in units of the last place, and gas per step.
| N | truth | FP127 (deployed, staticcall) | FP127Lib (inline) | ABDKMath64x64 | Solady FixedPointMathLib | PRBMath SD59x18 | ABDKMathQuad (binary128) | Balancer LogExpMath | Aave v3 MathUtils (RAY) | Morpho Blue MathLib | Maker rpow (RAY) | FP256 (float, inline) |
|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 1 | 10001.3699568431307942024761884151451229546 | 10001.3699568431307942024761884151438388605 |
10001.3699568431307942024761884151438388605 |
10001.3699568430573376724354583977572019649 |
10001.369956842326 |
10001.36995683515467 |
10001.369956843130794202476188261990122001 |
10001.36995684296813 |
reverts | reverts | 10001.36995684313079420207488 |
10001.3699568431307942024761884151451229546 |
| 2 | 10002.7401013644367924940998199373753631246 | 10002.7401013644367924940998199373727946122 |
10002.7401013644367924940998199373727946122 |
10002.7401013642898598829042433600022832252 |
10002.74010136282699 |
10002.74010134848237 |
10002.740101364436792494099819631025612394 |
10002.74010136411143 |
reverts | reverts | 10002.74010136443679249329706 |
10002.7401013644367924940998199373753631246 |
| 5 | 10006.851661254534624362262641758190829368 | 10006.8516612545346243622626417581844054175 |
10006.8516612545346243622626417581844054175 |
10006.851661254167143054114030853440908686 |
10006.85166125050847 |
10006.85166121463218 |
10006.8516612545346243622626409920059179602 |
10006.85166125372091 |
reverts | reverts | 10006.85166125453462436025495 |
10006.851661254534624362262641758190829368 |
| 10 | 10013.7080170352639378227825839791637869183 | 10013.7080170352639378227825839791509301991 |
10013.7080170352639378227825839791509301991 |
10013.7080170345284718452436023561347155919 |
10013.70801702720612 |
10013.70801695540438 |
10013.7080170352639378227825824457485972179 |
10013.7080170336354 |
reverts | reverts | 10013.70801703526393781876444 |
10013.7080170352639378227825839791637869183 |
| 20 | 10027.4348250436317842775218518191025424128 | 10027.4348250436317842775218518190767937232 |
10027.4348250436317842775218518190767937232 |
10027.4348250421588361327648875054308064136 |
10027.43482502749406 |
10027.43482488369373 |
10027.4348250436317842775218487480669392567 |
10027.43482504037025 |
reverts | reverts | 10027.43482504363178426947455 |
10027.4348250436317842775218518191025424128 |
| 50 | 10068.7282526709369311954105617373559711168 | 10068.7282526709369311954105617372913343473 |
10068.7282526709369311954105617372913343473 |
10068.7282526672393980502265287135799098905 |
10068.72825263042649 |
10068.72825226944521 |
10068.7282526709369311954105540281535213435 |
10068.72825266274953 |
reverts | reverts | 10068.72825267093693117520939 |
10068.7282526709369311954105617373559711168 |
| 100 | 10137.9288626133938773324977277050127626522 | 10137.928862613393877332497727704882600624 |
10137.928862613393877332497727704882600624 |
10137.9288626059479863986134695608143374557 |
10137.92886253181615 |
10137.92886180489168 |
10137.9288626133938773324977121806418126368 |
10137.92886259690654 |
reverts | reverts | 10137.92886261339387729181774 |
10137.9288626133938773324977277050127626522 |
| 365 | 10512.7109633435455501160300546893018100032 | 10512.7109633435455501160300546888091552906 |
10512.7109633435455501160300546888091552906 |
10512.7109633153633430060688858098671971675 |
10512.71096303477923 |
10512.71096028341784 |
10512.7109633435455501160299959305845636861 |
10512.71096328114209 |
reverts | reverts | 10512.71096334354554996205899 |
10512.7109633435455501160300546893018100032 |
| 1000 | 11468.1243852882470306069512046958528107607 | 11468.1243852882470306069512046943804052294 |
11468.1243852882470306069512046943804052294 |
11468.1243852040183872067688475304692019563 |
11468.12438436543188 |
11468.12437614239109 |
11468.1243852882470306069510290826738711704 |
11468.12438510174076 |
reverts | reverts | 11468.12438528824703014677523 |
11468.1243852882470306069512046958528107607 |
| 10000 | 39348.1163898331886255451916114813260386943 | 39348.1163898331886255451916114308065441121 |
39348.1163898331886255451916114308065441121 |
39348.1163869432317911623009365484904265031 |
39348.11635817061095 |
39348.11607603104394 |
39348.1163898331886255451855860429041149103 |
39348.11638343399906 |
reverts | reverts | 39348.11638983318860975615968 |
39348.1163898331886255451916114813260386943 |
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
| N | FP127 | FP127Lib | ABDK | Solady | PRBMath | Quad | Balancer | Aave | Morpho | Maker | FP256 | |||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 1 | 38 | 38 | 38 | 38 | 19 | 19 | 18 | 18 | 17.5 | 17.5 | 33.5 | 33.5 | 18 | 18 | 16 | 16 | 13 | 13 | — | — | 71 | 71 |
| 2 | 38 | 38 | 38 | 38 | 19 | 19 | 18 | 18 | 17 | 17 | 33 | 33 | 18 | 18 | 15 | 15 | 12.5 | 12.5 | — | — | 71 | 71 |
| 5 | 39 | 39 | 39 | 39 | 19 | 19 | 18 | 18 | 17 | 17 | 34 | 34 | 18 | 18 | 14 | 14 | 12.5 | 12.5 | — | — | 71.5 | 71.5 |
| 10 | 38 | 38 | 38 | 38 | 18.5 | 18.5 | 18 | 18 | 17 | 17 | 33 | 33 | 18 | 18 | 12 | 12 | 12 | 12 | — | — | 71 | 71 |
| 20 | 38 | 38 | 38 | 38 | 19 | 19 | 18 | 18 | 17.5 | 17.5 | 34 | 34 | 18 | 18 | 11 | 11 | 11 | 11 | — | — | 71 | 71 |
| 50 | 38 | 38 | 38 | 38 | 18 | 18 | 18 | 18 | 17 | 17 | 33 | 33 | 18 | 18 | 10 | 10 | 10 | 10 | — | — | 71.5 | 71.5 |
| 100 | 38 | 38 | 38 | 38 | 19 | 19 | 18 | 18 | 17 | 17 | 33.5 | 33.5 | 18 | 18 | 8 | 8 | 8 | 8 | — | — | 71 | 71 |
| 365 | 38 | 39 | 38 | 39 | 19 | 19.5 | 18 | 18 | 18 | 18 | 33 | 33 | 18 | 18 | 6 | 6 | 6 | 6 | — | — | 71 | 71 |
| 1000 | 38 | 38 | 38 | 38 | 18 | 19 | 17.5 | 17.5 | 17 | 17 | 33 | 33 | 17.5 | 17.5 | 4 | 4 | 4 | 4 | — | — | 71 | 71 |
| 10000 | 37 | 38 | 37 | 38 | 17.5 | 19 | 17.5 | 17.5 | 17 | 17 | 33 | 33 | 17 | 17 | 1 | 1 | 1 | 1 | — | — | 71 | 71 |
Median (min–max) correct digits over the inputs, capped at 80; "rev" counts inputs that reverted at that N and are excluded.
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: FP127 mul, div, exp; FP127Lib mul, div, exp; ABDK mul, div, exp; Solady sMulWad, sDivWad, expWad; PRBMath mul, div, exp; Quad mul, div, exp; Balancer mulDown, divDown, exp; Aave calculateCompoundedInterest, rayMul; Morpho wTaylorCompounded, wMulDown; Maker unsupported; FP256 mul, div, exp. Parameters reach each adapter floored into its representation (ladder-inputs.json).
The reference input in full: principal = 10000, rateAnnual = 0.05
Each cell: the value with the digits that agree with the truth in ink and the rest in red; below it, correct digits against the exact truth, against the format-rounded truth, the signed error in units of the last place, and gas per step.
| N | truth | FP127 (deployed, staticcall) | FP127Lib (inline) | ABDKMath64x64 | Solady FixedPointMathLib | PRBMath SD59x18 | ABDKMathQuad (binary128) | Balancer LogExpMath | Aave v3 MathUtils (RAY) | Morpho Blue MathLib | Maker rpow (RAY) | FP256 (float, inline) |
|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 1 | 10001.3699568442168947523014256696449249239 | 10001.3699568442168947523014256696449249036 |
10001.3699568442168947523014256696449249036 |
10001.3699568442168940643130503609370407503 |
10001.36995684421689 |
10001.36995684421689 |
10001.3699568442168947523014256696434184119 |
10001.36995684421689 |
10001.369956844216748025579 |
10001.36995684405409 |
reverts | 10001.3699568442168947523014256696449249239 |
| 2 | 10002.740101366609291175926524648192624907 | 10002.7401013666092911759265246481926248923 |
10002.7401013666092911759265246481926248923 |
10002.7401013666092903378959655391611249797 |
10002.74010136660929 |
10002.74010136660928 |
10002.7401013666092911759265246481906849063 |
10002.74010136660929 |
10002.74010136660694348404654 |
10002.74010136628159 |
reverts | 10002.740101366609291175926524648192624907 |
| 5 | 10006.8516612599681035447190899643916635711 | 10006.8516612599681035447190899643916635726 |
10006.8516612599681035447190899643916635726 |
10006.8516612599681028100695456828361784574 |
10006.8516612599681 |
10006.85166125996809 |
10006.8516612599681035447190899643908704196 |
10006.8516612599681 |
10006.85166125987638929232741 |
10006.85166125906267 |
reverts | 10006.8516612599681035447190899643916635711 |
| 10 | 10013.7080170461383418594567841237800085191 | 10013.7080170461383418594567841237800084967 |
10013.7080170461383418594567841237800084967 |
10013.7080170461383407274832957334353977785 |
10013.70801704613834 |
10013.70801704613833 |
10013.7080170461383418594567841237776326456 |
10013.70801704613834 |
10013.70801704467071276233857 |
10013.70801704304217 |
reverts | 10013.7080170461383418594567841237800085191 |
| 20 | 10027.4348250654104056540386919480208485404 | 10027.4348250654104056540386919480208485182 |
10027.4348250654104056540386919480208485182 |
10027.4348250654104049888262761847101955937 |
10027.4348250654104 |
10027.4348250654104 |
10027.4348250654104056540386919480198713688 |
10027.4348250654104 |
10027.43482504192190401276379 |
10027.43482503866036 |
reverts | 10027.4348250654104056540386919480208485404 |
| 50 | 10068.7282527256076979927807360904191194169 | 10068.7282527256076979927807360904191193953 |
10068.7282527256076979927807360904191193953 |
10068.7282527256076968512343849937451523147 |
10068.72825272560769 |
10068.72825272560768 |
10068.728252725607697992780736090417657742 |
10068.72825272560769 |
10068.72825180733318423959192 |
10068.72825179914578 |
reverts | 10068.7282527256076979927807360904191194169 |
| 100 | 10137.9288627234868961823696710416300525454 | 10137.9288627234868961823696710416300525214 |
10137.9288627234868961823696710416300525214 |
10137.9288627234868952345717141305669883877 |
10137.92886272348689 |
10137.92886272348688 |
10137.9288627234868961823696710416295789426 |
10137.92886272348689 |
10137.92884801092668615167631 |
10137.92884799443935 |
reverts | 10137.9288627234868961823696710416300525454 |
| 365 | 10512.7109637602403969751763633564522017482 | 10512.7109637602403969751763633564522017166 |
10512.7109637602403969751763633564522017166 |
10512.7109637602403964962843874175746350375 |
10512.71096376024039 |
10512.71096376024039 |
10512.7109637602403969751763633564498826411 |
10512.71096376024039 |
10512.70833333333333333333333 |
10512.70833327093113 |
reverts | 10512.7109637602403969751763633564522017482 |
| 1000 | 11468.1243865336300386096785282459267168535 | 11468.1243865336300386096785282459267167561 |
11468.1243865336300386096785282459267167561 |
11468.1243865336300369371994034572992404719 |
11468.12438653363003 |
11468.12438653363002 |
11468.1243865336300386096785282459240321407 |
11468.12438653363003 |
11467.97355042753058778065396 |
11467.97355024109644 |
reverts | 11468.1243865336300386096785282459267168535 |
| 10000 | 39348.1164325633456472307592365680379737982 | 39348.1164325633456472307592365680379712093 |
39348.1164325633456472307592365680379712093 |
39348.116432563345597011282561705769467153 |
39348.1164325633456 |
39348.11643256334557 |
39348.1164325633456472307592365680184930427 |
39348.1164325633456 |
37365.55643240955193903265578 |
37365.55642702954313 |
reverts | 39348.1164325633456472307592365680379737982 |
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. FP127 has 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.
Over all 6 inputs
| N | FP127 | FP127Lib | ABDK | Solady | PRBMath | Quad | Balancer | Aave | Morpho | Maker | FP256 | |||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 1 | 37 | 37 | 37 | 37 | 18 | 18 | 16 | 16 | 16 | 16 | 32 | 32 | 16 | 16 | — | — | — | — | — | — | 70 | 70 |
| 2 | 37 | 38 | 37 | 38 | 17.5 | 17.5 | 16 | 16 | 16 | 16 | 32 | 32 | 16 | 16 | — | — | — | — | — | — | 70 | 70 |
| 5 | 37 | 37.5 | 37 | 37.5 | 17.5 | 17.5 | 16 | 16 | 16 | 16 | 32 | 32 | 16 | 16 | — | — | — | — | — | — | 70 | 70 |
| 10 | 36 | 37.5 | 36 | 37.5 | 17 | 18 | 16 | 16 | 16 | 16 | 31 | 31 | 16 | 16 | — | — | — | — | — | — | 70 | 70 |
| 20 | 36 | 37.5 | 36 | 37.5 | 17 | 17.5 | 16 | 16 | 16 | 16 | 31 | 31 | 16 | 16 | — | — | — | — | — | — | 69 | 69 |
| 50 | 36 | 37 | 36 | 37 | 16.5 | 17.5 | 16 | 16 | 16 | 16 | 31 | 31 | 16 | 16 | — | — | — | — | — | — | 69 | 69 |
| 100 | 35 | 37 | 35 | 37 | 16 | 17 | 16 | 16 | 16 | 16 | 30 | 30 | 16 | 16 | — | — | — | — | — | — | 68 | 68 |
| 365 | 34.5 | 37 | 34.5 | 37 | 15.5 | 17 | 16 | 16 | 16 | 16 | 30 | 30 | 15.5 | 15.5 | — | — | — | — | — | — | 68 | 68 |
| 1000 | 34 | 35.5 | 34 | 35.5 | 14.5 | 16 | 15 | 15 | 15 | 15 | 29 | 29 | 15 | 15 | — | — | — | — | — | — | 67 | 67 |
| 10000 | 0.5 | 0.5 | 0.5 | 0.5 | 0 | 0 | 0 | 0 | 0 | 0 | 27 | 27 | 4 | 4 | — | — | — | — | — | — | 65 | 65 |
Median (min–max) correct digits over the inputs, capped at 80; "rev" counts inputs that reverted at that N and are excluded.
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: FP127 mul, sqrt, ln, div, add, exp, sub, normCdf; FP127Lib mul, sqrt, ln, div, add, exp, sub, normCdf; ABDK 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; PRBMath mul, sqrt, ln, div, exp, normCdf by the series/fraction through these; Quad mul, sqrt, ln, div, add, exp, sub, normCdf by the series/fraction through these; Balancer mulDown, pow(x, 1/2), ln, divDown, exp, normCdf by the series/fraction through these; Aave unsupported; Morpho unsupported; Maker unsupported; FP256 mul, sqrt, ln, div, add, exp, sub, normCdf by the series/fraction through these. Parameters reach each adapter floored into its representation (ladder-inputs.json).
The reference input in full: T = 0.5, r = 0.05, sigma = 0.2, spot = 100, strike = 100, tick = 0.000173
Each cell: the value with the digits that agree with the truth in ink and the rest in red; below it, correct digits against the exact truth, against the format-rounded truth, the signed error in units of the last place, and gas per step.
| N | truth | FP127 (deployed, staticcall) | FP127Lib (inline) | ABDKMath64x64 | Solady FixedPointMathLib | PRBMath SD59x18 | ABDKMathQuad (binary128) | Balancer LogExpMath | Aave v3 MathUtils (RAY) | Morpho Blue MathLib | Maker rpow (RAY) | FP256 (float, inline) |
|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 1 | 6.87839186610381111236482092683425007076306 | 6.87839186610381111236482092683425007066222 |
6.87839186610381111236482092683425007066222 |
6.8783918661038111084723989385736331314547 |
6.878391866103810997 |
6.878391866103810933 |
6.87839186610381111236482092683423446296251 |
6.878391866103810948 |
reverts | reverts | reverts | 6.87839186610381111236482092683425007076306 |
| 2 | 6.86806513271493210766538832843009014451141 | 6.86806513271493210766538832843009014466145 |
6.86806513271493210766538832843009014466145 |
6.86806513271493210157298339724185609611595 |
6.868065132714932044 |
6.868065132714931973 |
6.86806513271493210766538832843007004985001 |
6.868065132714932095 |
reverts | reverts | reverts | 6.86806513271493210766538832843009014451141 |
| 5 | 6.83714479479769759938000331844859304685863 | 6.83714479479769759938000331844859304728414 |
6.83714479479769759938000331844859304728414 |
6.83714479479769760228652711320229684588412 |
6.837144794797697437 |
6.83714479479769745 |
6.83714479479769759938000331844854958785622 |
6.837144794797697487 |
reverts | reverts | reverts | 6.83714479479769759938000331844859304685863 |
| 10 | 6.78581039602925175035404532612573043320465 | 6.78581039602925175035404532612573043420648 |
6.78581039602925175035404532612573043420648 |
6.78581039602925175654264330904474888939149 |
6.785810396029251611 |
6.785810396029251528 |
6.78581039602925175035404532612564075836968 |
6.785810396029251659 |
reverts | reverts | reverts | 6.78581039602925175035404532612573043320465 |
| 20 | 6.68388936636074529143221680202703623201243 | 6.68388936636074529143221680202703623396278 |
6.68388936636074529143221680202703623396278 |
6.6838893663607453099907013127634058946569 |
6.683889366360745126 |
6.68388936636074514 |
6.68388936636074529143221680202685090471822 |
6.683889366360745176 |
reverts | reverts | reverts | 6.68388936636074529143221680202703623201243 |
| 50 | 6.38410014515129075799369654827204817146431 | 6.38410014515129075799369654827204817621643 |
6.38410014515129075799369654827204817621643 |
6.38410014515129082038856489500489033162012 |
6.384100145151290678 |
6.384100145151290676 |
6.38410014515129075799369654827160797782368 |
6.38410014515129063 |
reverts | reverts | reverts | 6.38410014515129075799369654827204817146431 |
| 100 | 5.90429198156954564974290965066758972962968 | 5.90429198156954564974290965066758973868736 |
5.90429198156954564974290965066758973868736 |
5.90429198156954576133135723092770774655946 |
5.904291981569545436 |
5.904291981569545509 |
5.90429198156954564974290965066675510723534 |
5.904291981569545387 |
reverts | reverts | reverts | 5.90429198156954564974290965066758972962968 |
| 365 | 3.76450175108813956006578640941955904105981 | 3.76450175108813956006578640941955906555828 |
3.76450175108813956006578640941955906555828 |
3.76450175108813987908361331502504754098481 |
3.764501751088139439 |
3.764501751088139409 |
3.76450175108813956006578640941740283703066 |
3.764501751088139392 |
reverts | reverts | reverts | 3.76450175108813956006578640941955904105981 |
| 1000 | 0.974187219763713465710122175526671930776915 | 0.974187219763713465710122175526671954175089 |
0.974187219763713465710122175526671954175089 |
0.974187219763713765485063644788965575571638 |
0.974187219763713273 |
0.974187219763713293 |
0.974187219763713465710122175524596531068713 |
0.974187219763713135 |
reverts | reverts | reverts | 0.974187219763713465710122175526671930776915 |
| 10000 | 4.26395835385621571476498764907019748044021e-34 | 4.26325352420350177671331445478421006817079e-34 |
4.26325352420350177671331445478421006817079e-34 |
0.0 |
0.0 |
0.0 |
4.26395835385621571476498764850805535968142e-34 |
reverts | reverts | reverts | reverts | 4.26395835385621571476498764907019748044021e-34 |
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 e^(-eps) rounds to a grid point whose distance from one is wrong by up to 1e-18 relative, every step: at eps = 1e-12 that is six digits of the released share, at 1e-15 three, at 1e-18 nothing is released at all.
Over all 5 inputs
| N | FP127 | FP127Lib | ABDK | Solady | PRBMath | Quad | Balancer | Aave | Morpho | Maker | FP256 | |||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 1 | 26 | 26 | 26 | 26 | 7 | 7 | 12 | 12 | 6 | 6 | 22 | 22 | 12 | 12 | — | — | — | — | — | — | 59 | 59 |
| 2 | 26 | 26 | 26 | 26 | 7 | 7 | 12 | 12 | 6 | 6 | 22 | 22 | 12 | 12 | — | — | — | — | — | — | 59 | 59 |
| 5 | 26 | 27 | 26 | 27 | 7 | 7 | 12 | 12 | 6 | 6 | 22 | 22 | 12 | 12 | — | — | — | — | — | — | 59 | 59 |
| 10 | 26 | 27 | 26 | 27 | 7 | 7 | 12 | 12 | 6 | 6 | 22 | 22 | 12 | 12 | — | — | — | — | — | — | 59 | 59 |
| 20 | 26 | 27 | 26 | 27 | 7 | 7 | 12 | 12 | 6 | 6 | 22 | 22 | 12 | 12 | — | — | — | — | — | — | 59 | 59 |
| 50 | 26 | 28 | 26 | 28 | 7 | 7 | 12 | 12 | 6 | 6 | 22 | 22 | 12 | 12 | — | — | — | — | — | — | 59 | 59 |
| 100 | 26 | 28 | 26 | 28 | 7 | 7 | 12 | 12 | 6 | 6 | 22 | 22 | 12 | 12 | — | — | — | — | — | — | 59 | 59 |
| 365 | 26 | 29 | 26 | 29 | 7 | 7 | 11 | 11 | 6 | 6 | 22 | 22 | 11 | 11 | — | — | — | — | — | — | 59 | 59 |
| 1000 | 26 | 28 | 26 | 28 | 7 | 7 | 11 | 11 | 6 | 6 | 22 | 22 | 11 | 11 | — | — | — | — | — | — | 59 | 59 |
| 10000 | 26 | 28 | 26 | 28 | 7 | 7 | 11 | 11 | 6 | 6 | 21 | 21 | 11 | 11 | — | — | — | — | — | — | 59 | 59 |
Median (min–max) correct digits over the inputs, capped at 80; "rev" counts inputs that reverted at that N and are excluded.
The inputs and the ops
| input | parameters | why |
|---|---|---|
| reference | eps = 0.000001 | one millionth a step: a one-second step against a twelve-day time constant |
| nano | eps = 0.000000001 | 1e-9 a step: a one-second step against a thirty-year time constant |
| pico | eps = 0.000000000001 | 1e-12 a step: the factor is within WAD's last six digits of one |
| femto | eps = 0.000000000000001 | 1e-15 a step: three digits of the factor's distance from one survive on WAD |
| atto | eps = 0.00000000000000001 | 1e-17 a step: below WAD's grid, e^(-eps) is one and nothing decays |
Library calls per step: FP127 exp, mul, sub; FP127Lib exp, mul, sub; ABDK exp, mul, sub; Solady expWad, sMulWad; PRBMath exp, mul; Quad exp, mul, sub; Balancer exp, mulDown; Aave unsupported; Morpho unsupported; Maker unsupported; FP256 exp, mul, sub. Parameters reach each adapter floored into its representation (ladder-inputs.json).
The reference input in full: eps = 0.000001
Each cell: the value with the digits that agree with the truth in ink and the rest in red; below it, correct digits against the exact truth, against the format-rounded truth, the signed error in units of the last place, and gas per step.
| N | truth | FP127 (deployed, staticcall) | FP127Lib (inline) | ABDKMath64x64 | Solady FixedPointMathLib | PRBMath SD59x18 | ABDKMathQuad (binary128) | Balancer LogExpMath | Aave v3 MathUtils (RAY) | Morpho Blue MathLib | Maker rpow (RAY) | FP256 (float, inline) |
|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 1 | 0.000000999999500000166666625000008333331944444643 | 0.000000999999500000166666625000008333330356286197 |
0.000000999999500000166666625000008333330356286197 |
0.000000999999500000188935172618087676710274536163 |
0.000000999999500001 |
0.0000009999995 |
0.000000999999500000166666625000008351268400079745 |
0.000000999999500001 |
reverts | reverts | reverts | 0.000000999999500000166666625000008333331944444643 |
| 2 | 0.00000199999800000133333266666693333324444446984 | 0.00000199999800000133333266666693333324146219963 |
0.00000199999800000133333266666693333324146219963 |
0.00000199999800000141185821189715454693214269355 |
0.000001999998000003 |
0.000001999998000001 |
0.0000019999980000013333326666669334537325718948 |
0.000001999998000003 |
reverts | reverts | reverts | 0.00000199999800000133333266666693333324444446984 |
| 5 | 0.00000499998750002083330729169270831163195994543 | 0.00000499998750002083330729169270831162916850658 |
0.00000499998750002083330729169270831162916850658 |
0.00000499998750002109658419069404544643475674093 |
0.000004999987500025 |
0.00000499998750002 |
0.00000499998750002083330729169270858171956675914 |
0.000004999987500025 |
reverts | reverts | reverts | 0.00000499998750002083330729169270831163195994543 |
| 10 | 0.00000999995000016666625000083333194444642856895 | 0.00000999995000016666625000083333194443983689778 |
0.00000999995000016666625000083333194443983689778 |
0.00000999995000016713894361308767599894054001197 |
0.000009999950000175 |
0.000009999950000165 |
0.00000999995000016666625000083333252890150559837 |
0.000009999950000175 |
reverts | reverts | reverts | 0.00000999995000016666625000083333194444642856895 |
| 20 | 0.0000199998000013333266666933332444446984120635 | 0.000019999800001333326666693333244444693890718 |
0.000019999800001333326666693333244444693890718 |
0.0000199998000013342576604291611630515035358258 |
0.00001999980000135 |
0.00001999980000133 |
0.0000199998000013333266666933332455969252083375 |
0.00001999980000135 |
reverts | reverts | reverts | 0.0000199998000013333266666933332444446984120635 |
| 50 | 0.0000499987500208330729192708116320994533962727 | 0.0000499987500208330729192708116320994423985862 |
0.0000499987500208330729192708116320994423985862 |
0.000049998750020835685398123970912820368539542 |
0.000049998750020875 |
0.000049998750020825 |
0.0000499987500208330729192708116354756796406027 |
0.000049998750020875 |
reverts | reverts | reverts | 0.0000499987500208330729192708116320994533962727 |
| 100 | 0.000099995000166662500083331944464285466272597 | 0.0000999950001666625000833319444642854496080643 |
0.0000999950001666625000833319444642854496080643 |
0.0000999950001666675362260727766283707751426846 |
0.00009999500016675 |
0.00009999500016665 |
0.0000999950001666625000833319444707690150656674 |
0.00009999500016675 |
reverts | reverts | reverts | 0.000099995000166662500083331944464285466272597 |
| 365 | 0.000364933395603781349790247076049260633375857 | 0.00036493339560378134979024707604926057849132 |
0.00036493339560378134979024707604926057849132 |
0.000364933395603799567031427786290009862568695 |
0.000364933395604218 |
0.000364933395603853 |
0.000364933395603781349790247076073267291133876 |
0.000364933395604218 |
reverts | reverts | reverts | 0.000364933395603781349790247076049260633375857 |
| 1000 | 0.000999500166625008331944642832344025297644098 | 0.000999500166625008331944642832344025157086449 |
0.000999500166625008331944642832344025157086449 |
0.00099950016662505854030118523922965323436074 |
0.000999500166626284 |
0.000999500166625284 |
0.000999500166625008331944642832410424715795436 |
0.000999500166626284 |
reverts | reverts | reverts | 0.000999500166625008331944642832344025297644098 |
| 10000 | 0.00995016625083194642609402281996344222792092 | 0.0099501662508319464260940228199634411929768 |
0.0099501662508319464260940228199634411929768 |
0.00995016625083243862149792735571907087432919 |
0.009950166250845127 |
0.009950166250835246 |
0.00995016625083194642609402282061759264376801 |
0.009950166250845127 |
reverts | reverts | reverts | 0.00995016625083194642609402281996344222792092 |
Full dataset: ladder.json. Regenerate with make ladder.