futurePrice
FuturesComputes the fair price of a futures contract using continuous compounding.
Avg. gas
400
Max abs. error
1.2e-9
at a $1,000 spot
Max rel. error
2e-12
Signature
function futurePrice(
uint128 spot,
uint32 timeToExp,
uint64 rate
) internal pure returns (uint256 price)Parameters
| Name | Type | Description |
|---|---|---|
| spot | uint128 | Current spot price of the underlying, 18-decimal fixed-point. |
| timeToExp | uint32 | Time to contract expiration in seconds. timeToExp == 0 returns spot unchanged. |
| rate | uint64 | Annualized cost-of-carry (risk-free) rate, 18-decimal fixed-point. |
Returns
| Name | Type | Description |
|---|---|---|
| price | uint256 | Futures price in 18-decimal fixed-point. Always ≥ spot for a non-negative rate. |
Bounds
| Bound | Value |
|---|---|
| MIN_SPOT | 1e-6 smallest allowed spot price (1e12) |
| MAX_SPOT | 1e15 largest allowed spot price (1e33) |
| MAX_EXPIRATION | 2 years (63,072,000 seconds) |
| MAX_RATE | 400% annual (4e18) |
Behavior
- Validates all three inputs against module-wide constants and reverts with a typed error on any violation.
- No strike and no volatility — a futures price depends only on spot, time, and the cost-of-carry rate.
- Fast-path on expiration: when
timeToExp == 0, returnsspotunchanged (the carry factor ise⁰ = 1). - Shorter horizon than the options modules:
MAX_EXPIRATIONis 2 years, not 32. - Composes a single DeFiMath primitive —
expPositive, a fast path of exp for the non-negativer·τguaranteed by validation. - Pure
internalfunction; no external calls, no storage. Inlined into the caller's bytecode at compile time.
How it works
The fair forward/futures price is the spot compounded continuously at the cost-of-carry rate to expiry:
timeToExp (seconds) is annualized by dividing by SECONDS_IN_YEAR, the exponent r·τ is formed, and the carry factor e^(r·τ) is evaluated with Math.expPositive — a branch of exp specialized for non-negative inputs, which the input bounds guarantee. A single multiply by spot gives the price. That one transcendental is why it lands at just ~400 gas.
Because the price scales linearly with spot, its error is fundamentally relative and scale-invariant: 2e-12, inherited from exp. The 1.2e-9 absolute figure is that same error expressed in dollars at a $1,000 spot; it scales with the underlying. Head-to-head measurements live in defimath-compare.
Errors
| Error | Trigger |
|---|---|
| SpotLowerBoundError | spot ≤ MIN_SPOT |
| SpotUpperBoundError | spot ≥ MAX_SPOT |
| TimeToExpiryUpperBoundError | timeToExp ≥ MAX_EXPIRATION |
| RateUpperBoundError | rate ≥ MAX_RATE |
Example
import "defimath-lib/contracts/derivatives/Futures.sol";
uint256 price = Futures.futurePrice(
1000e18, // spot = $1,000
90 days, // 90 days to expiry
0.05e18 // 5% cost-of-carry rate
);
// price ≈ 1012.4e18 (spot compounded at 5% for 90 days)