EIP-8058 Gas discount for duplicate contract deployment (Contract Bytecode Deduplication Discount)
Declined for Inclusion · Fees & gas · EIP status Draft · created 2025-10-22
A proposal that waives the code storage gas when redeploying code identical to a contract already on the chain, if the existing contract's address is put in the transaction's access list.
Why it is needed
Today, redeploying identical bytecode (a contract's executable code) costs the same as the first deployment. But node software actually stores only one copy of the code and has multiple accounts point to it. In other words, no extra storage is used, yet the storage cost is charged again. If EIP-8037, which raises code storage gas from 200 to 1,900 per byte, is applied, the code storage cost of a single 24kB contract alone becomes about 46.6 million gas, and this unfairness grows much larger. Still, simply querying whether this code exists in the node database is not an option. A full sync node holds all historical code while a snap sync node holds only part of it, so query results would differ between nodes, gas calculation would diverge and consensus would break. This proposal decides on the discount by looking only at the access list already included in the transaction, so every node produces the same answer.
What changes
Today
- Redeploying the same code still costs the full code storage gas
- Nodes store one copy of the code, but the fee is charged anew every time
- The access list is used only to announce storage accesses in advance
After EIP-8058
- If the address of an existing contract with the same code is put in the access list, the code storage gas (GAS_CODE_DEPOSIT × length) is not charged
- The new account is only linked to the existing code hash, and the code is not stored again
- The transaction format stays the same, so existing wallets and tools keep working
Who is affected
- Apps and projects that deploy the same contract many times: Putting a single address in the access list greatly reduces the duplicate deployment cost. If EIP-8037 is applied, the savings are even larger.
- Wallet and developer tooling teams: They can reflect the possible discount in gas estimation (eth_estimateGas) and add a feature that detects duplicate deployments and fills in the access list automatically.
- Client (node) teams: They must add logic that builds a set of code hashes before transaction execution and compares it when deployment completes. There is no change to the state trie or database structure.
In depth
Construction of the code hash access set W
Before transaction execution begins, using the state from before any state changes, build the set W = { codeHash(a) | a ∈ accessList, a exists in state, a has code }. Every address in the access list is checked, and only the code hashes of accounts that exist in state and have deployed code enter W. Empty accounts and accounts without code contribute nothing. It reuses the EIP-2930 access list structure as is, with no new fields or protocol changes.
Contract creation gas calculation
When a contract creation transaction or CREATE/CREATE2 succeeds and returns bytecode B of length L, compute H = keccak256(B). If H ∉ W, the code is new, so GAS_CODE_DEPOSIT × L is charged, B is stored under H, and the new account's codeHash is linked to H. If H ∈ W, the code is linked to the existing code hash H with no charge and no storage. The cost of reading the codeHash of an access list address is already included in the access costs of EIP-2929/2930 (the access list's own cost and the cold→warm state access cost), so the duplicate check itself adds no gas.
Sequential deployments within the same block
Transactions execute sequentially, so if transaction T_A deploys bytecode B to address X earlier in a block (paying in full), a later transaction T_B in the same block can put X in its access list and receive the discount. This is because T_B's W is built from the current state, which already reflects T_A's changes. The source notes that this is complicated to exploit because it requires control over transaction ordering, and that builders cannot modify an already signed access list, but since it can happen, the specification formalizes the behavior.
Edge case: the same code deployed for the first time at the same time
If two transactions in the same block both deploy the same previously unseen bytecode and neither puts the other's address in its access list, both pay in full. The discount applies only when the deployed address is in the access list. The source considers this acceptable because the first deployment cannot be known when the transaction is written, the discount is an implicit opt-in through the access list, such a situation is extremely rare in practice, and the complexity of special handling is not large relative to the benefit.
Why the access list approach?
The result depends only on the transaction's access list and the current state, so every node computes the same gas. There is no need to maintain a reverse index from codeHash to accounts, and it builds on the existing EIP-2930/2929 infrastructure with minimal changes. It creates no new transaction structure, so there is no risk of a chain split caused by nodes rejecting transactions because of unknown fields. For reference, at the Cancun fork a full sync node held about 27,869 bytecodes that no live account points to. No account's codeHash references them, so this gap cannot yield a discount, and consensus stays safe.
Backward compatibility and implementation burden
It requires a scheduled network upgrade, but there is no change to the transaction structure. Existing transactions that have an access list automatically become eligible for the discount after the fork, and transactions without an access list behave exactly as they do now. RPC methods such as eth_estimateGas SHOULD reflect the possible discount when an access list is present, wallets MAY provide a UI for adding addresses for the discount, and transaction builders MAY detect duplicate deployments automatically. The state trie structure, database schema, transaction parsing and RLP encoding do not change. The duplicate check is a set membership test, so it is O(1) and involves no additional state reads, so there is no DoS risk either.
Status: Draft, dropped from Hegotá candidates
This EIP is in Draft status and its content may still change. At ACDE #243 on 08.13, it was not accepted as a candidate because the champion (the person responsible for the proposal and for pushing it forward) was not on the call. At ACDE #244 on 08.27, it was dropped from the Hegotá candidates because it has no champion and because Ben Adams pointed out that SETCODEFROM achieves the same goal more generally. This means it was absorbed into another proposal that solves the same problem.