EIP 2027: State Rent C - Net contract size accounting Source

AuthorAlexey Akhunov
TypeStandards Track

Simple Summary

Ethereum starts counting the number of storage slots filled and emptied in the contracts. Since the number of pre-existing slots is not currently accounted in the state, effectively, only net change in the number of slots is tracked. In the subsequent change, called Gross contract size accounting, the total number of storage slots starts being tracked.


This is part of the State Rent roadmap. This particular change introduces initial, net accounting of the number of the contract storage slots. Though not very useful on its own, it makes it possible to introduce gross accounting of the number of storage slots, which is useful for number of things:

  1. Gas cost of operations suchs as SLOAD and SSTORE will need to be increased to compensate for extra bandwidth consumed by the block proofs. Although in the beginning the cost would be fixed, it will later be automatically calibrated depending on the size of the contract SLOAD and SSTORE operate on.
  2. Snapshot sync protocols, like fast sync, warp sync, firehose, red queen, and perhaps others, will benefit from having the correct size of the contract storage present in the state (and therefore being provable via Merkle proofs).


Ethereum currently does not track the number of contract storage slots at all, and producing such number given the downloaded state cannot be done in constant O(1) time.


Each contract (account with codeHash field not equal to 0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470, which the hash of the empty code) gets a new uint64 field, called storagesize. On and after block C, the semantics of the operation SSTORE (location, value) changes as follows:

  • If previous value of the [location] is 0, and value is not 0, increment storagesize (semantics of increment described below)
  • If previous value of the [location] is not 0, and value is 0, decrement storagesize (semantics of decrement described below)
  • As with other state changes, changes of storagesize get reverted when the execution frame reverts, i.e. it needs to use the same techniques as storage values, like journalling (in Geth), and substates (in Parity). Value of storagesize is not observable from contracts at this point.

Semantics of increment storagesize

If storagesize is not present, storagesize = HUGE_NUMBER + 1. If storagesize is present, storagesize = storagesize + 1.

Semantics of decrement storagesize

If storagesize is not present, storagesize = HUGE_NUMBER - 1. If storagesize is present, storagesize = storagesize - 1.


There is a constant HUGE_NUMBER. It needs to be large enough so that no real metrics (contract storage size, number of accounts, number of contracts, total size of code, total size of storage) will never reach that number, and small enough that it fits in an unsigned 64-bit integer. Current suggestion is to have HUGE_NUMBER = 2^63, which is binary representation is the a single bit in a 64-bit number.

The idea is to make it decidable later whether the storagesize was ever incremented/decremented (presence of the field), and whether it has been converted from net to gross (by value being smaller than HUGE_NUMBER/2 - because it will not be possible for any contract be larger than 2^62 at the block C).


A mechanism for estimation of contract storage size has been proposed here. But it does have a big drawback of introducing a lot of complexity into the consensus (in the form of estimation algorithm, which has quite a few edge cases to cater for different sizes of the storage).

Backwards Compatibility

This change is not backwards compatible and requires hard fork to be activated. Since the newly introduced field is not observable, this change does not impact any operations of the existing smart contracts.

Test Cases

Tests cases will be generated out of a reference implementation.


There will be proof of concept implementation to refine and clarify the specification.

Copyright and related rights waived via CC0.