Low-level fixed-point primitives in 18-decimal format (1e18 = 1.0). All pure, gas-efficient, and validated to sub-1e-12 relative error against reference libraries.
Contract: Math.sol
| Function | Gas | Description |
|---|---|---|
| exp | 333 | Exponential function e^x |
| expm1 | 439 | e^x − 1 (precision-preserving for small x) |
| ln | 375 | Natural logarithm |
| log1p | 500 | ln(1 + x) (precision-preserving for small x) |
| log2 | 391 | Base-2 logarithm |
| log10 | 391 | Base-10 logarithm |
| pow | 750 | Power function x^a |
| sqrt | 245 | Square root |
| cbrt | 368 | Cube root |
| sqrtTime | 184 | Specialized sqrt of time in years for Black-Scholes — no input validation |
| stdNormCDF | 660 | Standard normal CDF Φ(x) |
| erf | 685 | Error function |
| mulDiv | 155 | (a · b) / d with full 512-bit intermediate precision |
| mul | 130 | (a · b) / 1e18 — fixed-point multiply with denominator baked in |
| abs | 17 | Branchless |int256| (handles int256.min cleanly) |
| min | 23 | Branchless minimum of two uint256 |
| max | 23 | Branchless maximum of two uint256 |
| clamp | 78 | Clamp x into [lo, hi] (composed max then min) |
| avg | 21 | Overflow-safe (a + b) / 2 via (a & b) + ((a ^ b) >> 1) |
npm install defimath-lib
1e18 = 1.0).exp takes int256, returns uint256; ln takes uint256, returns int256.internal pure — no storage access, no external calls.import "defimath-lib/contracts/math/Math.sol";
uint256 x = 2e18; // x = 2.0
uint256 root = DeFiMath.sqrt(x); // root ≈ 1.41421e18
int256 lnX = DeFiMath.ln(x); // lnX ≈ 0.69315e18
uint256 ePow = DeFiMath.exp(int256(x)); // ePow ≈ 7.389e18expm1 for small x. Computing ex − 1 via exp(x) - 1e18 catastrophically cancels when |x| < 0.01. expm1 uses a Taylor series in that range and preserves full 18-digit precision.log1p for small x. Same reason — log1p(x) preserves precision near zero where ln(1 + x) would lose ~15 digits to subtraction.exp underflows silently to 0. For x < −41.45e18, exp(x) returns 0 (not a revert) since the true value is below 1e-18 representational precision.ln, sqrt, cbrt, and sqrtTime emit the new CLZ opcode introduced in Osaka.sqrtTime is specialized, not general-purpose. It expects x as time in years (1e18 = 1 year) and performs no input validation. It is built for Black-Scholes option pricing — where the caller has already bounded x — and is precision-tuned for [1s, 8y]. For a general fixed-point square root use sqrt instead.| Error | Trigger |
|---|---|
| MulDivByZeroError | mulDiv(a, b, d) when d == 0 |
| MulDivOverflowError | mulDiv(a, b, d) when a · b / d ≥ 2256 |
| MulOverflowError | mul(a, b) when a · b / 1e18 ≥ 2256 |