Skip to content

Research notes

Ethereum access lists vs token allowances

An access list can make a storage read cheaper while a zero allowance still rejects the transfer. Track gas costs and spending permission in separate ledgers.

Ivory ceramic stepping stones with a lime sphere beside a closed ivory cabinet with a lime latch on a black floor.
Illustration for research notes; examples in this article are educational.

An Ethereum access list names addresses and storage keys to prewarm for one transaction's gas accounting. It does not grant token spending permission or block access to unlisted contracts. An ERC-20 allowance is token state authorizing a spender to transfer an owner's tokens up to a remaining amount. Verify access-list economics and token authority separately.

Separate the transaction envelope from token state

A wallet or RPC response can show a token address inside an accessList field. That address might also appear in an approval review. The repeated address does not make the two records interchangeable.

EIP-2930 defines access-list entries as addresses with associated storage keys. The transaction pays to make those entries warm before execution. Contracts and storage outside the list remain accessible under the applicable gas rules; this is not a whitelist of permitted calls.

Access lists also appear in EIP-1559 type-2 transactions. Seeing one does not mean the transaction must use the older type-1 fee format. Its fee caps and its access list answer different questions.

An allowance instead belongs to the token contract's state. Under ERC-20, approve sets the amount a spender may withdraw, while allowance reports the remaining amount for an owner and spender. The token's transfer logic enforces that authority.

Review questionEthereum access listOrdinary ERC-20 allowance
What does it identify?Addresses and storage keysOwner, token, spender and amount
What changes?Access charging within this transactionSpending authority stored by the token
Does it carry into the next transaction?Its warm status does notRemaining authority can persist
Does omission forbid a call?NoInsufficient allowance can prevent a transfer that requires it
Where is the evidence?Signed transaction fields and execution estimateToken read at an identified block

Even prewarming the exact slot holding an allowance does not replace its value. A cheaper read of zero still reads zero. The token allowance guide covers sizing and revocation; here the task is to keep permission evidence separate from gas preparation.

A warm address can still have cold storage

“Warm” describes transaction-local accounting, not a lasting change to the contract. EIP-2929 tracks addresses separately from address-and-storage-key pairs. The transaction destination starts warm, but that fact alone does not warm all its storage slots.

Under that schedule, a first cold SLOAD, the instruction that reads a storage slot, costs 2,100 gas. A warm read costs 100 gas. Without an explicit list, a normal successful first read warms that slot for subsequent reads in the same execution context. Reading one slot thirty times therefore differs from reading thirty distinct slots for the first time.

The EIP-2930 prepayment schedule charges 2,400 gas per listed address and 1,900 per listed storage key before execution. A listed slot's subsequent SLOAD still costs the warm-read charge. Count both the prepayment and the access charge.

Do not carry a warm label from a previous transaction into a new estimate. Likewise, do not count a storage key under one contract as a key under another. The accounting identifies the pair, not merely a number that happens to look like the same slot.

Calculate the break-even point for one access pattern

Consider a hypothetical router transaction under the EIP-2929/EIP-2930 rates above. The router is the transaction destination and reads thirty distinct slots in its own storage. Each slot is read once, for the first time in that transaction. Compare an empty access list with one containing the router address and all thirty keys.

Assume identical execution paths, adequate gas and no reverted subcalls. This worksheet isolates the listed address and these reads. It excludes other instructions, token transfers, transaction base costs, refunds and any transaction gas floor. It is not a router benchmark or a complete fee estimate.

Without the list, the reads cost 30 × 2,100 = 63,000 gas.

With the list, the address and keys cost 2,400 + 30 × 1,900 = 59,400 gas upfront. The warm reads add 30 × 100 = 3,000 gas, producing a 62,400-gas subtotal. The difference is a saving of 600 gas.

The router address was already warm, so listing it buys no additional account-access discount in this example. Its 2,400-gas entry cost still has to be recovered through the slot savings.

Distinct slots read onceNo list, gasAddress plus keys and reads, gasEffect of adding list
612,60014,400Costs 1,800 more
2450,40050,400Breaks even
3063,00062,400Saves 600

For this specific pattern, each listed first read saves 100 gas before the address overhead. Twenty-four such savings repay 2,400 gas; the twenty-fifth produces the first positive saving. This threshold is not a rule for arbitrary calls, writes, already-warm slots or multiple contracts.

Repeated or unused entries can spoil the result. Adding one duplicate key to the thirty-key list incurs another 1,900 gas without another warming benefit, turning the 600-gas saving into a 1,300-gas increase. EIP-2930 explicitly permits duplicates and charges them again.

The final receipt can also differ from this component worksheet. On forks applying EIP-7623's calldata-dependent gas floor, reducing execution gas need not reduce charged transaction gas when the floor governs. Compare complete estimates, then reconcile the receipt. Use the max fee and priority fee guide for the separate gas-price calculation.

Keep the permission ledger alongside the gas calculation

Extend the hypothetical router workflow to an owner holding 420 Q, a token with six decimals. The router calls the token directly as spender to transfer 60 Q from the owner to a different, nonzero recipient. Assume the finite-allowance behavior of OpenZeppelin Contracts v5.4.0 ERC20, no transfer fees, no other restrictions and no intervening balance or allowance changes. The router propagates a failed token transfer so the whole attempt reverts.

The thirty-slot calculation above remains a separate component. It does not include the token's storage operations or quote the gas consumed by these attempts.

Confirmed stepAccess list on that transactionOwner Q balanceRouter Q allowance
Starting stateNot applicable4200
Router attempts 60 Q; entire attempt revertsRouter and relevant token slots listed4200
Separate approval sets 125 QEmpty420125
Router successfully transfers 60 QEmpty36065

The first attempt fails because warming storage cannot satisfy the insufficient-allowance check. The later empty list does not block the successful transfer. It changes the gas treatment of accesses, while the confirmed approval supplies authority.

The approved amount is 125 × 10⁶ = 125,000,000 base units. After the successful transfer, the balance is 420 − 60 = 360 Q, and the remaining allowance is 125 − 60 = 65 Q.

In this pinned implementation, finite allowances decrement when spent; maximum-uint256 allowances receive different treatment. Check the actual token implementation before applying the ledger to it. EIP-140's rollback semantics support the unchanged token state after the fully reverted attempt. An included revert can still incur a network fee, tracked separately from these Q amounts.

Removing entries from the next transaction's access list cannot revoke the residual 65 Q. If permission was activated by a signed permit, its nonce and activation deadline require another check; the permit versus approval guide explains those fields. None of them can be inferred from an access-list response.

Generate a candidate, then compare the same transaction

Geth's documented eth_createAccessList method accepts a transaction call object and a block selector. It returns candidate addresses and keys plus gas consumption with that list. The documentation warns that the estimate can change before inclusion and that adding a list need not reduce gas.

Treat the result as a proposal for one simulation state. Generating it does not submit an approval or reserve the observed chain state. A routing decision, balance update or different input can change which storage the actual execution touches.

Use two comparable estimates: one with an empty list and one with the candidate. Hold the sender, destination, calldata, value, block state and relevant gas settings constant. Check the execution outcome as well as the total gas. If one version reverts or produces a different result, investigate that difference before comparing its apparent cost. Access charges can affect gas available to later calls: EIP-150's forwarding rule limits forwarded gas using the amount remaining after call costs.

Do not add address and key charges a second time to a total that already includes them. Label the candidate's reported gas, a full transaction estimate and an actual receipt distinctly. The failed-swap gas worksheet helps reconcile included attempts without treating failed token movement as a zero-fee event.

Keep a review record that answers both questions

Before signing, fill in a small record for the intended operation:

RecordEvidence to retain
Transaction identityChain, sender, destination, decoded call and value
Gas comparisonSimulation block, candidate list, empty-list estimate and list estimate
Permission identityOwner, token, actual spender, verified decimals and intended amount
Permission stateAllowance before execution, read block and any separate authorization receipt
Observed resultTransaction status, gas charged, transfers and remaining allowance

The destination and spender deserve separate fields. A transaction sent to a router may cause another contract to call the token; verify which address the token actually treats as spender. A plausible-looking address inside the access list proves neither that role nor the contract's trustworthiness.

If the workflow includes a future deployment, resolve CREATE versus CREATE2 address derivation separately. CREATE2's specification defines an address calculation using the deployer, salt and initialization code. Putting a predicted address in an access list does not deploy the contract or authorize it to spend.

Finish with two observed answers: whether the list improves the complete transaction's gas estimate, and whether the intended spender has the required token authority. After execution, read the remaining allowance again. A smaller gas subtotal is useful only within its stated assumptions; it never substitutes for that permission record.

Keep the context with the example.

Each worked example is illustrative, with its sources and assumptions in the article. Read our editorial standards for authorship, verification and corrections.