Skip to main content

Try it Live

Run Uint examples in the interactive playground

Uint128

Uint128 is a 128-bit unsigned integer type optimized for large counters, cumulative values, and intermediate calculations that exceed 64-bit range.

Overview

Uint128 provides a bigint-based implementation for 128-bit unsigned integers with a comprehensive API for arithmetic, bitwise operations, and conversions. It follows Tevm’s branded type pattern for type safety.

Range

  • Minimum: 0n
  • Maximum: 340282366920938463463374607431768211455n (2^128 - 1)
  • Size: 16 bytes

Use Cases

  • Large counters and accumulators
  • Cumulative token amounts
  • Intermediate calculations in financial applications
  • State values requiring more than 64 bits
  • Cross-chain identifiers

Installation

bun add tevm

Basic Usage

import * as Uint128 from 'tevm/Uint128';

// Create from various sources
const a = Uint128(100n);
const b = Uint128("0xff");
const c = Uint128(255);

// Arithmetic with wrapping
const sum = Uint128.plus(a, b);
const product = Uint128.times(a, c);

// Comparisons
if (Uint128.greaterThan(sum, product)) {
  console.log("Sum is larger");
}

// Conversions
const hex = Uint128.toHex(sum);
const bytes = Uint128.toBytes(sum);
console.log(`Result: ${Uint128.toString(sum)}`);

Constants

Uint128.SIZE;  // 16
Uint128.MAX;   // 340282366920938463463374607431768211455n
Uint128.MIN;   // 0n
Uint128.ZERO;  // 0n
Uint128.ONE;   // 1n

Constructors

from

Create Uint128 from bigint, number, or string (decimal or hex).
const a = Uint128(100n);
const b = Uint128(255);
const c = Uint128("0xff");
const d = Uint128("1000000000000000000");
Throws: Error if value is negative or exceeds MAX.

fromBigInt

Create from bigint.
const value = Uint128.fromBigInt(12345678901234567890n);

fromNumber

Create from number (must be integer).
const value = Uint128(255);
Throws: Error if not an integer or out of range.

fromHex

Create from hex string (with or without 0x prefix).
const a = Uint128("0xff");
const b = Uint128("ffffffffffffffffffffffffffffffff");

fromBytes

Create from byte array (big-endian, up to 16 bytes).
const bytes = new Uint8Array([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255]);
const value = Uint128(bytes);
Throws: Error if length exceeds 16 bytes.

fromAbiEncoded

Create from ABI-encoded bytes (32 bytes, right-aligned).
const abiBytes = Bytes32();
abiBytes[31] = 255;
const value = Uint128(abiBytes);

tryFrom

Try to create Uint128, returns null on failure.
const valid = Uint128.tryFrom(100n);    // 100n
const invalid = Uint128.tryFrom(-1);    // null

Conversions

toBigInt

Convert to bigint.
const bigint = Uint128.toBigInt(value);

toNumber

Convert to number.
const num = Uint128.toNumber(value);
Throws: Error if value exceeds Number.MAX_SAFE_INTEGER.

toHex

Convert to hex string with 0x prefix.
const hex = Uint128.toHex(value);  // "0xff"

toBytes

Convert to 16-byte array (big-endian).
const bytes = Uint128.toBytes(value);  // Uint8Array[16]

toAbiEncoded

Convert to 32-byte ABI-encoded value.
const encoded = Uint128.toAbiEncoded(value);  // Uint8Array[32]

toString

Convert to decimal string.
const str = Uint128.toString(value);  // "255"

Arithmetic

All arithmetic operations wrap on overflow/underflow.

plus

Add two values with wrapping.
const sum = Uint128.plus(a, b);

// Wrapping behavior
const max = Uint128.MAX;
const wrapped = Uint128.plus(max, Uint128(1n));  // 0n

minus

Subtract with wrapping.
const diff = Uint128.minus(a, b);

// Wrapping on underflow
const zero = Uint128(0n);
const wrapped = Uint128.minus(zero, Uint128(1n));  // MAX

times

Multiply with wrapping.
const product = Uint128.times(a, b);

dividedBy

Integer division.
const quotient = Uint128.dividedBy(a, b);
Throws: Error on division by zero.

modulo

Modulo operation.
const remainder = Uint128.modulo(a, b);
Throws: Error on modulo by zero.

toPower

Exponentiation with wrapping.
const result = Uint128.toPower(base, exponent);

// Example
const base = Uint128(2n);
const exp = Uint128(10n);
const power = Uint128.toPower(base, exp);  // 1024n

Comparison

equals / notEquals

const isEqual = Uint128.equals(a, b);
const notEqual = Uint128.notEquals(a, b);

lessThan / lessThanOrEqual

const isLess = Uint128.lessThan(a, b);
const isLessOrEqual = Uint128.lessThanOrEqual(a, b);

greaterThan / greaterThanOrEqual

const isGreater = Uint128.greaterThan(a, b);
const isGreaterOrEqual = Uint128.greaterThanOrEqual(a, b);

minimum / maximum

Get min/max of two values.
const min = Uint128.minimum(a, b);
const max = Uint128.maximum(a, b);

min / max

Get min/max from array.
const values = [Uint128(100n), Uint128(50n), Uint128(75n)];
const minValue = Uint128.min(values);  // 50n
const maxValue = Uint128.max(values);  // 100n

Bitwise Operations

bitwiseAnd / bitwiseOr / bitwiseXor

const andResult = Uint128.bitwiseAnd(a, b);
const orResult = Uint128.bitwiseOr(a, b);
const xorResult = Uint128.bitwiseXor(a, b);

bitwiseNot

const inverted = Uint128.bitwiseNot(a);

shiftLeft / shiftRight

const shifted = Uint128.shiftLeft(value, 8);   // value << 8
const shifted = Uint128.shiftRight(value, 8);  // value >> 8
Shifts >= 128 bits return zero.

Utilities

isZero

Check if value is zero.
const isZero = Uint128.isZero(value);

isValid

Check if value is valid Uint128 (0 to MAX).
const valid = Uint128.isValid(100n);   // true
const invalid = Uint128.isValid(-1);   // false

bitLength

Get number of bits required to represent value.
const bits = Uint128.bitLength(value);  // 0-128

leadingZeros

Get number of leading zero bits.
const zeros = Uint128.leadingZeros(value);  // 0-128

popCount

Count number of set bits (1s).
const count = Uint128.popCount(value);

clone

Clone a value (no-op for bigint).
const copy = Uint128.clone(value);

Aggregate Operations

sum

Sum array of values with wrapping.
const values = [Uint128(100n), Uint128(50n), Uint128(75n)];
const total = Uint128.sum(values);  // 225n

product

Multiply array of values with wrapping.
const values = [Uint128(10n), Uint128(5n), Uint128(2n)];
const result = Uint128.product(values);  // 100n

Mathematical Functions

gcd

Calculate greatest common divisor.
const a = Uint128(48n);
const b = Uint128(18n);
const divisor = Uint128.gcd(a, b);  // 6n

lcm

Calculate least common multiple.
const a = Uint128(12n);
const b = Uint128(18n);
const multiple = Uint128.lcm(a, b);  // 36n

isPowerOf2

Check if value is a power of 2.
const isPower = Uint128.isPowerOf2(Uint128(16n));   // true
const notPower = Uint128.isPowerOf2(Uint128(15n));  // false

Examples

Large Counters

// Track cumulative gas used across blocks
let cumulativeGas = Uint128(0n);

for (const block of blocks) {
  const blockGas = Uint128(block.gasUsed);
  cumulativeGas = Uint128.plus(cumulativeGas, blockGas);
}

console.log(`Total gas: ${Uint128.toString(cumulativeGas)}`);

Token Amounts

// Calculate total supply with 18 decimals
const tokenAmounts = [
  Uint128(1000000000000000000n),  // 1 token
  Uint128(2500000000000000000n),  // 2.5 tokens
  Uint128(500000000000000000n),   // 0.5 tokens
];

const totalSupply = Uint128.sum(tokenAmounts);
console.log(`Total: ${Uint128.toString(totalSupply)} wei`);

Intermediate Calculations

// Calculate compound interest: principal * (1 + rate)^periods
const principal = Uint128(1000000n);
const rate = Uint128(105n);  // 5% as 105/100
const base = Uint128(100n);

// Interest after 10 periods
const multiplier = Uint128.toPower(rate, Uint128(10n));
const amount = Uint128.times(principal, multiplier);
const result = Uint128.dividedBy(amount, Uint128.toPower(base, Uint128(10n)));

Bitwise Flags

// 128-bit feature flags
const FLAG_A = Uint128(1n << 0n);
const FLAG_B = Uint128(1n << 1n);
const FLAG_C = Uint128(1n << 127n);

let flags = Uint128.ZERO;
flags = Uint128.bitwiseOr(flags, FLAG_A);
flags = Uint128.bitwiseOr(flags, FLAG_C);

// Check flag
const hasA = !Uint128.isZero(Uint128.bitwiseAnd(flags, FLAG_A));
const hasB = !Uint128.isZero(Uint128.bitwiseAnd(flags, FLAG_B));

Performance Notes

  • Implementation: Pure bigint (no assembly optimization)
  • Operations: Arithmetic operations wrap using bitwise AND with MAX
  • Memory: 16-byte representation
  • Best for: Values exceeding 64-bit range but not requiring full 256 bits

Type Safety

Uint128 uses branded types to prevent mixing with other numeric types:
import * as Uint128 from 'tevm/Uint128';
import * as Uint64 from 'tevm/Uint64';

const a = Uint128(100n);
const b = Uint64(50n);

// Type error: cannot mix Uint128 and Uint64
// const sum = Uint128.plus(a, b);  // ❌

// Convert first
const converted = Uint128(Uint64.toBigInt(b));
const sum = Uint128.plus(a, converted);  // ✅

Reference