Skip to main content

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.

Try it Live

Run Authorization examples in the interactive playground

Utilities

Helper functions for authorization formatting and comparison.

format

Format authorization to human-readable string.
Authorization.format.call(
  auth: Authorization.Item | Authorization.Unsigned
): string
Parameters:
  • auth: Authorization (signed or unsigned) to format
Returns: Human-readable string representation

Usage

Signed Authorization:
import { Authorization } from 'tevm';

const auth: Authorization.Item = {
  chainId: 1n,
  address: contractAddress,
  nonce: 42n,
  yParity: 0,
  r: 0x123456789abcdef0n,
  s: 0xfedcba9876543210n
};

console.log(Authorization.format.call(auth));
// "Authorization(chain=1, to=0x742d...bEb2, nonce=42, r=0x123456789abcdef0, s=0xfedcba9876543210, v=0)"
Unsigned Authorization:
import { Authorization } from 'tevm';

const unsigned: Authorization.Unsigned = {
  chainId: 1n,
  address: contractAddress,
  nonce: 0n
};

console.log(Authorization.format.call(unsigned));
// "Authorization(chain=1, to=0x742d...bEb2, nonce=0)"

Format Details

Signed format:
Authorization(chain={chainId}, to={address}, nonce={nonce}, r={r}, s={s}, v={yParity})
Unsigned format:
Authorization(chain={chainId}, to={address}, nonce={nonce})
Address formatting: Shortened to 0x{first4}...{last4}

Examples

import { Authorization, Address } from 'tevm';

const addr = Address('0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb2');

// Unsigned
const unsigned = { chainId: 1n, address: addr, nonce: 0n };
Authorization.format.call(unsigned);
// "Authorization(chain=1, to=0x742d...bEb2, nonce=0)"

// Signed
const auth = {
  chainId: 1n,
  address: addr,
  nonce: 42n,
  yParity: 0,
  r: 0x123n,
  s: 0x456n
};
Authorization.format.call(auth);
// "Authorization(chain=1, to=0x742d...bEb2, nonce=42, r=0x123, s=0x456, v=0)"

Use Cases

Logging:
console.log(`Processing: ${Authorization.format.call(auth)}`);
Debugging:
const formatted = Authorization.format.call(auth);
console.error(`Invalid authorization: ${formatted}`);
Display:
function displayAuth(auth: Authorization.Item): void {
  const formatted = Authorization.format.call(auth);
  document.getElementById('auth-display').textContent = formatted;
}

equals

Check if two authorizations are equal.
Authorization.equals.call(
  auth1: Authorization.Item,
  auth2: Authorization.Item
): boolean
Parameters:
  • auth1: First authorization
  • auth2: Second authorization
Returns: true if all fields are equal, false otherwise Comparison: Compares all fields:
  • chainId
  • address (byte-by-byte)
  • nonce
  • yParity
  • r
  • s

Usage

import { Authorization } from 'tevm';

const auth1: Authorization.Item = {
  chainId: 1n,
  address: contractAddress,
  nonce: 0n,
  yParity: 0,
  r: 0x123n,
  s: 0x456n
};

const auth2: Authorization.Item = {
  chainId: 1n,
  address: contractAddress,
  nonce: 0n,
  yParity: 0,
  r: 0x123n,
  s: 0x456n
};

const auth3: Authorization.Item = {
  ...auth1,
  nonce: 1n  // Different nonce
};

console.log(Authorization.equals.call(auth1, auth2)); // true
console.log(Authorization.equals.call(auth1, auth3)); // false

Implementation Details

Address Comparison: Byte-by-byte comparison:
function addressEquals(a: Address, b: Address): boolean {
  if (a.length !== b.length) return false;
  for (let i = 0; i < a.length; i++) {
    if (a[i] !== b[i]) return false;
  }
  return true;
}
Field Comparison:
function equals(auth1: Authorization.Item, auth2: Authorization.Item): boolean {
  return (
    auth1.chainId === auth2.chainId &&
    addressEquals(auth1.address, auth2.address) &&
    auth1.nonce === auth2.nonce &&
    auth1.yParity === auth2.yParity &&
    auth1.r === auth2.r &&
    auth1.s === auth2.s
  );
}

Examples

Exact match:
const auth1 = { chainId: 1n, address: addr, nonce: 0n, yParity: 0, r: 0x123n, s: 0x456n };
const auth2 = { chainId: 1n, address: addr, nonce: 0n, yParity: 0, r: 0x123n, s: 0x456n };

Authorization.equals.call(auth1, auth2); // true
Different chainId:
const auth1 = { chainId: 1n, ... };
const auth2 = { chainId: 137n, ... };

Authorization.equals.call(auth1, auth2); // false
Different address:
const auth1 = { address: addr1, ... };
const auth2 = { address: addr2, ... };

Authorization.equals.call(auth1, auth2); // false
Different signature:
const auth1 = { ..., r: 0x123n, s: 0x456n };
const auth2 = { ..., r: 0x789n, s: 0xabcn };

Authorization.equals.call(auth1, auth2); // false

Common Patterns

Deduplication

Remove duplicate authorizations:
import { Authorization } from 'tevm';

function deduplicateAuths(
  authList: Authorization.Item[]
): Authorization.Item[] {
  const unique: Authorization.Item[] = [];

  for (const auth of authList) {
    // Check if already in unique list
    const isDuplicate = unique.some(u =>
      Authorization.equals.call(u, auth)
    );

    if (!isDuplicate) {
      unique.push(auth);
    }
  }

  return unique;
}

const deduplicated = deduplicateAuths([auth1, auth2, auth1, auth3]);
// Returns [auth1, auth2, auth3]

Authorization Set

Track unique authorizations:
import { Authorization } from 'tevm';

class AuthorizationSet {
  private auths: Authorization.Item[] = [];

  add(auth: Authorization.Item): boolean {
    if (this.has(auth)) {
      return false;
    }
    this.auths.push(auth);
    return true;
  }

  has(auth: Authorization.Item): boolean {
    return this.auths.some(a =>
      Authorization.equals.call(a, auth)
    );
  }

  remove(auth: Authorization.Item): boolean {
    const index = this.auths.findIndex(a =>
      Authorization.equals.call(a, auth)
    );

    if (index === -1) return false;

    this.auths.splice(index, 1);
    return true;
  }

  toArray(): Authorization.Item[] {
    return [...this.auths];
  }

  get size(): number {
    return this.auths.length;
  }
}

const set = new AuthorizationSet();
set.add(auth1); // true
set.add(auth1); // false (duplicate)
set.has(auth1); // true

Logging Helper

Create logging helper:
import { Authorization } from 'tevm';

class AuthLogger {
  log(auth: Authorization.Item | Authorization.Unsigned): void {
    const formatted = Authorization.format.call(auth);
    console.log(`[AUTH] ${formatted}`);
  }

  error(auth: Authorization.Item | Authorization.Unsigned, error: Error): void {
    const formatted = Authorization.format.call(auth);
    console.error(`[AUTH ERROR] ${formatted}: ${error.message}`);
  }

  debug(auth: Authorization.Item | Authorization.Unsigned, message: string): void {
    const formatted = Authorization.format.call(auth);
    console.debug(`[AUTH DEBUG] ${formatted} - ${message}`);
  }
}

const logger = new AuthLogger();
logger.log(auth);
logger.debug(auth, 'Processing authorization');

Comparison Helper

Compare and report differences:
import { Authorization } from 'tevm';

interface AuthDifference {
  field: string;
  value1: any;
  value2: any;
}

function compareAuths(
  auth1: Authorization.Item,
  auth2: Authorization.Item
): AuthDifference[] {
  const differences: AuthDifference[] = [];

  if (auth1.chainId !== auth2.chainId) {
    differences.push({
      field: 'chainId',
      value1: auth1.chainId,
      value2: auth2.chainId
    });
  }

  if (!addressEquals(auth1.address, auth2.address)) {
    differences.push({
      field: 'address',
      value1: auth1.address,
      value2: auth2.address
    });
  }

  if (auth1.nonce !== auth2.nonce) {
    differences.push({
      field: 'nonce',
      value1: auth1.nonce,
      value2: auth2.nonce
    });
  }

  if (auth1.yParity !== auth2.yParity) {
    differences.push({
      field: 'yParity',
      value1: auth1.yParity,
      value2: auth2.yParity
    });
  }

  if (auth1.r !== auth2.r) {
    differences.push({
      field: 'r',
      value1: auth1.r,
      value2: auth2.r
    });
  }

  if (auth1.s !== auth2.s) {
    differences.push({
      field: 's',
      value1: auth1.s,
      value2: auth2.s
    });
  }

  return differences;
}

const diffs = compareAuths(auth1, auth2);
if (diffs.length > 0) {
  console.log('Differences found:');
  diffs.forEach(d => {
    console.log(`  ${d.field}: ${d.value1} vs ${d.value2}`);
  });
}

Format for Display

Create display-friendly format:
import { Authorization, Address } from 'tevm';

interface DisplayAuth {
  chain: string;
  delegateTo: string;
  nonce: string;
  signature?: string;
}

function formatForDisplay(auth: Authorization.Item): DisplayAuth {
  return {
    chain: getChainName(auth.chainId),
    delegateTo: Address.toChecksummed(auth.address),
    nonce: auth.nonce.toString(),
    signature: `r:${auth.r.toString(16)}, s:${auth.s.toString(16)}, v:${auth.yParity}`
  };
}

function getChainName(chainId: bigint): string {
  switch (chainId) {
    case 1n: return 'Ethereum Mainnet';
    case 137n: return 'Polygon';
    case 42161n: return 'Arbitrum';
    default: return `Chain ${chainId}`;
  }
}

const display = formatForDisplay(auth);
console.log(`Chain: ${display.chain}`);
console.log(`Delegate to: ${display.delegateTo}`);
console.log(`Nonce: ${display.nonce}`);
console.log(`Signature: ${display.signature}`);

Batch Formatting

Format multiple authorizations:
import { Authorization } from 'tevm';

function formatAuthBatch(
  authList: Authorization.Item[]
): string {
  const formatted = authList.map((auth, i) =>
    `${i + 1}. ${Authorization.format.call(auth)}`
  );

  return formatted.join('\n');
}

console.log('Authorization List:');
console.log(formatAuthBatch([auth1, auth2, auth3]));
// 1. Authorization(chain=1, to=0x742d...bEb2, nonce=0, ...)
// 2. Authorization(chain=1, to=0x1234...5678, nonce=1, ...)
// 3. Authorization(chain=1, to=0x9abc...def0, nonce=2, ...)

Find Duplicates

Find all duplicates in list:
import { Authorization } from 'tevm';

function findDuplicates(
  authList: Authorization.Item[]
): Array<{ auth: Authorization.Item; indices: number[] }> {
  const duplicates = new Map<string, number[]>();

  authList.forEach((auth, index) => {
    const key = Authorization.format.call(auth);
    const indices = duplicates.get(key) || [];
    indices.push(index);
    duplicates.set(key, indices);
  });

  const result: Array<{ auth: Authorization.Item; indices: number[] }> = [];

  duplicates.forEach((indices, key) => {
    if (indices.length > 1) {
      result.push({
        auth: authList[indices[0]],
        indices
      });
    }
  });

  return result;
}

const dupes = findDuplicates(authList);
dupes.forEach(d => {
  console.log(`Duplicate at indices ${d.indices.join(', ')}:`);
  console.log(`  ${Authorization.format.call(d.auth)}`);
});

Performance

format

O(1) - Constant time string construction Cost:
  • Address shortening: O(40) = O(1)
  • String concatenation: O(1)
  • Number to hex conversion: O(log n) for bigint

equals

O(1) - Constant time comparison Cost:
  • 5 bigint comparisons: O(1) each
  • 1 number comparison: O(1)
  • Address comparison: O(20) = O(1)
Total: O(1)

Optimization Tips

  1. Cache formatted strings if formatting same auth repeatedly
  2. Use equals for deduplication instead of string comparison
  3. Batch format operations when possible

Testing

Test format

import { Authorization } from 'tevm';

const auth: Authorization.Item = {
  chainId: 1n,
  address: contractAddress,
  nonce: 0n,
  yParity: 0,
  r: 0x123n,
  s: 0x456n
};

const formatted = Authorization.format.call(auth);
expect(formatted).toContain('chain=1');
expect(formatted).toContain('nonce=0');
expect(formatted).toContain('r=0x123');
expect(formatted).toContain('s=0x456');
expect(formatted).toContain('v=0');

Test equals

import { Authorization } from 'tevm';

// Same authorizations
const auth1 = { chainId: 1n, address: addr, nonce: 0n, yParity: 0, r: 0x123n, s: 0x456n };
const auth2 = { chainId: 1n, address: addr, nonce: 0n, yParity: 0, r: 0x123n, s: 0x456n };

expect(Authorization.equals.call(auth1, auth2)).toBe(true);

// Different authorizations
const auth3 = { ...auth1, nonce: 1n };
expect(Authorization.equals.call(auth1, auth3)).toBe(false);

See Also