Diffusal
Contracts

BlackScholesLib

Black-Scholes option pricing implementation

The BlackScholesLib and BlackScholesWad libraries implement the Black-Scholes pricing model for European options. These libraries are the mathematical core of Diffusal's pricing system, calculating option prices and Greeks with high precision using 64.64 fixed-point arithmetic.


Overview

The Black-Scholes libraries provide:

LibraryPurpose
BlackScholesLibCore pricing in 64.64 fixed-point format
BlackScholesWadWAD adapter for external interface

Architecture

┌─────────────────────────────────────────────────────────────────┐
│                     DiffusalOptionsQuoter                       │
│                    (external interface)                         │
│                            │                                    │
│                            ▼                                    │
│                    BlackScholesWad                              │
│               (WAD ↔ 64.64 conversion)                          │
│                            │                                    │
│                            ▼                                    │
│                    BlackScholesLib                              │
│               (core 64.64 arithmetic)                           │
│                            │                                    │
│                            ▼                                    │
│                  Math64x64Extended                              │
│             (ln, exp, sqrt, normalCdf)                          │
└─────────────────────────────────────────────────────────────────┘

Key Concepts

Black-Scholes Formula

The Black-Scholes model prices European options. For the complete mathematical derivation and formula details, see Black-Scholes Model.

Call Option:

C=SN(d1)KerTN(d2)C = S \cdot N(d_1) - K \cdot e^{-rT} \cdot N(d_2)

Put Option:

P=KerTN(d2)SN(d1)P = K \cdot e^{-rT} \cdot N(-d_2) - S \cdot N(-d_1)

Option Greeks

Greeks measure option sensitivity to various parameters. See Black-Scholes: Greeks for complete formulas.

GreekMeaningRange (Call)
DeltaPrice sensitivity to spot0 to 1
GammaDelta sensitivity to spotAlways positive
VegaPrice sensitivity to volatilityAlways positive
ThetaTime decay (per year)Usually negative
RhoSensitivity to interest ratePositive (calls)

Precision Model

Format Conversion

┌───────────────────────────────────────────────────────────────┐
│                    Precision Hierarchy                        │
├───────────────────────────────────────────────────────────────┤
│  External Interface:  WAD (1e18)                              │
│      0.50e18 = 50% volatility                                 │
│      3000e18 = $3000 spot price                               │
├───────────────────────────────────────────────────────────────┤
│  Internal Math:       64.64 fixed-point (int128)              │
│      Upper 64 bits = integer part                             │
│      Lower 64 bits = fractional part                          │
│      Range: roughly ±9.2e18 with ~18 decimal precision        │
└───────────────────────────────────────────────────────────────┘

Conversion Functions

// WAD → 64.64
function wadTo64x64(uint256 wad) internal pure returns (int128) {
    return ((wad << 64) / 1e18).toInt256().toInt128();
}

// 64.64 → WAD (unsigned)
function from64x64ToWad(int128 x) internal pure returns (uint256) {
    return (uint256(int256(x)) * 1e18) >> 64;
}

// 64.64 → WAD (signed)
function from64x64ToSignedWad(int128 x) internal pure returns (int256) {
    // Handles negative values for Greeks
}

BlackScholesLib (64.64)

Types

Params64x64

Input parameters for pricing:

struct Params64x64 {
    int128 spot;          // S - Current price of underlying
    int128 strike;        // K - Strike price
    int128 rate;          // r - Risk-free interest rate
    int128 volatility;    // σ - Annualized volatility
    int128 timeToExpiry;  // T - Time to expiration in years
}

Greeks64x64

Option Greeks:

struct Greeks64x64 {
    int128 delta;   // ∂V/∂S - Rate of change with respect to spot
    int128 gamma;   // ∂²V/∂S² - Rate of change of delta
    int128 vega;    // ∂V/∂σ - Sensitivity to volatility
    int128 theta;   // ∂V/∂t - Time decay (per year)
    int128 rho;     // ∂V/∂r - Sensitivity to interest rate
}

PriceResult64x64

Complete pricing result:

struct PriceResult64x64 {
    int128 price;          // Option price
    int128 d1;             // d1 intermediate value
    int128 d2;             // d2 intermediate value
    Greeks64x64 greeks;    // Option Greeks
}

Core Functions

calculateD1D2

Calculates the d1 and d2 values:

function calculateD1D2(Params64x64 memory p)
    internal pure returns (int128 d1, int128 d2)

Implementation:

// σ√T
int128 sqrtT = Math64x64Extended.sqrt(p.timeToExpiry);
int128 volSqrtT = p.volatility.mul(sqrtT);

// ln(S/K)
int128 ratio = p.spot.div(p.strike);
int128 logRatio = Math64x64Extended.ln(ratio);

// (r + σ²/2)T
int128 volSquaredHalf = p.volatility.mul(p.volatility).mul(HALF);
int128 rateAdjustedT = (p.rate.add(volSquaredHalf)).mul(p.timeToExpiry);

// d1 = [ln(S/K) + (r + σ²/2)T] / (σ√T)
d1 = (logRatio.add(rateAdjustedT)).div(volSqrtT);

// d2 = d1 - σ√T
d2 = d1.sub(volSqrtT);

priceCall

Prices a European call option with full Greeks:

function priceCall(Params64x64 memory p)
    internal pure returns (PriceResult64x64 memory result)

Formula: C=SN(d1)KerTN(d2)C = S \cdot N(d_1) - K \cdot e^{-rT} \cdot N(d_2)


pricePut

Prices a European put option with full Greeks:

function pricePut(Params64x64 memory p)
    internal pure returns (PriceResult64x64 memory result)

Formula: P=KerTN(d2)SN(d1)P = K \cdot e^{-rT} \cdot N(-d_2) - S \cdot N(-d_1)


priceCallOnly / pricePutOnly

Gas-optimized pricing without Greeks calculation:

function priceCallOnly(Params64x64 memory p) internal pure returns (int128 optionPrice)
function pricePutOnly(Params64x64 memory p) internal pure returns (int128 optionPrice)

Use case: When only the price is needed (e.g., getOptionQuote()).


BlackScholesWad (WAD Adapter)

Types

ParamsWad

struct ParamsWad {
    uint256 spot;          // S - Current price (WAD)
    uint256 strike;        // K - Strike price (WAD)
    uint256 rate;          // r - Risk-free rate (WAD, 0.05e18 = 5%)
    uint256 volatility;    // σ - Volatility (WAD, 0.50e18 = 50%)
    uint256 timeToExpiry;  // T - Time in years (WAD, 0.25e18 = 3 months)
}

GreeksWad

struct GreeksWad {
    int256 delta;   // Delta (WAD, range -1e18 to 1e18)
    int256 gamma;   // Gamma (WAD)
    int256 vega;    // Vega (WAD)
    int256 theta;   // Theta (WAD, per year)
    int256 rho;     // Rho (WAD)
}

PriceResultWad

struct PriceResultWad {
    uint256 price;      // Option price (WAD)
    GreeksWad greeks;   // Greeks (WAD)
}

Pricing Functions

priceCall / pricePut

Full pricing with Greeks:

function priceCall(ParamsWad memory p)
    internal pure returns (PriceResultWad memory result)

function pricePut(ParamsWad memory p)
    internal pure returns (PriceResultWad memory result)

priceCallOnly / pricePutOnly

Gas-optimized pricing:

function priceCallOnly(ParamsWad memory p) internal pure returns (uint256 priceWad)
function pricePutOnly(ParamsWad memory p) internal pure returns (uint256 priceWad)

Pricing Example

Input Parameters

ParamsWad memory params = ParamsWad({
    spot: 3000e18,        // $3000
    strike: 3200e18,      // $3200
    rate: 0.05e18,        // 5% risk-free rate
    volatility: 0.60e18,  // 60% annualized volatility
    timeToExpiry: 0.25e18 // 3 months (0.25 years)
});

Call Option Price

PriceResultWad memory result = BlackScholesWad.priceCall(params);
// result.price ≈ 197.42e18 ($197.42 per contract)
// result.greeks.delta ≈ 0.423e18 (42.3%)
// result.greeks.gamma ≈ 0.0008e18
// result.greeks.vega ≈ 573.2e18
// result.greeks.theta ≈ -385.6e18 (per year)
// result.greeks.rho ≈ 273.4e18

Interpretation

GreekValueMeaning
Delta = 0.42342.3%1spotincrease1 spot increase → 0.423 option increase
Gamma = 0.0008Delta increases by 0.08% per $1 spot move
Vega = 573.21% vol increase → $5.73 price increase
Theta = -385.6/365-$1.06/dayOption loses ~$1.06/day to time decay
Rho = 273.41% rate increase → $2.73 price increase

Integration Points

Depends On

LibraryPurpose
Math64x64ExtendedLow-level math (ln, exp, sqrt, normalCdf)
ConstantsWAD, 64.64 constants

Used By

ContractPurpose
DiffusalOptionsQuoterAll option pricing
DiffusalLiquidationEngineMark prices for liquidation
MarginEngineStress scenario pricing

Gas Considerations

Cost Breakdown

OperationApprox. GasNotes
normalCdf~20kMost expensive (polynomial approximation)
ln~5kNatural logarithm
exp~5kExponential
sqrt~3kSquare root
Full price with Greeks~100k4x normalCdf + other ops
Price only (no Greeks)~60k2x normalCdf

Optimization

Use priceOnly() variants when Greeks aren't needed:

// Gas optimized: ~60k gas
uint256 price = BlackScholesWad.priceCallOnly(params);

// Full calculation: ~100k gas
PriceResultWad memory result = BlackScholesWad.priceCall(params);

Security Considerations

Numerical Precision

The 64.64 format provides ~18 decimal digits of precision:

  • Safe range: Prices and volatilities in practical ranges
  • Overflow risk: Very large spot/strike ratios (>10^9)
  • Underflow risk: Very small time to expiry or volatility

Edge Cases

ScenarioHandling
Zero volatilityWill revert (division by zero in d1/d2)
Zero time to expiryWill revert (division by zero)
Very deep ITM/OTMMay lose precision near 0 or 1
Negative price resultClamped to 0 (shouldn't occur for valid inputs)

Input Validation

The libraries assume valid inputs. The DiffusalOptionsQuoter validates:

  • Non-zero volatility
  • Non-expired options
  • Non-zero spot and strike prices

Code Reference

Source:

  • packages/contracts/src/utils/BlackScholesLib.sol — Core 64.64 implementation
  • packages/contracts/src/utils/BlackScholesWad.sol — WAD adapter

Key Constants

// From Constants.sol (64.64 format)
int128 constant ONE_64X64 = 0x10000000000000000;   // 1.0
int128 constant TWO_64X64 = 0x20000000000000000;   // 2.0
int128 constant HALF_64X64 = 0x8000000000000000;   // 0.5

// WAD
uint256 constant WAD = 1e18;

On this page