sqrt

Math

Computes the principal square root of an 18-decimal fixed-point input.

Gas

245

Max rel. error

2.8e-16

Signature

solidity
function sqrt(uint256 x) internal pure returns (uint256 y)

Parameters

NameTypeDescription
xuint256Input in 18-decimal fixed-point format (1e18 = 1.0).

Returns

NameTypeDescription
yuint256Square root √x in 18-decimal fixed-point format.

Bounds

BoundValue
SQRT_UPPER_BOUND⌊(2²⁵⁶ − 1) / 1e18⌋ + 1 ≈ 1.158e59 — the smallest input where the FP18 scaling step x · 1e18 would overflow uint256. x == 0 returns 0 without revert.

Behavior

  • Returns 0 when x == 0 (no revert).
  • Reverts with SqrtUpperBoundError() only at the input magnitude where the FP18 scaling step (x · 1e18) would overflow uint256 — i.e. x ≥ ⌊(2²⁵⁶ − 1) / 1e18⌋ + 1 ≈ 1.158e59.
  • Uses the CLZ opcode (Osaka) for a near-optimal initial guess; see EIP-7939.
  • Pure assembly hot path; no external calls or storage.

How it works

Square root in fixed-point reduces to two well-known problems: getting a fast initial guess and converging quickly with Newton's iteration. DeFiMath does both in assembly. The CLZ opcode (introduced in EVM Osaka) gives us floor(log2(x)) for free, and from there an initial guess y₀ = 2^⌈bits/2⌉ lands within a factor of √2 (~1.41) of the true root — a one-bit error. Newton's iteration

y ← (y + x/y) / 2

then doubles the number of correct bits every step, so six iterations carry us from one correct bit to 64 — comfortably bit-exact at the 1e18 fixed-point scale.

To compute sqrt(v) · 1e18 we scale the input first: sqrt(x · 1e18) = sqrt(v · 1e36) = sqrt(v) · 1e18. So for inputs ≥ 1.0 we multiply by 1e18 once, run the iteration, and we're done. The input cap is set at exactly the boundary where this scaling multiplication would overflow uint256 — no earlier, so the function accepts the full precision-safe input range.

For inputs below 1.0 we invert instead of scaling: compute sqrt(1e54 / x), then divide 1e36 by the result. This preserves bit precision — a naive sqrt(x · 1e18) for tiny x would land in too few high-order bits and lose accuracy. The whole hot path stays in unchecked Yul assembly with no branches inside Newton — ~245 gas, the cheapest sqrt of any on-chain library we've measured.

Errors

ErrorTrigger
SqrtUpperBoundErrorx ≥ SQRT_UPPER_BOUND

Example

solidity
import "defimath-lib/contracts/math/Math.sol";

uint256 x = 2e18;             // x = 2.0
uint256 y = DeFiMath.sqrt(x); // y ≈ 1.41421356e18