Skip to main content

Try it Live

Run Address examples in the interactive playground

Address

Ethereum addresses are 20-byte identifiers for accounts (both externally-owned and contracts). They’re derived from public keys (EOAs) or calculated deterministically during contract deployment.
New to Ethereum addresses? Start with Fundamentals to learn address derivation, EIP-55 checksumming, and CREATE/CREATE2 contract deployment.

Overview

Address is a specialized branded Uint8Array that extends the 20-byte (Bytes20) type with address-specific semantics, including EIP-55 mixed-case checksumming for error detection and validation.
import type { brand } from './brand.js'

export type AddressType = Uint8Array & {
  readonly [brand]: "Address"
}
Address is a branded Uint8Array (20 bytes). TypeScript enforces type safety through a unique Symbol brand, preventing accidental mixing with other Uint8Arrays while maintaining zero runtime overhead.
Voltaire handles checksums automatically while storing addresses as raw bytes internally to avoid case-sensitivity bugs.

Developer Experience

Despite being a Uint8Array, addresses display formatted in most environments:
const address = Address(0x742d35Cc6634C0532925a3b844Bc9e7595f51e3en);
console.log(address);
// Address("0x742d35cc6634c0532925a3b844bc9e7595f51e3e")
This makes debugging more readable than raw byte arrays while maintaining the performance and compatibility benefits of Uint8Array.

API Styles

Voltaire offers two API styles for Address:
import { Address } from '@tevm/voltaire/Address'

const addr = Address('0x742d35Cc6634C0532925a3b844Bc9e7595f51e3e')
addr.toHex()
addr.toChecksummed()
addr.equals(otherAddr)
OOP-style with instance methods. Good for method chaining.

Quick Start

import { Address } from '@tevm/voltaire/Address';

// Create from hex string
const addr = Address.from('0x742d35Cc6634C0532925a3b844Bc9e7595f51e3e');

// Get checksummed representation
console.log(Address.toChecksummed(addr));
// "0x742d35Cc6634C0532925a3b844Bc9e7595f51e3e"

// Get lowercase hex
console.log(Address.toHex(addr));
// "0x742d35cc6634c0532925a3b844bc9e7595f51e3e"

// Validate checksum
console.log(Address.isValidChecksum('0x742d35Cc...'));
// true

Practical Examples

See Fundamentals for detailed explanations of address derivation, checksumming, and contract address calculation.

API Methods

Constructors

Conversions

Validation

Comparisons

Contract Addresses

Reference

  • Fundamentals - Address derivation, checksumming, and deployment
  • Usage Patterns - Common patterns and best practices
  • AddressType - Type definition and branded type pattern
  • Variants - Additional utilities and variants
  • WASM - WebAssembly implementation details

Complete API

    Types

    import type { brand } from './brand.js'
    
    export type AddressType = Uint8Array & {
      readonly [brand]: "Address"
    }
    
    Main branded type. Runtime is Uint8Array (20 bytes), TypeScript enforces type safety through Symbol branding.

    Constants

    Address.SIZE      // 20 - Address size in bytes
    Address.HEX_SIZE  // 42 - Hex string length with "0x" prefix (2 + 40 characters)
    
    // ERC-7528: Native asset address constant
    Address.NATIVE_ASSET_ADDRESS  // "0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE"
    

    NATIVE_ASSET_ADDRESS (ERC-7528)

    const NATIVE_ASSET_ADDRESS = "0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE"
    
    Standard address representing native ETH in token-related operations, as defined in ERC-7528. Use cases:
    • Representing ETH in token lists alongside ERC-20 tokens
    • Multicall operations mixing ETH and token transfers
    • DEX interfaces treating ETH as a “token”
    Example:
    import { NATIVE_ASSET_ADDRESS } from '@tevm/voltaire/Address';
    
    // Check if address is native ETH
    function isNativeAsset(tokenAddress: string): boolean {
      return tokenAddress.toLowerCase() === NATIVE_ASSET_ADDRESS.toLowerCase();
    }
    
    // Handle token or ETH transfer
    async function transfer(token: string, to: string, amount: bigint) {
      if (isNativeAsset(token)) {
        // Send ETH
        await sendTransaction({ to, value: amount });
      } else {
        // Send ERC-20
        await erc20.transfer(to, amount);
      }
    }
    

    Usage Patterns

    Validating User Input

    // Safe parsing with validation
    function parseUserAddress(input: string): Address {
      if (!Address.isValid(input)) {
        throw new Error("Invalid address format");
      }
    
      const addr = Address(input);
    
      // Optionally verify checksum if provided
      if (Address.isValidChecksum(input) === false) {
        console.warn("Checksum mismatch - possible typo");
      }
    
      return addr;
    }
    
    // Usage
    try {
      const addr = parseUserAddress("0x742d35Cc...");
      console.log(`Valid address: ${addr.toChecksummed()}`);
    } catch (e) {
      console.error("Invalid address");
    }
    

    Sorting and Deduplicating

    // Sort addresses for consistent ordering
    const addresses = [
      Address("0xCCCC..."),
      Address("0xAAAA..."),
      Address("0xBBBB..."),
    ];
    
    const sorted = Address.sortAddresses(addresses);
    console.log(sorted.map(a => a.toHex()));
    // ["0xaaaa...", "0xbbbb...", "0xcccc..."]
    
    // Remove duplicates
    const unique = Address.deduplicateAddresses([addr1, addr2, addr1]);
    console.log(unique.length); // 2
    

    Predicting Contract Addresses

    // Predict CREATE2 address before deployment
    const factory = Address("0x...");
    const salt = Bytes32();
    const initCode = compileContract(); // bytecode
    
    // Calculate address deterministically
    const predictedAddress = factory.calculateCreate2Address(salt, initCode);
    
    // Deploy contract
    await deployer.deploy(initCode, salt);
    
    // Verify prediction
    const deployedAddress = await getDeployedAddress();
    console.log(predictedAddress.equals(deployedAddress)); // true
    

    Tree-Shaking

    Import only what you need for optimal bundle size:
    // Import specific functions (tree-shakeable)
    import { fromHex, toChecksummed, equals } from '@tevm/voltaire/Address';
    
    const addr = fromHex("0x742d35cc...");
    const checksummed = toChecksummed(addr);
    const isEqual = equals(addr, addr2);
    
    // Only these 3 functions included in bundle
    // Unused functions (calculateCreateAddress, fromPublicKey, etc.) excluded
    
    Importing from tevm/Address instead of the main entry point enables tree-shaking. For example, if you only need fromHex and toChecksummed, contract address calculation and public key derivation are excluded from your bundle.
    • Keccak256 - Keccak256 hashing for address derivation and verification
    • Bytes - Fixed-size byte types including Bytes32 for salts
    • Uint - Unsigned integer types for address arithmetic

    Try It Yourself

    Specification References