Skip to main content

Try it Live

Run Address examples in the interactive playground

Address.IsValidChecksum({ keccak256 })

Factory function that creates a checksum validator with explicit crypto dependency.Parameters:
  • deps: { keccak256: (data: Uint8Array) => Uint8Array } - Crypto dependencies
Returns: (str: string) => booleanBundle size benefit: Crypto dependencies explicit - only bundled if you import them.Example:
import { IsValidChecksum } from 'tevm/Address/AddressType'
import { hash as keccak256 } from 'tevm/crypto/Keccak256'

// Create factory with explicit crypto dependency
const isValidChecksum = IsValidChecksum({ keccak256 })

// Validate checksummed addresses
isValidChecksum("0x5aAeb6053F3E94C9b9A09f33669435E7Ef1BeAed") // true
isValidChecksum("0x5aaeb6053F3E94C9b9A09f33669435E7Ef1BeAed") // false

EIP-55 Checksum Rules

All lowercase: Valid (no checksum to verify)
Address.isValidChecksum("0x742d35cc6634c0532925a3b844bc9e7595f51e3e") // true
All uppercase: Valid (no checksum to verify)
Address.isValidChecksum("0x742D35CC6634C0532925A3B844BC9E7595F51E3E") // true
Mixed case: Must match keccak256-based checksum
// Correct mixed case
Address.isValidChecksum("0x742d35Cc6634C0532925a3b844Bc9e7595f51e3e") // true

// Incorrect mixed case
Address.isValidChecksum("0x742d35cc6634c0532925a3b844bc9e7595f51e3E") // false

Use Cases

Strict Validation

Require checksummed addresses:
import { Address } from 'tevm'

function parseStrictAddress(input: string): Address {
  if (!Address.isValid(input)) {
    throw new Error('Invalid address format')
  }

  if (!Address.isValidChecksum(input)) {
    throw new Error('Invalid or missing EIP-55 checksum')
  }

  return Address(input)
}

Warn on Invalid Checksum

Accept but warn about invalid checksums:
import { Address } from 'tevm'

function parseAddressWithWarning(input: string): Address {
  if (!Address.isValid(input)) {
    throw new Error('Invalid address format')
  }

  if (!Address.isValidChecksum(input)) {
    console.warn('Address has invalid checksum. Double-check the address.')
  }

  return Address(input)
}

UI Validation

Provide checksum feedback in forms:
import { Address } from 'tevm'

function validateAddressInput(value: string) {
  if (!value) {
    return { valid: false, message: 'Address required' }
  }

  if (!Address.isValid(value)) {
    return { valid: false, message: 'Invalid address format' }
  }

  if (!Address.isValidChecksum(value)) {
    return {
      valid: true,
      warning: 'Invalid checksum. Address may be mistyped.'
    }
  }

  return { valid: true }
}

Accept Lowercase, Return Checksummed

Accept any valid format, return checksummed:
import { Address } from 'tevm'

function normalizeAddress(input: string): string {
  if (!Address.isValid(input)) {
    throw new Error('Invalid address')
  }

  const addr = Address(input)
  return addr.toChecksummed() // Always return checksummed
}

// All inputs normalized to checksummed
console.log(normalizeAddress("0x742d35cc6634c0532925a3b844bc9e7595f51e3e"))
// "0x742d35Cc6634C0532925a3b844Bc9e7595f51e3e"

Checksum Calculation

The checksum is computed as follows:
  1. Convert address to lowercase hex (without 0x)
  2. Compute keccak256 hash of lowercase string
  3. For each hex character (if letter):
    • If corresponding hash nibble >= 8: uppercase
    • Otherwise: lowercase
Example:
import { Address } from 'tevm'

const lowercase = "0x5aaeb6053f3e94c9b9a09f33669435e7ef1beaed"
const addr = Address(lowercase)

// Generate checksummed version
const checksummed = addr.toChecksummed()
console.log(checksummed)
// "0x5aAeb6053F3E94C9b9A09f33669435E7Ef1BeAed"
//     ^  ^     ^  ^ ^^     ^  ^             ^

// Verify checksum
console.log(Address.isValidChecksum(checksummed)) // true
console.log(Address.isValidChecksum(lowercase))   // true (all lowercase = no checksum)

Common Scenarios

QR Code addresses: Often all uppercase (valid):
const qrCode = "0x742D35CC6634C0532925A3B844BC9E7595F51E3E"
console.log(Address.isValidChecksum(qrCode)) // true (all uppercase)
Database addresses: Often lowercase (valid):
const db = "0x742d35cc6634c0532925a3b844bc9e7595f51e3e"
console.log(Address.isValidChecksum(db)) // true (all lowercase)
User input: May have incorrect checksum (invalid):
const userInput = "0x742d35cc6634c0532925a3b844bc9e7595f51e3E" // Wrong!
console.log(Address.isValidChecksum(userInput)) // false (mixed case wrong)

Error Detection

Checksums help detect typos:
import { Address } from 'tevm'

// Original (correct)
const correct = "0x5aAeb6053F3E94C9b9A09f33669435E7Ef1BeAed"

// Typo: changed 'a' to 'b' at position 3
const typo = "0x5bAeb6053F3E94C9b9A09f33669435E7Ef1BeAed"

console.log(Address.isValidChecksum(correct)) // true
console.log(Address.isValidChecksum(typo))    // false (checksum mismatch)
Detection rate: EIP-55 checksums can detect:
  • ~99.986% of single character errors
  • Most multi-character errors
Not detected:
  • All lowercase → all lowercase (no checksum)
  • All uppercase → all uppercase (no checksum)

Performance

Cryptographic operation: Uses keccak256 hash internally. Bundle size impact: With the factory pattern, keccak256 is only bundled if you explicitly import it. Crypto dependencies are now explicit and tree-shakeable. Alternative: Use isValid() if checksum verification not required.

Integration with Parsing

Validate before parsing:
import { Address } from 'tevm'

if (!Address.isValid(input)) {
  throw new Error('Invalid format')
}

if (!Address.isValidChecksum(input)) {
  console.warn('Invalid checksum')
}

const addr = Address(input)
Parse then validate:
import { Address } from 'tevm'

const addr = Address(input)

// Check if input had valid checksum
if (!Address.isValidChecksum(input)) {
  console.warn('Input had invalid checksum')
}

// Always return checksummed
return addr.toChecksummed()

See Also