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 Transaction examples in the interactive playground

getAccessList

Extract access list from transaction.

Access List Structure

type AccessList = readonly Item[]

type Item = {
  address: AddressType       // 20-byte contract address
  storageKeys: readonly Hash[]  // 32-byte storage slot keys
}

Transaction Types

TypeAccess List Support
Legacy (0x00)Returns []
EIP-2930 (0x01)Returns tx.accessList
EIP-1559 (0x02)Returns tx.accessList
EIP-4844 (0x03)Returns tx.accessList
EIP-7702 (0x04)Returns tx.accessList

Usage Patterns

Pre-warming Storage

import { getAccessList } from 'tevm/Transaction'

async function prewarmStorage(tx: Transaction.Any) {
  const accessList = getAccessList(tx)

  for (const item of accessList) {
    // Mark address as warm (2600 gas vs 100 gas)
    await markAddressWarm(item.address)

    // Mark storage slots as warm (2100 gas vs 100 gas)
    for (const key of item.storageKeys) {
      await markStorageWarm(item.address, key)
    }
  }
}

Gas Cost Calculation

import { getAccessList } from 'tevm/Transaction'

function calculateAccessListGasCost(tx: Transaction.Any): bigint {
  const accessList = getAccessList(tx)

  let cost = 0n

  for (const item of accessList) {
    cost += 2400n  // Per address (TU_DATA + TU_ACCESS_LIST_ADDRESS_COST)

    for (const _ of item.storageKeys) {
      cost += 1900n  // Per storage key (TU_ACCESS_LIST_STORAGE_KEY_COST)
    }
  }

  return cost
}

// Usage
const accessListCost = calculateAccessListGasCost(tx)
console.log(`Access list adds ${accessListCost} gas`)

Access List Analysis

import { getAccessList } from 'tevm/Transaction'

function analyzeAccessList(tx: Transaction.Any) {
  const accessList = getAccessList(tx)

  const uniqueAddresses = new Set(
    accessList.map(item => Address.toHex(item.address))
  )

  const totalStorageKeys = accessList.reduce(
    (sum, item) => sum + item.storageKeys.length,
    0
  )

  return {
    addressCount: uniqueAddresses.size,
    storageKeyCount: totalStorageKeys,
    isEmpty: accessList.length === 0,
    gasCost: calculateAccessListGasCost(tx)
  }
}

Merging Access Lists

import { getAccessList } from 'tevm/Transaction'
import * as AccessList from 'tevm/AccessList'

function mergeTransactionAccessLists(
  transactions: Transaction.Any[]
): AccessList.AccessList {
  const lists = transactions.map(getAccessList)
  return AccessList.merge(...lists)
}

// Usage
const merged = mergeTransactionAccessLists([tx1, tx2, tx3])

Validation

import { getAccessList } from 'tevm/Transaction'

function validateAccessList(tx: Transaction.Any): boolean {
  const accessList = getAccessList(tx)

  for (const item of accessList) {
    // Check address is valid
    if (item.address.length !== 20) {
      return false
    }

    // Check storage keys are valid
    for (const key of item.storageKeys) {
      if (key.length !== 32) {
        return false
      }
    }

    // Check for duplicates
    const uniqueKeys = new Set(item.storageKeys.map(k => Hash.toHex(k)))
    if (uniqueKeys.size !== item.storageKeys.length) {
      return false  // Duplicate storage keys
    }
  }

  return true
}

Building Access Lists

import { getAccessList } from 'tevm/Transaction'
import * as AccessList from 'tevm/AccessList'

function buildOptimalAccessList(
  existingTx: Transaction.Any,
  additionalAddresses: AddressType[]
): AccessList.AccessList {
  // Start with existing access list
  let list = getAccessList(existingTx)

  // Add additional addresses
  for (const addr of additionalAddresses) {
    list = AccessList.withAddress(list, addr)
  }

  // Remove duplicates and optimize
  return AccessList.deduplicate(list)
}

Gas Savings

Access lists pre-declare storage access to save gas:
// Without access list
const coldAddressAccess = 2600n  // COLD_ACCOUNT_ACCESS_COST
const coldStorageAccess = 2100n  // COLD_SLOAD_COST

// With access list
const accessListAddress = 2400n      // Per address in list
const accessListStorage = 1900n      // Per storage key in list
const warmAddressAccess = 100n       // WARM_STORAGE_READ_COST
const warmStorageAccess = 100n       // WARM_STORAGE_READ_COST

// Net savings per access (if accessed multiple times)
const addressSavings = coldAddressAccess - (accessListAddress + warmAddressAccess)
// = 2600 - (2400 + 100) = 100 gas

const storageSavings = coldStorageAccess - (accessListStorage + warmStorageAccess)
// = 2100 - (1900 + 100) = 100 gas
Access lists are beneficial when addresses/slots accessed 2+ times.

See Also

References