impliedVolatility
Black-76Computes implied volatility from a market option price on a future using Newton-Raphson.
Avg. gas
11,760 / 11,802
Max abs. error
2e-6
when σ < 1
Max rel. error
1e-6
when σ ≥ 1
Signature
function impliedVolatility(
uint128 future,
uint128 strike,
uint32 timeToExp,
uint64 rate,
uint128 optionPrice,
bool isCall
) internal pure returns (uint256 volatility)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. Must be > 0 — timeToExp == 0 reverts (unlike the pricer, which treats it as expired). |
| rate | uint64 | Annualized risk-free (discount) rate, 18-decimal fixed-point. |
| optionPrice | uint128 | Observed market option price, 18-decimal fixed-point. Must lie within the no-arbitrage band, otherwise the solver reverts. |
| isCall | bool | true if optionPrice is a call price, false if it's a put price. |
Returns
| Name | Type | Description |
|---|---|---|
| volatility | uint256 | Implied volatility in 18-decimal fixed-point, clamped to [0.01%, 1800%]. |
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) |
| MIN_VOL_IV | 0.01% floor on the recovered vol (1e14) |
| MAX_VOL_IV | 1800% ceiling on the recovered vol (18e18) |
| IV_MAX_ITER | 30 Newton-Raphson iterations before reverting |
Behavior
- Validates all inputs against module-wide constants and reverts with a typed error on any violation.
- Unlike the pricer and greeks,
timeToExp == 0is not allowed — a zero expiry reverts withTimeToExpiryLowerBoundError. - The observed
optionPricemust lie within the discounted no-arbitrage band[max(e^(−rτ)(F − K), 0), e^(−rτ)F]for calls (analogously for puts) — otherwisePriceOutOfBoundsError. - Newton-Raphson from a fixed
55%seed, up to30iterations, converging when the price residual falls within~1e6wei. RevertsNoConvergenceErrorif it fails to converge or if vega gets too small to invert. Typical convergence is 4–6 iterations. - The recovered volatility is clamped to
[MIN_VOL_IV, MAX_VOL_IV]— i.e.[0.01%, 1800%]— on every step. - Each iteration reuses precomputed state and evaluates the call / put price together with vega in a single pass. Pure
internalfunction; no external calls, no storage.
How it works
impliedVolatility inverts the Black-76 pricer: given a market price, it finds the volatility σ that reproduces it. There is no closed form, so DeFiMath uses Newton-Raphson on the pricing residual:
Each step needs both the option price and its derivative with respect to vol (vega) at the current σ. These share almost all of their intermediate work — d₁, d₂, the density and CDF — so DeFiMath computes them together from cached state (ln(F/K), √T, the discount factor) that never changes across iterations.
The solver seeds at σ₀ = 55%, caps at 30 iterations, and stops once the price residual is within ~1e6 wei; the running estimate is clamped into [0.01%, 1800%] each step. Convergence is a round-trip guarantee: IV(price(σ)) ≈ σ to within a relative 1e-6 where σ ≥ 1 and an absolute 2e-6 where σ < 1 — head-to-head measurements 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 |
| TimeToExpiryLowerBoundError | timeToExp == 0 |
| RateUpperBoundError | rate ≥ MAX_RATE |
| PriceOutOfBoundsError | optionPrice outside the no-arbitrage band |
| NoConvergenceError | solver failed to converge (or vega too small to invert) |
Example
import "defimath-lib/contracts/derivatives/Black76.sol";
uint256 iv = Black76.impliedVolatility(
1000e18, // future = $1,000
1050e18, // strike = $1,050
90 days, // 90 days to expiry
0.05e18, // 5% discount rate
96.9e18, // observed market price ≈ $96.90
true // call
);
// iv ≈ 0.60e18 (recovers ~60% vol)