Skip to main content

Try it Live

Run AccessList examples in the interactive playground

Validation

Type guards and validation functions for AccessList.

AccessList.is()

Type guard checking if value is valid AccessList.
AccessList.is(value: unknown): value is BrandedAccessList
Parameters:
  • value: Value to check
Returns: true if valid AccessList Example:
if (AccessList.is(maybeList)) {
  // TypeScript knows maybeList is BrandedAccessList
  const cost = maybeList.gasCost();
}
Validation:
  • Must be array
  • Each element must be valid Item
  • Does not validate address/key byte lengths

AccessList.isItem()

Type guard checking if value is valid AccessList.Item.
AccessList.isItem(value: unknown): value is Item
Parameters:
  • value: Value to check
Returns: true if valid Item Example:
const item = { address: addr, storageKeys: [key] };

if (AccessList.isItem(item)) {
  // TypeScript knows item is Item
  console.log(item.address);
  console.log(item.storageKeys.length);
}
Validation:
  • Must have address property
  • Must have storageKeys property (array)
  • Does not validate byte lengths

AccessList.assertValid()

Validates access list structure with detailed error messages.
AccessList.assertValid(list: unknown): asserts list is BrandedAccessList
Parameters:
  • list: Value to validate
Returns: Nothing (asserts type) Throws:
  • Error if not array
  • Error if item has invalid structure
  • Error if address not 20 bytes
  • Error if storage key not 32 bytes
Example:
try {
  AccessList.assertValid(list);
  // Safe to use as AccessList
  processAccessList(list);
} catch (err) {
  console.error('Invalid:', err.message);
}
Validation:
  • List must be array
  • Each item must be object with address and storageKeys
  • Addresses must be 20 bytes
  • Storage keys must be 32 bytes each
  • All keys in item must be valid

Patterns

Runtime Type Check

function processAccessList(data: unknown) {
  if (AccessList.is(data)) {
    // Safe to use
    return data.gasCost();
  }
  throw new Error('Invalid access list');
}

Validate External Data

function parseAccessList(external: unknown): BrandedAccessList {
  try {
    AccessList.assertValid(external);
    return external;
  } catch (err) {
    throw new Error(`Invalid access list: ${err.message}`);
  }
}

Item Validation

function validateItem(item: unknown): Item {
  if (!AccessList.isItem(item)) {
    throw new Error('Invalid item structure');
  }

  // Additional validation
  if (item.address.length !== 20) {
    throw new Error('Address must be 20 bytes');
  }

  for (const key of item.storageKeys) {
    if (key.length !== 32) {
      throw new Error('Storage key must be 32 bytes');
    }
  }

  return item;
}

Deep Validation

function strictValidate(list: unknown): BrandedAccessList {
  // Structure validation
  AccessList.assertValid(list);

  // Additional checks
  const deduped = list.deduplicate();
  if (deduped.length !== list.length) {
    throw new Error('Access list contains duplicates');
  }

  return list;
}

Conditional Processing

function maybeProcess(data: unknown) {
  if (AccessList.is(data)) {
    return processAccessList(data);
  } else if (Array.isArray(data)) {
    try {
      const list = AccessList(data);
      AccessList.assertValid(list);
      return processAccessList(list);
    } catch {
      return null;
    }
  }
  return null;
}

Validation Levels

Level 1: Type Guard (is)

Quick runtime check without byte validation.
if (AccessList.is(value)) {
  // Structure is correct
  // Addresses/keys may be wrong length
}
Use when:
  • Trusting internal data
  • Performance critical
  • Will validate elsewhere

Level 2: Deep Validation (assertValid)

Full validation including byte lengths.
AccessList.assertValid(value);
// All checks passed
Use when:
  • Processing external data
  • User input
  • Network data
  • Before critical operations

Level 3: Custom Validation

Application-specific checks.
AccessList.assertValid(list);

// Custom checks
if (list.length > MAX_SIZE) {
  throw new Error('Access list too large');
}

if (!list.hasSavings()) {
  throw new Error('Access list not beneficial');
}
Use when:
  • Business logic validation
  • Gas optimization requirements
  • Protocol-specific constraints

Error Messages

assertValid Errors

// Not an array
"Access list must be an array"

// Invalid item structure
"Access list item must have address and storageKeys"

// Invalid address
"Access list address must be 20 bytes"

// Invalid storage key
"Access list storage key must be 32 bytes"

Handling Errors

try {
  AccessList.assertValid(data);
} catch (err) {
  if (err.message.includes('array')) {
    // Wrong type
  } else if (err.message.includes('address')) {
    // Invalid address
  } else if (err.message.includes('storage key')) {
    // Invalid key
  } else if (err.message.includes('item')) {
    // Invalid structure
  }
}

Best Practices

  1. Validate external data
    // Good
    AccessList.assertValid(userProvidedList);
    processAccessList(userProvidedList);
    
    // Bad
    processAccessList(userProvidedList); // May crash
    
  2. Use type guards for internal data
    // Good: Performance-friendly
    if (AccessList.is(internalList)) {
      process(internalList);
    }
    
    // Overkill for trusted data
    AccessList.assertValid(internalList);
    
  3. Validate before encoding
    // Good
    AccessList.assertValid(list);
    const bytes = list.toBytes();
    
    // May produce invalid RLP
    const bytes = list.toBytes();
    
  4. Provide clear error context
    try {
      AccessList.assertValid(list);
    } catch (err) {
      throw new Error(`Transaction ${txHash}: ${err.message}`);
    }
    
  5. Don’t double validate
    // Bad: Redundant
    if (AccessList.is(list)) {
      AccessList.assertValid(list);
    }
    
    // Good: Pick one
    AccessList.assertValid(list);
    

See Also