Skip to main content

Overview

The ank-math module provides fixed-point math helpers for WAD (1e18) and RAY (1e27) arithmetic, along with Uniswap V3-style tick and liquidity math utilities.

Constants

WAD

pub const WAD: u128 = 1_000_000_000_000_000_000u128; // 1e18
1e18 fixed-point scale. Used for most token amounts and standard precision calculations.

RAY

pub const RAY: u128 = 1_000_000_000_000_000_000_000_000_000u128; // 1e27
1e27 fixed-point scale. Used for higher-precision calculations like interest rates and compounding factors.

Other Constants

pub const MIN_TICK: i32 = -887_272;
pub const MAX_TICK: i32 = 887_272;
pub const Q96: u128 = 1u128 << 96; // 2^96
pub const MAX_UINT128: u128 = u128::MAX;

WAD Math Functions

wad_mul

pub fn wad_mul(a: u128, b: u128) -> u128
Multiply two WAD numbers: (a * b) / WAD (truncating).
a
u128
required
First WAD-scaled operand
b
u128
required
Second WAD-scaled operand
return
u128
Result in WAD scale

wad_div

pub fn wad_div(a: u128, b: u128) -> u128
Divide two WAD numbers: (a * WAD) / b (truncating; 0 if b == 0).
a
u128
required
Numerator in WAD scale
b
u128
required
Denominator in WAD scale
return
u128
Result in WAD scale, or 0 if b is 0

wad_mul_sat

pub fn wad_mul_sat(a: u128, b: u128) -> u128
Saturating WAD multiply that avoids intermediate overflow. Computes floor(a*b/WAD) using a hi/lo split.
a
u128
required
First WAD-scaled operand
b
u128
required
Second WAD-scaled operand
return
u128
Result in WAD scale (saturates on overflow)

wad_div_sat

pub fn wad_div_sat(a: u128, b: u128) -> u128
Saturating WAD divide that avoids intermediate overflow. Computes floor(a*WAD/b) via quotient/remainder splitting.
a
u128
required
Numerator in WAD scale
b
u128
required
Denominator in WAD scale
return
u128
Result in WAD scale (saturates on overflow)

RAY Math Functions

ray_mul

pub fn ray_mul(a: u128, b: u128) -> u128
Multiply two RAY numbers: (a * b) / RAY (truncating).
a
u128
required
First RAY-scaled operand
b
u128
required
Second RAY-scaled operand
return
u128
Result in RAY scale

ray_div

pub fn ray_div(a: u128, b: u128) -> u128
Divide two RAY numbers: (a * RAY) / b (truncating; 0 if b == 0).
a
u128
required
Numerator in RAY scale
b
u128
required
Denominator in RAY scale
return
u128
Result in RAY scale, or 0 if b is 0

ray_mul_sat

pub fn ray_mul_sat(a: u128, b: u128) -> u128
Saturating RAY multiply that avoids intermediate overflow.
a
u128
required
First RAY-scaled operand
b
u128
required
Second RAY-scaled operand
return
u128
Result in RAY scale (saturates on overflow)

ray_div_sat

pub fn ray_div_sat(a: u128, b: u128) -> u128
Saturating RAY divide that avoids intermediate overflow.
a
u128
required
Numerator in RAY scale
b
u128
required
Denominator in RAY scale
return
u128
Result in RAY scale (saturates on overflow)

ray_pow

pub fn ray_pow(base: u128, exp: u64) -> u128
Fast exponentiation in RAY space: returns base^exp in RAY. Uses repeated squaring with saturating mul/div.
base
u128
required
Base value in RAY scale
exp
u64
required
Exponent (not scaled)
return
u128
Result in RAY scale (base^exp)

ray_mul_checked

pub fn ray_mul_checked(a: u128, b: u128) -> Option<u128>
Checked RAY multiply with banker’s rounding via + RAY/2.
a
u128
required
First RAY-scaled operand
b
u128
required
Second RAY-scaled operand
return
Option<u128>
Result in RAY scale, or None on overflow

Utility Functions

mul_div_wad

pub fn mul_div_wad(num: u128, den: u128) -> u128
Alias for wad_div_sat(num, den). Computes num * WAD / den with saturation.

mul_bps_sat

pub fn mul_bps_sat(x: u128, bps: u32) -> u128
x * bps / 10_000 with saturation (basis points multiply).
x
u128
required
Value to multiply
bps
u32
required
Basis points (1 bps = 0.01%)
return
u128
Result after applying basis points

mul_div_small

pub fn mul_div_small(num: u128, mul: u128, den: u128) -> u128
Compute floor(num * mul / den) splitting to avoid overflow; 0 if den == 0.

Uniswap V3 Math

The module includes extensive Uniswap V3-style math utilities in submodules:

tick_math

Converts between ticks and sqrt-price (Q96 format).
pub fn get_sqrt_ratio_at_tick(tick: i32) -> Result<u128, String>
pub fn get_tick_at_sqrt_ratio(sqrt_price_x96: u128) -> Result<i32, String>

liquidity_math

Calculates liquidity from token amounts and vice versa.
pub fn get_liquidity_for_amount0(sqrt_ratio_a_x96: u128, sqrt_ratio_b_x96: u128, amount0: u128) -> u128
pub fn get_liquidity_for_amount1(sqrt_ratio_a_x96: u128, sqrt_ratio_b_x96: u128, amount1: u128) -> u128
pub fn get_amount0_for_liquidity(sqrt_ratio_a_x96: u128, sqrt_ratio_b_x96: u128, liquidity: u128) -> u128
pub fn get_amount1_for_liquidity(sqrt_ratio_a_x96: u128, sqrt_ratio_b_x96: u128, liquidity: u128) -> u128

sqrt_price_math

Calculates next sqrt-price after swaps.
pub fn get_next_sqrt_price_from_input(sqrt_p_x96: u128, liquidity: u128, amount_in: u128, zero_for_one: bool) -> u128
pub fn get_next_sqrt_price_from_output(sqrt_p_x96: u128, liquidity: u128, amount_out: u128, zero_for_one: bool) -> u128
pub fn get_amount0_delta(sqrt_ratio_a_x96: u128, sqrt_ratio_b_x96: u128, liquidity: u128) -> u128
pub fn get_amount1_delta(sqrt_ratio_a_x96: u128, sqrt_ratio_b_x96: u128, liquidity: u128) -> u128

Usage Examples

Basic WAD arithmetic

use ank_math::{wad_mul, wad_div, WAD};

let a = 2 * WAD; // 2.0
let b = 3 * WAD; // 3.0

let product = wad_mul(a, b); // 6.0 in WAD
let quotient = wad_div(a, b); // 0.666... in WAD

RAY exponentiation

use ank_math::{ray_pow, RAY};

let interest_rate = (105 * RAY) / 100; // 1.05 in RAY
let compounded = ray_pow(interest_rate, 10); // 1.05^10

Notes

  • ”*_sat” variants use saturating arithmetic to avoid panics
  • Liquidity/price formulas follow the standard V3 equations, using BigUint internally to avoid intermediate overflow and then clamping to u128
  • The tick conversions use f64 for ln/pow and are accurate for typical ranges; extreme ticks may incur tiny rounding drift
  • Big-int → u128 conversion uses a saturating clamp (u128::MAX) on overflow

Build docs developers (and LLMs) love