put
Black-76Computes the price of a European put option on a future using the Black-76 model.
Avg. gas
2,565
Max abs. error
1.3e-10
when price < 1
Max rel. error
5e-12
when price ≥ 1
Signature
solidity
function put(
uint128 future,
uint128 strike,
uint32 timeToExp,
uint64 volatility,
uint64 rate
) internal pure returns (uint256 price)Parameters
| Name | Type | Description |
|---|---|---|
| future | uint128 | Current future price in 18-decimal fixed-point format. |
| strike | uint128 | Strike price, 18-decimal fixed-point. Precision-tuned for the no-arbitrage band against the future — see Bounds. |
| timeToExp | uint32 | Time to expiration in seconds. timeToExp == 0 is allowed (handled as expired). |
| volatility | uint64 | Annualized implied volatility, 18-decimal fixed-point (e.g. 60% → 6e17). |
| rate | uint64 | Annualized risk-free (discount) rate, 18-decimal fixed-point. The future already embeds the cost of carry. |
Returns
| Name | Type | Description |
|---|---|---|
| price | uint256 | Put option price in 18-decimal fixed-point. Always ≥ 0. |
Bounds
| Bound | Value |
|---|---|
| MIN_FUTURE | 1e-6 smallest allowed future price (1e12) |
| MAX_FUTURE | 1e15 largest allowed future price (1e33) |
| MAX_STSP_RATIO | 5× (strike must lie within [future/5, future·5]) |
| MAX_EXPIRATION | 32 years (1,009,152,000 seconds) |
| MAX_RATE | 400% annual (4e18) |
Behavior
- Validates all five inputs against module-wide constants and reverts with a typed error on any violation.
- Prices options on a future, not spot:
d₁carries no rate term and the whole payoff is discounted bye^(−rτ), since the future already embeds the cost of carry. - Fast-path on expiration: when
timeToExp == 0, returns intrinsic valuemax(strike − future, 0)without running the pricer. - Symmetric counterpart of the call: same d₁/d₂ machinery with
Φ(−d₁)/Φ(−d₂)in place ofΦ(d₁)/Φ(d₂). By put-call parity the two prices differ bye^(−rτ)(F − K). - Equivalent to
e^(−rτ) ·BlackScholes.put(spot = F, rate = 0). Pureinternalfunction; no external calls, no storage.
How it works
put implements the closed-form Black-76 formula for a European put on a future:
It reuses the same d₁/d₂ machinery as the call — d₁ carries no rate term — evaluating Φ(−d₁)/Φ(−d₂) with Math.stdNormCDF and discounting the whole bracket once by e^(−rT) via Math.expPositive(rT).
The suite enforces a 5e-12 relative bound where the price is ≥ 1 and a 1.3e-10 absolute bound for the sub-$1 (deep-OTM) tail, both at future = $1,000 across a full sweep of strike, time, vol, and rate — head-to-head measurements against other libraries live in defimath-compare.
Errors
| Error | Trigger |
|---|---|
| FutureLowerBoundError | future ≤ MIN_FUTURE |
| FutureUpperBoundError | future ≥ MAX_FUTURE |
| StrikeLowerBoundError | strike · 5 < future |
| StrikeUpperBoundError | future · 5 < strike |
| TimeToExpiryUpperBoundError | timeToExp ≥ MAX_EXPIRATION |
| RateUpperBoundError | rate ≥ MAX_RATE |
Example
solidity
import "defimath-lib/contracts/derivatives/Black76.sol";
uint256 price = Black76.put(
1000e18, // future = $1,000
950e18, // strike = $950
90 days, // 90 days to expiry
0.60e18, // 60% annualized vol
0.05e18 // 5% discount rate
);
// price ≈ 93.5e18 (about $93.50 per option)