SafeMath and u256 Usage
This document explains the implementation and usage of SafeMath
for the u256
data type, focusing on its importance in avoiding overflows and underflows in blockchain smart contracts.
Why Use SafeMath?
When working with unsigned integers like u256
, overflows and underflows can lead to critical bugs or vulnerabilities in your smart contracts. SafeMath
mitigates these risks by adding checks for these conditions during arithmetic operations.
Importing SafeMath
To start using SafeMath
, include the necessary imports in your AssemblyScript code:
import { SafeMath } from "@btc-vision/btc-runtime/runtime";
import { u128, u256 } from "as-bignum/assembly";
Available Methods
SafeMath
provides a comprehensive suite of arithmetic operations for u256
, u128
, and smaller unsigned integers (u64
). Below is a list of the most commonly used methods:
Addition
- Method:
SafeMath.add(a: u256, b: u256): u256
- Description: Adds two
u256
values safely, throwing an error if an overflow occurs. - Example:
let a: u256 = u256.fromU32(1000);
let b: u256 = u256.fromU32(2000);
let sum: u256 = SafeMath.add(a, b); // Result: 3000
Subtraction
- Method:
SafeMath.sub(a: u256, b: u256): u256
- Description: Subtracts one
u256
value from another, throwing an error if an underflow occurs. - Example:
let a: u256 = u256.fromU32(5000);
let b: u256 = u256.fromU32(3000);
let difference: u256 = SafeMath.sub(a, b); // Result: 2000
Multiplication
- Method:
SafeMath.mul(a: u256, b: u256): u256
- Description: Multiplies two
u256
values safely, throwing an error if an overflow occurs. - Example:
let a: u256 = u256.fromU32(10);
let b: u256 = u256.fromU32(20);
let product: u256 = SafeMath.mul(a, b); // Result: 200
Division
- Method:
SafeMath.div(a: u256, b: u256): u256
- Description: Divides one
u256
value by another, throwing an error if a division by zero occurs. - Example:
let a: u256 = u256.fromU32(100);
let b: u256 = u256.fromU32(5);
let quotient: u256 = SafeMath.div(a, b); // Result: 20
Modulo
- Method:
SafeMath.mod(a: u256, b: u256): u256
- Description: Computes the remainder of
a
divided byb
, throwing an error ifb
is zero. - Example:
let a: u256 = u256.fromU32(10);
let b: u256 = u256.fromU32(3);
let remainder: u256 = SafeMath.mod(a, b); // Result: 1
Advanced Methods
Exponentiation
- Method:
SafeMath.pow(base: u256, exponent: u256): u256
- Description: Computes
base
raised to the power ofexponent
safely. - Example:
let base: u256 = u256.fromU32(2);
let exponent: u256 = u256.fromU32(10);
let result: u256 = SafeMath.pow(base, exponent); // Result: 1024
Logarithm (Approximate)
- Method:
SafeMath.approximateLog2(x: u256): u256
- Description: Approximates the binary logarithm (
log2
) of au256
value. - Example:
let x: u256 = u256.fromU32(1024);
let log2: u256 = SafeMath.approximateLog2(x); // Result: 10
Best Practices
- Avoid native operations (
+
,-
,*
,/
) to ensure safety. - Even with SafeMath, ensure the inputs are within the expected range to prevent logical errors.
- For performance-critical code, use unchecked arithmetic only when absolutely safe and well-documented.