DeFiMath v4.0.0: Black-76 options on futures, and a cleaner API
v4.0.0 is the first major release since v3.0.0, and it earns the version bump two ways: a new Black-76 module for pricing European options on a future, and a library reorganization that gives every module a name that reads like its math. The reorg changes import paths and call sites, so upgrading is not drop-in — a short migration guide is at the bottom.
Black-76: European options on a future
Black-76 prices dated European options whose underlying is a
future, not a spot price — the standard model for options on commodity,
rate, and crypto futures. It ships the same surface as Black-Scholes: call,
put, the four Greeks (delta, gamma, theta, vega), and a
Newton-Raphson impliedVolatility solver.
| Function | Gas | Returns |
|---|---|---|
| call | 2,552 | call price |
| put | 2,565 | put price |
| delta | 1,915 | (Δcall, Δput) |
| gamma | 1,704 | Γ (call = put) |
| theta | 3,255 | (Θcall, Θput), per day |
| vega | 1,659 | ν (call = put), per 1% vol |
| impliedVolatility | 11,760 / 11,802 | IV from call / put price |
Under the hood Black-76 is Black-Scholes with the underlying set to the future
F and the rate zeroed inside d₁, with the whole payoff discounted by
e^(−rT):
price = e^(−rT) · [ F·Φ(d₁) − K·Φ(d₂) ] (call)
d₁ = [ ln(F/K) + σ²T/2 ] / (σ√T), d₂ = d₁ − σ√T
That structure is reused verbatim from the Black-Scholes
kernel — the same stdNormCDF, exp, and ln primitives — so it inherits the
same precision and the same gas discipline. Prices hold to 5e-12 relative
error (1.3e-10 absolute deep out-of-the-money), verified in CI against a
black-scholes/greeks reference driven through the discounting identity.
A cleaner API — and why this is v4.0.0
Every library dropped its DeFiMath* prefix, and the two derivative modules got
names that say what they are. The library namespace now carries the context, so
functions shed their redundant prefixes too — DeFiMathOptions.callOptionPrice
is just BlackScholes.call. The old contracts/finance/ folder split into
contracts/rates/ and contracts/statistics/.
| v3.x | v4.0.0 |
|---|---|
DeFiMath · math/Math.sol | Math · math/Math.sol |
DeFiMathOptions · derivatives/Options.sol | BlackScholes · derivatives/BlackScholes.sol |
DeFiMathBinary · derivatives/Binary.sol | BinaryOptions · derivatives/BinaryOptions.sol |
DeFiMathFutures · derivatives/Futures.sol | Futures · derivatives/Futures.sol |
DeFiMathRates · finance/Rates.sol | Rates · rates/Rates.sol |
DeFiMathStats · finance/Stats.sol | Statistics · statistics/Statistics.sol |
| — | Black76 · derivatives/Black76.sol (new) |
Two function families were also renamed now that the library name carries the context:
- Black-Scholes —
callOptionPrice → call,putOptionPrice → put. The Greeks (delta,gamma,theta,vega,impliedVolatility) keep their names. - Binary options — the
binaryprefix is gone:binaryCallPrice → call,binaryPutPrice → put,binaryDelta → delta,binaryGamma → gamma,binaryTheta → theta,binaryVega → vega.
No formula, precision, or gas number changed in the rename — only the names and import paths.
Bugfix: expired put delta
BlackScholes.delta returned +1 for the put leg of an in-the-money option at
expiry (timeToExp == 0); the correct value is −1. Fixed, with a regression
test that fuzzes moneyness at expiry and asserts the delta bounds and put-call
delta parity. The call leg and every non-expiry case were already correct. The
new Black-76 module handles this case correctly from the
start.
Precision & docs
Every derivative function now carries full NatSpec — parameter semantics, the
error metric, and the enforced bound — matching the format already on the math
primitives. Where a function has both a relative and an absolute guarantee
(price-like outputs near zero), both are documented and published: relative
error where |result| ≥ 1, absolute where |result| < 1.
Testing
Black-76 ships with the same two-layer coverage as the rest of the library —
100 Hardhat correctness tests (validated against the discounting identity) and
16 Foundry properties (put-call parity, delta parity δcall − δput = e^(−rT),
discounted bounds, monotonicity, IV round-trips). The suite totals grow to
740 Hardhat tests and 114 Foundry properties × 32,000 runs = 3,648,000
random executions per CI run.
Migrating from v3.x
Update imports and call sites per the table above. A minimal example:
// v3.x
import "defimath-lib/contracts/derivatives/Options.sol";
import "defimath-lib/contracts/finance/Stats.sol";
uint256 px = DeFiMathOptions.callOptionPrice(spot, strike, timeToExp, vol, rate);
uint256 sd = DeFiMathStats.stdDev(data);
// v4.0.0
import "defimath-lib/contracts/derivatives/BlackScholes.sol";
import "defimath-lib/contracts/statistics/Statistics.sol";
uint256 px = BlackScholes.call(spot, strike, timeToExp, vol, rate);
uint256 sd = Statistics.stdDev(data);
Signatures, return types, and every numeric result are unchanged — the upgrade is a find-and-replace on names and paths, nothing more.
Get it
npm install defimath-lib
- Release notes: github.com/MerkleBlue/defimath/releases/tag/v4.0.0
- Package: npmjs.com/package/defimath-lib