Skip to main content
Voltaire uses branded types to prevent common bugs like passing a Hash where an Address is expected. The brand exists only at compile time - at runtime, it’s just a Uint8Array.

What is a Branded Type?

A branded type adds a compile-time tag to a base type:
// The brand symbol (shared across all primitives)
declare const brand: unique symbol

// AddressType is a Uint8Array with an invisible brand tag
type AddressType = Uint8Array & { readonly [brand]: 'Address' }

// HashType is also a Uint8Array, but with a different brand
type HashType = Uint8Array & { readonly [brand]: 'Hash' }
At runtime, both are plain Uint8Array. TypeScript prevents you from mixing them up:
import { Address, Hash } from '@tevm/voltaire'

function transfer(to: AddressType, txHash: HashType) { /* ... */ }

const addr = Address('0x742d35Cc6634C0532925a3b844Bc9e7595f51e3e')
const hash = Hash('0x1234567890abcdef...')

transfer(addr, hash)  // OK
transfer(hash, addr)  // Type error: HashType is not assignable to AddressType

Zero Runtime Overhead

The brand is a phantom type - it exists only in TypeScript’s type system:
const addr = Address('0x742d35Cc6634C0532925a3b844Bc9e7595f51e3e')

// At runtime, it's just a Uint8Array
console.log(addr instanceof Uint8Array)  // true
console.log(addr.length)                  // 20
console.log(addr[0])                      // First byte as number

// All Uint8Array methods work
addr.slice(0, 4)
addr.subarray(12, 20)
new DataView(addr.buffer)

Validation at Construction

Branded types are validated when created. If you have an AddressType, it’s valid:
// These throw on invalid input
Address('0xnot_valid')           // Error: Invalid hex
Address('0x123')                 // Error: Must be 20 bytes
Address(new Uint8Array(10))      // Error: Must be 20 bytes

// If construction succeeds, the value is valid
const addr = Address('0x742d35Cc6634C0532925a3b844Bc9e7595f51e3e')
// addr is guaranteed to be exactly 20 bytes of valid data

Console Formatting

Branded types display nicely when logged:
const addr = Address('0x742d35Cc6634C0532925a3b844Bc9e7595f51e3e')
console.log(addr)
// Address("0x742d35cc6634c0532925a3b844bc9e7595f51e3e")

Using Branded Types in Function Signatures

Use branded types in your function parameters:
import type { AddressType } from '@tevm/voltaire/Address'
import type { HashType } from '@tevm/voltaire/Hash'

// Type-safe function - cannot swap arguments by accident
function verifyTransaction(from: AddressType, to: AddressType, txHash: HashType) {
  // No runtime validation needed - types guarantee validity
}

API Documentation Note

All Voltaire documentation shows the recommended API using constructors like Address(), Hash(), etc. These return instances with prototype methods. For bundle-size optimization, Voltaire also provides a tree-shakeable functional API with the same method signatures but imported as standalone functions.

All Branded Types

TypeSizeDescription
AddressType20 bytesEthereum address
HashType32 bytesKeccak256 hash
BytecodeTypeVariableEVM bytecode
BlobType128 KBEIP-4844 blob
HexTypeVariableHex string (0x...)
Uint8Type1 byte8-bit unsigned integer
Uint16Type2 bytes16-bit unsigned integer
Uint32Type4 bytes32-bit unsigned integer
Uint64Type8 bytes64-bit unsigned integer
Uint128Type16 bytes128-bit unsigned integer
Uint256Type32 bytes256-bit unsigned integer
Int8Type1 byte8-bit signed integer
Int16Type2 bytes16-bit signed integer
Int32Type4 bytes32-bit signed integer
Int64Type8 bytes64-bit signed integer
Int128Type16 bytes128-bit signed integer
Int256Type32 bytes256-bit signed integer
Bytes1-321-32 bytesFixed-size byte arrays
Bytes6464 bytes64-byte array (signatures)
WeiTypebigintWei denomination
GweiTypebigintGwei denomination
EtherTypebigintEther denomination
AccessListTypeVariableEIP-2930 access list
AuthorizationTypeVariableEIP-7702 authorization
SignatureType64-65 bytesECDSA/Ed25519 signature
SelectorType4 bytesFunction selector
CallDataTypeVariableContract call data
EventLogTypeVariableEvent log entry
ReceiptTypeVariableTransaction receipt
NonceTypebigintAccount nonce
BlockNumberTypebigintBlock number
TransactionHashType32 bytesTransaction hash
BlockHashType32 bytesBlock hash
GasLimitTypebigintGas limit
GasPriceTypebigintGas price
PrivateKeyType32 bytesPrivate key
PublicKeyType64 bytesUncompressed public key
Base64TypeVariableBase64 encoded string
RlpTypeVariableRLP encoded data
ChainIdTypenumberChain identifier
OpcodeTypenumberEVM opcode

Learn More