> ## Documentation Index
> Fetch the complete documentation index at: https://voltaire.tevm.sh/llms.txt
> Use this file to discover all available pages before exploring further.

# Checksummed

> EIP-55 checksummed address type and validation

<Card title="Try it Live" icon="play" href="https://playground.tevm.sh?example=primitives/address.ts">
  Run Address examples in the interactive playground
</Card>

# Checksummed

EIP-55 checksummed address type providing mixed-case format for display and integrity verification.

## Overview

`Checksummed` is a branded hex string type representing an Ethereum address with EIP-55 checksum encoding. Unlike `AddressType` (a `Uint8Array`), `Checksummed` is a `string` with mixed casing that encodes integrity verification in the character case.

**Key characteristics:**

* **Type:** Branded string (not `Uint8Array`)
* **Format:** Mixed-case hex (e.g., `0x742d35Cc6634C0532925a3b844Bc9e7595f51e3e`)
* **Use cases:** UI display, user input validation, QR codes, wallet integrations
* **Validation:** Checksum encodes keccak256 hash for detecting typos

## Type Definition

```typescript theme={null}
import type { Hex } from 'tevm'

type Checksummed = Hex.Sized<20> & {
  readonly __variant: 'Address'
  readonly __checksummed: true
}
```

Branded string with EIP-55 mixed-case checksum extending `Hex.Sized<20>`.

Defined in: [primitives/Address/AddressType/ChecksumAddress.js:8](https://github.com/evmts/voltaire/blob/main/src/primitives/Address/AddressType/ChecksumAddress.js#L8)

## ChecksumAddress API

<Tabs>
  <Tab title="Standard API">
    ### `ChecksumAddress.from(value)`

    Create checksummed address from any input format.

    **Parameters:**

    * `value: number | bigint | string | Uint8Array` - Input to convert

    **Returns:** `Checksummed` - EIP-55 checksummed hex string

    **Note:** Uses keccak256 internally. Import keccak256 hash function to use this API.

    Defined in: [primitives/Address/AddressType/ChecksumAddress.js:23](https://github.com/evmts/voltaire/blob/main/src/primitives/Address/AddressType/ChecksumAddress.js#L23)

    **Example:**

    ```typescript theme={null}
    import * as ChecksumAddress from 'tevm/Address/ChecksumAddress'
    import { hash as keccak256 } from 'tevm/crypto/Keccak256'

    // Create factory function with crypto dependency
    const from = ChecksumAddress.From({ keccak256 })

    // Various input formats
    from("0x742d35cc6634c0532925a3b844bc9e7595f51e3e")
    // "0x742d35Cc6634C0532925a3b844Bc9e7595f51e3e"

    from(69n)
    // "0x0000000000000000000000000000000000000045"

    from(addr)  // AddressType
    // "0x742d35Cc6634C0532925a3b844Bc9e7595f51e3e"
    ```
  </Tab>

  <Tab title="Tree-Shakeable Factory">
    ### `ChecksumAddress.From({ keccak256 })`

    Factory function that creates a checksummed address converter with explicit crypto dependency.

    **Parameters:**

    * `deps: { keccak256: (data: Uint8Array) => Uint8Array }` - Crypto dependencies

    **Returns:** `(value: number | bigint | string | Uint8Array) => Checksummed`

    **Bundle size benefit:** Crypto dependencies explicit - only bundled if you import them.

    **Example:**

    ```typescript theme={null}
    import { From } from 'tevm/Address/ChecksumAddress'
    import { hash as keccak256 } from 'tevm/crypto/Keccak256'

    // Create factory with explicit crypto dependency
    const from = From({ keccak256 })

    // Use the created function
    const checksummed = from("0x742d35cc6634c0532925a3b844bc9e7595f51e3e")
    // "0x742d35Cc6634C0532925a3b844Bc9e7595f51e3e"
    ```
  </Tab>
</Tabs>

<Tabs>
  <Tab title="Standard API">
    ### `ChecksumAddress.isValid(str)`

    Validate EIP-55 checksum of address string.

    **Parameters:**

    * `str: string` - Address string to validate

    **Returns:** `boolean` - `true` if checksum is valid

    **Note:** Uses keccak256 internally. Import keccak256 hash function to use this API.

    Defined in: [primitives/Address/AddressType/ChecksumAddress.js:63](https://github.com/evmts/voltaire/blob/main/src/primitives/Address/AddressType/ChecksumAddress.js#L63)

    **EIP-55 Logic:**

    * If all letters same case (all lower OR all upper), valid
    * If mixed case, each letter's case must match keccak256-based checksum
    * Zero address with all same case always valid

    **Example:**

    ```typescript theme={null}
    import * as ChecksumAddress from 'tevm/Address/ChecksumAddress'
    import { hash as keccak256 } from 'tevm/crypto/Keccak256'

    // Create factory function with crypto dependency
    const isValid = ChecksumAddress.IsValid({ keccak256 })

    // Correct checksum
    isValid("0x5aAeb6053F3E94C9b9A09f33669435E7Ef1BeAed")
    // true

    // Wrong case on one character
    isValid("0x5aaeb6053F3E94C9b9A09f33669435E7Ef1BeAed")
    // false (first 'A' should be uppercase)

    // All lowercase (no mixed case = no checksum requirement)
    isValid("0x5aaeb6053f3e94c9b9a09f33669435e7ef1beaed")
    // true

    // All uppercase (no mixed case = no checksum requirement)
    isValid("0x5AAEB6053F3E94C9B9A09F33669435E7EF1BEAED")
    // true
    ```
  </Tab>

  <Tab title="Tree-Shakeable Factory">
    ### `ChecksumAddress.IsValid({ keccak256 })`

    Factory function that creates a checksum validator with explicit crypto dependency.

    **Parameters:**

    * `deps: { keccak256: (data: Uint8Array) => Uint8Array }` - Crypto dependencies

    **Returns:** `(str: string) => boolean`

    **Bundle size benefit:** Crypto dependencies explicit - only bundled if you import them.

    **Example:**

    ```typescript theme={null}
    import { IsValid } from 'tevm/Address/ChecksumAddress'
    import { hash as keccak256 } from 'tevm/crypto/Keccak256'

    // Create factory with explicit crypto dependency
    const isValid = IsValid({ keccak256 })

    // Validate checksummed addresses
    isValid("0x5aAeb6053F3E94C9b9A09f33669435E7Ef1BeAed") // true
    isValid("0x5aaeb6053F3E94C9b9A09f33669435E7Ef1BeAed") // false
    ```
  </Tab>
</Tabs>

## EIP-55 Checksum Algorithm

The checksum encodes integrity verification in hexadecimal character casing:

1. Convert address to lowercase hex (without `0x` prefix)
2. Compute keccak256 hash of lowercase hex string
3. For each hex character:
   * If character is a letter (a-f):
     * If corresponding hash nibble >= 8: uppercase
     * Otherwise: lowercase
   * If character is a digit (0-9): unchanged

**Pseudocode:**

```
lowercase = address.toHex().slice(2)  // Remove 0x
hash = keccak256(lowercase)
result = "0x"
for i in 0..39:
  char = lowercase[i]
  if char is letter:
    hashNibble = hash[i/2] nibble at position (i % 2)
    if hashNibble >= 8:
      result += char.toUpperCase()
    else:
      result += char.toLowerCase()
  else:
    result += char
```

## Use Cases

### UI Display

Display addresses with integrity verification:

```typescript theme={null}
import { Address } from 'tevm'

function AddressDisplay({ address }: { address: Address }) {
  const checksummed = address.toChecksummed()

  return (
    <div>
      <span className="font-mono">{checksummed}</span>
      <button onClick={() => navigator.clipboard.writeText(checksummed)}>
        Copy
      </button>
    </div>
  )
}
```

### User Input Validation

Validate user-provided addresses and detect typos:

```typescript theme={null}
import { Address } from 'tevm'
import * as ChecksumAddress from 'tevm/Address/ChecksumAddress'

function validateUserInput(input: string): { valid: boolean; error?: string; address?: Address } {
  const trimmed = input.trim()

  // Check basic format
  if (!Address.isValid(trimmed)) {
    return { valid: false, error: "Invalid address format" }
  }

  // Check checksum if mixed case
  const hasMixedCase = trimmed !== trimmed.toLowerCase() && trimmed !== trimmed.toUpperCase()
  if (hasMixedCase && !ChecksumAddress.isValid(trimmed)) {
    // Provide correct checksummed version
    const addr = Address(trimmed)
    const correct = addr.toChecksummed()
    return {
      valid: false,
      error: `Invalid checksum. Did you mean: ${correct}?`
    }
  }

  const address = Address(trimmed)
  return { valid: true, address }
}

// Usage
const result = validateUserInput("0x742d35cc6634C0532925a3b844Bc9e7595f51e3e")
if (!result.valid) {
  console.error(result.error)
  // "Invalid checksum. Did you mean: 0x742d35Cc6634C0532925a3b844Bc9e7595f51e3e?"
}
```

### QR Codes

Use checksummed addresses in QR codes for error detection:

```typescript theme={null}
import { Address } from 'tevm'
import QRCode from 'qrcode'

async function generateAddressQR(address: Address): Promise<string> {
  const checksummed = address.toChecksummed()
  const qr = await QRCode.toDataURL(checksummed)
  return qr
}

// Usage
const addr = Address("0x742d35cc6634c0532925a3b844bc9e7595f51e3e")
const qrDataUrl = await generateAddressQR(addr)
```

### Wallet Integrations

Wallets expect checksummed addresses:

```typescript theme={null}
import { Address } from 'tevm'

async function requestPayment(recipient: Address, amount: bigint) {
  const checksummed = recipient.toChecksummed()

  await ethereum.request({
    method: 'eth_sendTransaction',
    params: [{
      to: checksummed,
      value: `0x${amount.toString(16)}`
    }]
  })
}
```

### Storage

Store addresses with checksums for verification on retrieval:

```typescript theme={null}
import { Address } from 'tevm'
import * as ChecksumAddress from 'tevm/Address/ChecksumAddress'

// Store
function saveAddress(key: string, address: Address) {
  const checksummed = address.toChecksummed()
  localStorage.setItem(key, checksummed)
}

// Retrieve with validation
function loadAddress(key: string): Address | null {
  const stored = localStorage.getItem(key)
  if (!stored) return null

  // Validate checksum to detect corruption
  if (!ChecksumAddress.isValid(stored)) {
    console.error("Stored address checksum invalid - possible corruption")
    return null
  }

  return Address(stored)
}
```

## Comparison with Other Formats

```typescript theme={null}
import { Address } from 'tevm'

const addr = Address("0x742d35cc6634c0532925a3b844bc9e7595f51e3e")

// Lowercase (toHex)
addr.toHex()
// "0x742d35cc6634c0532925a3b844bc9e7595f51e3e"

// Checksummed (toChecksummed)
addr.toChecksummed()
// "0x742d35Cc6634C0532925a3b844Bc9e7595f51e3e"

// Uppercase (toUppercase)
addr.toUppercase()
// "0x742D35CC6634C0532925A3B844BC9E7595F51E3E"

// All represent the same address
Address(addr.toHex()).equals(Address(addr.toChecksummed()))
// true
```

## Example Walkthrough

```typescript theme={null}
import { Address } from 'tevm'

// Input address (lowercase)
const addr = Address("0x5aaeb6053f3e94c9b9a09f33669435e7ef1beaed")

// Generate checksummed output
console.log(addr.toChecksummed())
// "0x5aAeb6053F3E94C9b9A09f33669435E7Ef1BeAed"
//     ^  ^     ^  ^ ^^     ^  ^             ^
//     Letters capitalized based on keccak256 hash
```

**Breakdown:**

1. Lowercase hex: `5aaeb6053f3e94c9b9a09f33669435e7ef1beaed`
2. Keccak256 hash of lowercase: `ce1b9e8e5e10a90a16c6c3ae3f56c5cf99d82e39c703c1a2adcdf2bd7ad9d685`
3. For each letter character:
   * `a` at position 1: hash nibble = `c` (12) >= 8 → `A`
   * `a` at position 2: hash nibble = `e` (14) >= 8 → `A`
   * `e` at position 3: hash nibble = `1` (1) \< 8 → `e`
   * And so on...

## Performance

**Time complexity:** O(n) where n = 20 bytes (constant time)

**Overhead:** One keccak256 hash computation

For repeated conversions, consider caching:

```typescript theme={null}
import { Address } from 'tevm'
import type { Checksummed } from 'tevm/Address/ChecksumAddress'

class CachedAddress {
  private _checksumCache?: Checksummed

  constructor(private address: Address) {}

  toChecksummed(): Checksummed {
    if (!this._checksumCache) {
      this._checksumCache = this.address.toChecksummed()
    }
    return this._checksumCache
  }
}
```

## Bundle Size Considerations

<Tip>
  With the factory pattern, keccak256 is only bundled if you explicitly import it. Crypto dependencies are now explicit and tree-shakeable.
</Tip>

**Tree-shaking:**

* `ChecksumAddress.From({ keccak256 })` → Crypto dependencies explicit - only bundled if imported
* `ChecksumAddress.IsValid({ keccak256 })` → Crypto dependencies explicit - only bundled if imported
* `Address.toLowercase()` → No crypto dependencies
* `Address.toUppercase()` → No crypto dependencies

**Selective imports for optimal bundle size:**

```typescript theme={null}
// Minimal bundle (no crypto)
import { from, toHex } from 'tevm/Address'

// With checksumming - explicit crypto import
import { From } from 'tevm/Address/ChecksumAddress'
import { hash as keccak256 } from 'tevm/crypto/Keccak256'

const from = From({ keccak256 })
```

## Related

* [Address](/primitives/address) - Main Address class documentation
* [toChecksummed](/primitives/address/to-checksummed) - Convert address to checksummed format
* [isValidChecksum](/primitives/address/is-valid-checksum) - Validate EIP-55 checksum
* [Variants](/primitives/address/variants) - Overview of all address variants
* [AddressType](/primitives/address/branded-address) - Functional API and tree-shaking
* [EIP-55: Mixed-case checksum](https://eips.ethereum.org/EIPS/eip-55) - Specification
* [Keccak256](/crypto/keccak256) - Keccak256 hash function
