Skip to content

Amsterdam: EIP-8037: State Creation Gas Cost Increase#9815

Open
daniellehrner wants to merge 16 commits intobesu-eth:mainfrom
daniellehrner:feat/eip_8037
Open

Amsterdam: EIP-8037: State Creation Gas Cost Increase#9815
daniellehrner wants to merge 16 commits intobesu-eth:mainfrom
daniellehrner:feat/eip_8037

Conversation

@daniellehrner
Copy link
Contributor

PR description

Adds support for EIP-8037 for Amsterdam:

  1. State gas infrastructure: New StateGasCostCalculator interface + Eip8037StateGasCostCalculator with dynamic cost_per_state_byte (quantized, from block gas limit). Two new AtomicLong fields in TxValues: stateGasUsed and
    stateGasReservoir.
  2. Reservoir model: MainnetTransactionProcessor splits execution gas into gasLeft (capped at 16.7M) and reservoir (overflow). MessageFrame.consumeStateGas() draws from reservoir first, then regular gas.
  3. Gas cost splits: AmsterdamGasCalculator reduces regular gas for all state-creation operations (CREATE 32K→9K, SSTORE set 20K→2.9K, new account 25K→0, etc). State portion charged via charge*StateGas() methods at each
    operation call site.
  4. 2D block accounting: gas_used = max(block_regular_gas, block_state_gas). Calldata floor applies to regular dimension only. TransactionProcessingResult carries both dimensions. GasState record tracks both during block
    building.
  5. Pre-Amsterdam unchanged: StateGasCostCalculator.NONE is a no-op, reservoir is always 0, all charge* methods return true.
  6. Block building: BlockTransactionSelector tracks cumulative regular and state gas separately via GasState. A transaction is rejected if adding it would exceed the block gas limit in either dimension. Post-execution
    validation checks both dimensions since state gas is only known after execution.

@daniellehrner daniellehrner added the amsterdam relating to Glamsterdam fork label Feb 16, 2026
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR implements EIP-8037, which introduces multidimensional gas metering for the Amsterdam hard fork. The main purpose is to split gas costs into regular gas and state gas dimensions, with state-creation operations (CREATE, SSTORE, code deposits, etc.) having their costs dynamically calculated based on block gas limits.

Changes:

  • Introduces StateGasCostCalculator interface and Eip8037StateGasCostCalculator implementation with dynamic cost-per-state-byte calculations
  • Implements reservoir gas model where transaction gas is split between regular gas (capped at 16.7M) and overflow reservoir for state gas consumption
  • Adds 2D block gas accounting where gas_metered = max(regular_gas, state_gas) for block capacity checks

Reviewed changes

Copilot reviewed 29 out of 29 changed files in this pull request and generated 4 comments.

Show a summary per file
File Description
StateGasCostCalculator.java Defines strategy interface for state gas calculations with default no-op implementation
Eip8037StateGasCostCalculator.java Implements EIP-8037 state gas cost calculations with quantized cost-per-state-byte formula
AmsterdamGasCalculator.java Extends OsakaGasCalculator with reduced regular gas costs for state-creation operations
TxValues.java Adds atomic fields for tracking state gas used and reservoir
MessageFrame.java Adds state gas consumption methods and reservoir management
TransactionProcessingResult.java Adds stateGasUsed field to track state gas dimension
MainnetTransactionProcessor.java Implements reservoir initialization and runtime TX_MAX_GAS_LIMIT enforcement on regular gas
BlockGasAccountingStrategy.java Extends interface to support 2D gas accounting with regular and state dimensions
GasState.java New record tracking cumulative regular and state gas during block building
BlockSizeTransactionSelector.java Updates to use 2D gas state for transaction selection with capacity checks across both dimensions

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

@github-project-automation github-project-automation bot moved this to Backlog in Amsterdam Feb 17, 2026
@daniellehrner daniellehrner moved this from Backlog to In progress in Amsterdam Feb 17, 2026
@daniellehrner daniellehrner self-assigned this Feb 17, 2026
Implement state gas tracking in the EVM layer:
- StateGasCostCalculator and Eip8037StateGasCostCalculator for cost-per-state-byte
- AmsterdamGasCalculator with split regular/state gas costs
- MessageFrame state gas reservoir, spill, and collision tracking
- State gas charging in SSTORE, CREATE, CALL, and SELFDESTRUCT operations

Signed-off-by: daniellehrner <daniel.lehrner@consensys.net>
Wire state gas into transaction processing, block building, and validation:
- MainnetTransactionProcessor: intrinsic state gas, reservoir init, spill handling
- BlockGasAccountingStrategy.AMSTERDAM: 2D gas metering (max of regular, state)
- BlockGasUsedValidator.AMSTERDAM: pre-refund 2D validation
- OsakaTargetingGasLimitCalculator: Amsterdam constructor with uncapped tx gas limit
- Block creation: 2D headroom checks for transaction selection
- TransactionProcessingResult: carry state gas used

Signed-off-by: daniellehrner <daniel.lehrner@consensys.net>
Update reference test fixtures to bal@v5.2.0 for EIP-8037 compatibility.

Signed-off-by: daniellehrner <daniel.lehrner@consensys.net>
Extract gas accounting logic from MainnetTransactionProcessor into a
testable TransactionGasAccounting class with builder pattern. Add tests
for SSTORE state gas, block gas accounting strategy, state gas spill,
and regular gas limit enforcement.

Signed-off-by: daniellehrner <daniel.lehrner@consensys.net>
daniellehrner and others added 7 commits March 6, 2026 06:27
Signed-off-by: daniellehrner <daniel.lehrner@consensys.net>
e.g. ./gradlew --no-daemon :ethereum:core:jmh -Pincludes=Mod -Pexcludes=Mul,Add,SMod -Pcases=MOD_256_128,MOD_256_192

Signed-off-by: Simon Dudley <simon.dudley@consensys.net>
…eth#9972)

* preserve caller-provided gas prices in TransactionSimulator

When isAllowExceedingBalance is true but the caller explicitly provided
non-zero gas pricing parameters, preserve them and the block header's
baseFee so effective gas price is computed correctly during execution.
This ensures gas fees are actually charged so that stateRoot and block
hash are correct in eth_simulateV1 results.

When gas params are absent or zero (typical eth_call, or explicitly
zero maxFeePerGas), behavior is unchanged - all fields stay zero and
baseFee is zeroed to avoid validation failures.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Signed-off-by: Sally MacFarlane <macfarla.github@gmail.com>

---------

Signed-off-by: Sally MacFarlane <macfarla.github@gmail.com>
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
Signed-off-by: daniellehrner <daniel.lehrner@consensys.net>
Signed-off-by: daniellehrner <daniel.lehrner@consensys.net>
Signed-off-by: daniellehrner <daniel.lehrner@consensys.net>
@daniellehrner daniellehrner marked this pull request as ready for review March 9, 2026 10:33
@daniellehrner
Copy link
Contributor Author

Tests with the latest version of the spec tests can be run with:

./gradlew referenceTestsDevnet --tests "*_amsterdam_*"

…adle task

Signed-off-by: daniellehrner <daniel.lehrner@consensys.net>
'src/reference-test/resources/custom'
}
}
referenceTestDevnet {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Before we were always bulding the referenceTestDevnet classes, but not running them in the CI. Now we are not enough buidling them. This separation of referenceTestDevnet from referenceTests is needed, because the new test v5.3 contains all tests back to Frontier and not only the Amsterdam ones. This makes buidling them too strainous in the CI where we only want to run the referenceTests task

# Conflicts:
#	ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/OsakaTargetingGasLimitCalculator.java
Copy link
Contributor

@matkt matkt left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For safety reason it will be nice to have a second reviewer (@fab-10 ) and hoodi fullsync

setWorkingState(getWorkingState() + gasUsedByTransaction);

final long regularGasUsed =
gasAccountingStrategy.calculateBlockGas(
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the method name calculateBlockGas is not clear, since it seems related to the block, while it is for a tx

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I see that you renamed the variable, that's fine but also the method could named to better reflect what it does

Signed-off-by: daniellehrner <daniel.lehrner@consensys.net>
Copy link
Contributor

@fab-10 fab-10 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM just a nit: a method naming

setWorkingState(getWorkingState() + gasUsedByTransaction);

final long regularGasUsed =
gasAccountingStrategy.calculateBlockGas(
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I see that you renamed the variable, that's fine but also the method could named to better reflect what it does

private boolean blockOccupancyAboveThreshold(final long cumulativeGasUsed) {
final long gasRemaining = blockGasLimit - cumulativeGasUsed;
final double occupancyRatio = (double) cumulativeGasUsed / (double) blockGasLimit;
private boolean blockOccupancyAboveThreshold(final GasState state) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

…sactionRegularGas

Signed-off-by: daniellehrner <daniel.lehrner@consensys.net>
…Processor.java, AbstractBlockProcessorTest.java

2. move handleStateGasSpill into its own method

3. Added CREATE state gas underflow guard

4. Improved failCodeDepositWithoutRollback documentation

Signed-off-by: daniellehrner <daniel.lehrner@consensys.net>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

amsterdam relating to Glamsterdam fork

Projects

None yet

Development

Successfully merging this pull request may close these issues.

6 participants