Abstract
This EIP charges access lists for their data footprint, preventing the circumvention of the EIP-7623 floor pricing. This effectively reduces the worst-case block size by ~21% with minimal impact on users.
Motivation
Access lists are only priced for storage but not for their data.
Furthermore, access lists can circumvent the EIP-7623 floor pricing by contributing to EVM gas while still leaving a non-negligible data footprint. This enables achieving the maximal possible block size by combining access lists with calldata at a certain ratio.
Specification
| Parameter | Value | Source |
|---|---|---|
ACCESS_LIST_ADDRESS_COST | 2400 | EIP-2930 |
ACCESS_LIST_STORAGE_KEY_COST | 1900 | EIP-2930 |
TOTAL_COST_FLOOR_PER_TOKEN | 16 | EIP-7976 |
Let access_list_bytes be the total byte count of addresses (20 bytes each) and storage keys (32 bytes each) in the access list.
Let access_list_data_cost = 64 * access_list_bytes (i.e. 1280 gas per address and 2048 gas per storage key). The 64 gas-per-byte rate matches the EIP-7976 calldata floor.
The access list data cost is added as a flat surcharge to the gas used calculation, leaving the EIP-2930 access_list_cost and the EIP-7976 floor calculation unchanged:
tx.gasUsed = (
21000
+ access_list_data_cost
+
max(
STANDARD_TOKEN_COST * tokens_in_calldata
+ execution_gas_used
+ isContractCreation * (32000 + INITCODE_WORD_COST * words(calldata))
+ access_list_cost,
TOTAL_COST_FLOOR_PER_TOKEN * floor_tokens_in_calldata
)
)
Any transaction with a gas limit below tx.gasUsed evaluated with execution_gas_used = 0 is considered invalid.
Rationale
Access list data is always charged at floor rate (added to access_list_cost), and access list tokens are included in the floor calculation. This ensures:
- Access list data always pays floor rate regardless of execution level
- Access lists cannot be used to bypass the calldata floor pricing
- Consistent pricing across all transaction data sources
Backwards Compatibility
This is a backwards incompatible gas repricing that requires a scheduled network upgrade.
Requires updates to gas estimation in wallets and nodes. Normal usage patterns remain largely unaffected.
Reference Implementation
def calculate_access_list_data_cost(access_list):
"""EIP-7981: flat 64 gas per byte of access list data."""
# Each access entry: 20-byte address + 32 bytes per storage key
total_bytes = sum(20 + 32 * len(access.slots) for access in access_list)
return total_bytes * 64
def calculate_intrinsic_cost(tx):
"""
Calculate intrinsic gas cost and floor gas cost.
Both include the EIP-7981 access list data surcharge, so that
tx.gasUsed = max(intrinsic_gas + execution_gas_used, floor_gas).
"""
# Calldata tokens (EIP-7976)
zero_bytes = count_zero_bytes(tx.data)
nonzero_bytes = len(tx.data) - zero_bytes
tokens_in_calldata = zero_bytes + nonzero_bytes * 4
floor_tokens_in_calldata = len(tx.data) * 4
# Access list cost (EIP-2930, unchanged) and EIP-7981 data surcharge
access_list_cost = 0
access_list_data_cost = 0
if has_access_list(tx):
for access in tx.access_list:
access_list_cost += (
ACCESS_LIST_ADDRESS_COST
+ len(access.slots) * ACCESS_LIST_STORAGE_KEY_COST
)
access_list_data_cost = calculate_access_list_data_cost(tx.access_list)
# EIP-7976 floor (calldata only) plus EIP-7981 surcharge
floor_gas = (
TX_BASE_COST
+ floor_tokens_in_calldata * TOTAL_COST_FLOOR_PER_TOKEN
+ access_list_data_cost
)
# Intrinsic gas plus EIP-7981 surcharge
calldata_cost = tokens_in_calldata * STANDARD_TOKEN_COST
create_cost = TX_CREATE_COST + init_code_cost(tx.data) if is_create(tx) else 0
intrinsic_gas = (
TX_BASE_COST
+ calldata_cost
+ create_cost
+ access_list_cost
+ access_list_data_cost
)
return intrinsic_gas, floor_gas
Security Considerations
This EIP closes a loophole that allows circumventing EIP-7623 floor pricing. Without this fix, attackers can achieve larger blocks than intended by combining access lists with calldata. All transaction data sources now contribute to the floor calculation consistently.
Copyright
Copyright and related rights waived via CC0.