EIP-7907 Contract code size gas charge (Meter Contract Code Size)
Hegota Proposed for Inclusion · Fees & gas · EIP status Draft · created 2025-03-14
When loading contract code larger than 24KB, an extra 2 gas is charged per 32 bytes of the excess. This proposal makes callers pay gas in proportion to the work that contracts growing up to 64KB under EIP-7954 impose on nodes.
Why it is needed
Ethereum limited contract code size to 24KB in EIP-170. This is because, for large code, the amount read from disk, the preprocessing before execution and the size of the block proof all grow in proportion to the code length, and gas did not charge separately for this cost. In effect, the limit was set to prevent denial-of-service (DoS) attacks. EIP-7954 raises this limit to 64KB so that larger contracts can be deployed. However, if only the limit is raised and the cost is left unchanged, the party loading a large contract makes nodes do more work while paying the same gas. This EIP charges extra gas for the part above 24KB in proportion to its size, preserving the principle of the Ethereum gas model that you pay for the resources you use.
What changes
Today
- Contract code can be deployed only up to 24KB (24576 bytes).
- Loading a contract costs only the account access cost, regardless of the code size.
- The account information has no separate code size, so you have to read the entire code to know the size.
After EIP-7907
- With EIP-7954, up to 64KB can be deployed, and the part above 24KB costs an extra 2 gas per 32 bytes.
- Contract code also gets cold and warm states, and the extra cost is paid only the first time it is loaded in a transaction.
- A codesize field is added to the account information, so the size can be known without reading the whole code.
Who is affected
- Users: A transaction that loads a contract larger than 24KB for the first time costs more gas. The excess charge is 0 for code of 24KB or less.
- Contract and app developers: You can deploy up to 64KB, but the part above 24KB is charged the first time it is loaded in a transaction. When deciding whether to split code or keep it in one contract, you need to consider this cost as well.
- Wallets and EIP-7702 users: When calling a delegated account, if the delegation target code is cold, extra gas is paid. Gas estimation logic must reflect this cost.
- Client teams: You must implement tracking of the cold and warm state of code, revertible journaling, and the codesize field of the account tuple and the migration rules.
In depth
Charge formula and constants
The extra cost is computed as EXCESS_CODE_COST = ceil32(excess_code_size(len(code))) * GAS_PER_CODE_WORD // 32. Since excess_code_size(n) = max(0, n - 0x6000), code of 0x6000 (24576 bytes) or less has zero excess, and for larger code only the length beyond that is counted. ceil32 is a function that rounds up to a multiple of 32 bytes. GAS_PER_CODE_WORD is 2, so each word (32 bytes) of excess is charged 2 additional gas. Plugging into the formula, code of 65536 bytes, the maximum under EIP-7954, has 40960 bytes of excess, which is 1280 words, so 2560 gas is added. The accompanying constants COLD_SLOAD_COST 2100, WARM_STORAGE_READ_COST 100, and COLD_ACCOUNT_ACCESS_COST 2600 are taken unchanged from EIP-2929. The MAX_CODE_SIZE and MAX_INITCODE_SIZE limits themselves are left as set in EIP-7954 and are not changed. The activation block FORK_BLKNUM is not yet determined (TBD).
Cold and warm code state and the opcodes it applies to
The cold/warm distinction that previously existed only for accounts and storage is also applied to contract code. The gas schedule changes for the opcodes that load code, CALL, STATICCALL, DELEGATECALL, CALLCODE, and EXTCODECOPY, so that when the code is cold, EXCESS_CODE_COST is added to the access cost. The source table splits this into three cases. If both the account and the code are cold, COLD_ACCOUNT_ACCESS_COST 2600 is charged plus COLD_SLOAD_COST 2100 and EXCESS_CODE_COST. If the account is warm (it is in the access list, or its balance or storage was touched earlier) but the code is cold, WARM_STORAGE_READ_COST 100 is charged plus 2100 and EXCESS_CODE_COST. If both the account and the code are warm, only 100 is charged. If the call target is an address that delegates to another account through EIP-7702, additional gas is also counted when the code of the delegation target account is cold. The record of making code warm is subject to journaling, so like other state warming in EIP-2930 it is rolled back on revert. Empty code (keccak("") = 0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470) is always treated as warm.
When the transaction entry point is a large contract
If the to address of the transaction is itself a contract larger than 24KB, its code is loaded directly without going through a call opcode. In this case, the cost computed by rule 1 is charged before execution begins, and that contract code is marked warm. This cost is not added into the transaction's initial gas fee but is deducted separately. If gas runs out at this step and execution halts (out-of-gas halt), execution ends there and no balance transfer takes place.
Adding codesize to the account tuple and migration
The tuple representing an account changes from (nonce, balance, storage_root, code_hash) to (nonce, balance, storage_root, code_hash, codesize). This is because most key-value databases used by production clients cannot tell the size of a value without reading the whole value. A migration that moves the entire state at once is avoided, and two rules are set. First, accounts created or updated after FORK_BLKNUM write codesize into the tuple. Second, for accounts without a codesize field, the size is obtained by measuring the bytecode length when it is needed for charging. Such accounts may contain code larger than 24KB that was deployed after EIP-7954 was activated.
Why 2 gas per word and a 24KB floor were chosen
The 2 gas per word reflects three costs: disk I/O to fetch large code, the computation that preprocesses code before execution (JUMPDEST analysis), and the increase in Merkle proof size for blocks containing large contracts. The formula could have been written more simply, without the EIP-170 24KB limit, as ceil32(contract_size) * GAS_PER_CODE_WORD // 32. However, to stay conservative, and to avoid lowering the loading cost of existing contracts under 24KB, the 24KB floor was put into the formula. As a result, the charge in this EIP is an extra cost that applies only to contracts larger than 24KB.
The EXTCODECOPY exception and backwards compatibility
EXTCODECOPY only needs to read the requested range, so in theory it could be excluded from the charge. However, the block witness needs the entire code, so making an exception may require further protocol-level changes. The EIP therefore includes EXTCODECOPY in the charge for now and notes that an exception can be considered later. The backwards compatibility section says that CALL, STATICCALL, DELEGATECALL, CALLCODE, EXTCODESIZE, and EXTCODECOPY may incur extra gas when they access cold code. EXTCODESIZE, which was not in the opcode list of the Behavior section, appears here.
Draft status and fork discussion
This EIP is in Draft status, so its content may change. The Test Cases, Reference Implementation, and Security Considerations sections are still empty, and the activation block is also TBD. In the core developer calls, at 10.08 ACDE #247, EIP-7907 was added to the Hegota PFI (Proposed for Inclusion) list and the decision was deferred to the next call. It was treated as a proposal to close the DoS gap that arose when Glamsterdam raised only the contract size limit and dropped size-based charging.