Skip to main content

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 by b, throwing an error if b 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 of exponent 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 a u256 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.