The SafeMath class provides overflow-safe arithmetic operations for u256 values.
import { SafeMath } from '@btc-vision/btc-runtime/runtime';
import { u256 } from '@btc-vision/as-bignum/assembly';Adds two u256 values with overflow checking.
static add(a: u256, b: u256): u256const sum = SafeMath.add(u256.fromU64(100), u256.fromU64(50)); // 150Throws: Revert if result overflows
Subtracts b from a with underflow checking.
static sub(a: u256, b: u256): u256const diff = SafeMath.sub(u256.fromU64(100), u256.fromU64(30)); // 70Throws: Revert if b > a (underflow)
Multiplies two u256 values with overflow checking.
static mul(a: u256, b: u256): u256const product = SafeMath.mul(u256.fromU64(100), u256.fromU64(5)); // 500Throws: Revert if result overflows
Divides a by b.
static div(a: u256, b: u256): u256const quotient = SafeMath.div(u256.fromU64(100), u256.fromU64(4)); // 25Throws: Revert if b is zero
Returns remainder of a divided by b.
static mod(a: u256, b: u256): u256const remainder = SafeMath.mod(u256.fromU64(100), u256.fromU64(30)); // 10Throws: Revert if b is zero
Raises base to power exponent using binary exponentiation.
static pow(base: u256, exponent: u256): u256const power = SafeMath.pow(u256.fromU64(2), u256.fromU64(10)); // 1024Throws: Revert on overflow
Computes 10^exponent (optimized for base 10).
static pow10(exponent: u8): u256const million = SafeMath.pow10(6); // 1,000,000Throws: Revert if exponent > 77 (would overflow)
Computes square root using Newton-Raphson method.
static sqrt(a: u256): u256const root = SafeMath.sqrt(u256.fromU64(144)); // 12Returns smaller of two values.
static min(a: u256, b: u256): u256const smaller = SafeMath.min(u256.fromU64(100), u256.fromU64(50)); // 50Returns larger of two values.
static max(a: u256, b: u256): u256const larger = SafeMath.max(u256.fromU64(100), u256.fromU64(50)); // 100Increments value by 1 with overflow protection.
static inc(value: u256): u256const incremented = SafeMath.inc(u256.fromU64(100)); // 101Throws: Revert if value equals u256.Max
Decrements value by 1 with underflow protection.
static dec(value: u256): u256const decremented = SafeMath.dec(u256.fromU64(100)); // 99Throws: Revert if value is zero
Computes (a * b) % modulus without intermediate overflow.
static mulmod(a: u256, b: u256, modulus: u256): u256// For cryptographic operations where intermediate product would overflow
const result = SafeMath.mulmod(largeA, largeB, prime);Use case: Elliptic curve operations, modular arithmetic
Computes modular multiplicative inverse.
static modInverse(a: u256, modulus: u256): u256// Find x such that (a * x) % modulus = 1
const inverse = SafeMath.modInverse(value, prime);Throws: If inverse doesn't exist
Returns floor of base-2 logarithm (position of highest set bit).
static approximateLog2(x: u256): u256const log = SafeMath.approximateLog2(u256.fromU64(1024)); // 10
const log2 = SafeMath.approximateLog2(u256.fromU64(1000)); // 9 (floor)Returns: 0 for both input 0 and input 1
Computes natural logarithm (ln) with high precision.
static preciseLog(x: u256): u256// Returns ln(x) scaled by 10^6 for fixed-point precision
const lnScaled = SafeMath.preciseLog(u256.fromU64(10)); // ~2,302,585Returns: ln(x) * 1,000,000
Computes approximate natural logarithm using bit length.
static approxLog(x: u256): u256// Uses bitLength * ln(2) approximation, scaled by 10^6
const approxLn = SafeMath.approxLog(u256.fromU64(8)); // ~2,079,441 (3 * ln(2))Returns: Approximate ln(x) * 1,000,000
Returns number of bits needed to represent the value.
static bitLength256(x: u256): u32const bits = SafeMath.bitLength256(u256.fromU64(255)); // 8
const bits2 = SafeMath.bitLength256(u256.fromU64(256)); // 9Shifts left by specified bits.
static shl(value: u256, shift: i32): u256const shifted = SafeMath.shl(u256.fromU64(1), 10); // 1024Warning: Unlike other SafeMath operations, bits shifted beyond type width are silently lost (no throw). Shifts >= 256 return 0.
Shifts a u128 value left by specified bits.
static shl128(value: u128, shift: i32): u128Warning: Same behavior as shl - overflow bits are silently lost.
Shifts right by specified bits.
static shr(value: u256, shift: i32): u256const shifted = SafeMath.shr(u256.fromU64(1024), 5); // 32Performs bitwise AND.
static and(a: u256, b: u256): u256Performs bitwise OR.
static or(a: u256, b: u256): u256Performs bitwise XOR.
static xor(a: u256, b: u256): u256Checks if value is even.
static isEven(a: u256): boolif (SafeMath.isEven(value)) {
// Value is even
}SafeMath does not provide comparison methods. Use the built-in u256 methods instead:
// Use u256 built-in comparison methods
u256.eq(a, b) // Equal
u256.ne(a, b) // Not equal
u256.lt(a, b) // Less than
u256.le(a, b) // Less than or equal
u256.gt(a, b) // Greater than
u256.ge(a, b) // Greater than or equalReturns the smaller of two u256 values.
static min(a: u256, b: u256): u256Returns the larger of two u256 values.
static max(a: u256, b: u256): u256// u128 min/max
SafeMath.min128(a: u128, b: u128): u128
SafeMath.max128(a: u128, b: u128): u128
// u64 min/max
SafeMath.min64(a: u64, b: u64): u64
SafeMath.max64(a: u64, b: u64): u64All u256 operations have u128 variants for better gas efficiency with smaller values:
import { u128 } from '@btc-vision/as-bignum/assembly';
SafeMath.add128(a: u128, b: u128): u128 // Addition
SafeMath.sub128(a: u128, b: u128): u128 // Subtraction
SafeMath.mul128(a: u128, b: u128): u128 // Multiplication
SafeMath.div128(a: u128, b: u128): u128 // Division
SafeMath.min128(a: u128, b: u128): u128 // Minimum
SafeMath.max128(a: u128, b: u128): u128 // Maximum
SafeMath.shl128(value: u128, shift: i32): u128 // Left shiftNative u64 variants for optimal performance:
SafeMath.add64(a: u64, b: u64): u64 // Addition
SafeMath.sub64(a: u64, b: u64): u64 // Subtraction
SafeMath.mul64(a: u64, b: u64): u64 // Multiplication
SafeMath.div64(a: u64, b: u64): u64 // Division
SafeMath.min64(a: u64, b: u64): u64 // Minimum
SafeMath.max64(a: u64, b: u64): u64 // MaximumFor signed 128-bit operations (separate module):
import { SafeMathI128 } from '@btc-vision/btc-runtime/runtime';
import { i128 } from '@btc-vision/as-bignum/assembly';See the SafeMathI128 module for signed integer operations.
// Calculate 5% fee
const FEE_PERCENT = u256.fromU64(5);
const HUNDRED = u256.fromU64(100);
function calculateFee(amount: u256): u256 {
return SafeMath.div(SafeMath.mul(amount, FEE_PERCENT), HUNDRED);
}// 100 basis points = 1%
const BPS = u256.fromU64(10000);
function applyBps(amount: u256, bps: u256): u256 {
return SafeMath.div(SafeMath.mul(amount, bps), BPS);
}const PRECISION = u256.fromU64(1_000_000); // 6 decimals
function mulFixed(a: u256, b: u256): u256 {
return SafeMath.div(SafeMath.mul(a, b), PRECISION);
}function average(a: u256, b: u256): u256 {
// (a + b) / 2 without overflow
return SafeMath.add(
SafeMath.shr(a, 1),
SafeMath.add(
SafeMath.shr(b, 1),
SafeMath.mul(
SafeMath.mod(a, u256.fromU64(2)),
SafeMath.mod(b, u256.fromU64(2))
)
)
);
}All SafeMath operations throw Revert on error:
try {
const result = SafeMath.div(amount, u256.Zero);
} catch (e) {
// Division by zero caught
}| Solidity | SafeMath |
|---|---|
a + b (checked) |
SafeMath.add(a, b) |
a - b (checked) |
SafeMath.sub(a, b) |
a * b (checked) |
SafeMath.mul(a, b) |
a / b |
SafeMath.div(a, b) |
a % b |
SafeMath.mod(a, b) |
a ** b |
SafeMath.pow(a, b) |
Math.sqrt(a) |
SafeMath.sqrt(a) |
mulmod(a, b, m) |
SafeMath.mulmod(a, b, m) |
Navigation:
- Previous: OP721 API
- Next: Storage API