# Besu: Amsterdam state-gas conformance review

Reviewed public sources on 2026-10-27. **No new, demonstrated consensus defect in normal Amsterdam block execution was established.** Three existing reports match concrete differences at the reviewed head: an Amsterdam convenience factory using Prague gas rules, an auxiliary scalar gas estimate, and optional LIGHT validation. Their reachability and specification limits are stated below. None is presented as a new full-node consensus exploit.

This is the bounded Besu EIP-8037/7778/8038 item, not an implementation audit of every Glamsterdam client or EIP. Source inspection and public HTTP reads only: no Besu build, local execution reproducer, node request, transaction submission, or private source was used. “Correct” below means the inspected code implements the particular rule; it is not a proof over all executions.

## Immutable sources and fork/spec versions

| Source | Branch and reviewed commit | Pin discovery |
|---|---|---|
| Besu | main: `aa06c4f8dfc461e483d46c6a1ac72b5bfef8d945` | [commits/main](https://api.github.com/repos/besu-eth/besu/commits/main) |
| Execution specifications (EELS) | forks/bogota: `7f2f4c9bf6d73b09ecb8b24eb14d08bf0cf0247b` | [commits/forks/bogota](https://api.github.com/repos/ethereum/execution-specs/commits/forks/bogota) |
| Geth comparator | master: `8817f99f92852f8ac53e596de6202dd9e3494065` | [commits/master](https://api.github.com/repos/ethereum/go-ethereum/commits/master) |
| EIP text snapshot | master: `d4c575521d99ec881a444ab3af604e684b5f0743` | [commits/master](https://api.github.com/repos/ethereum/EIPs/commits/master) |
| Consensus specifications | master: `8a80ffa82bd49aac0dd6db17f9e8150aa257fbc2` | [commits/master](https://api.github.com/repos/ethereum/consensus-specs/commits/master) |
| Execution API reference | main: `3284ee80c3da3e516c53782dde75157cccf1ebdc` | [commits/main](https://api.github.com/repos/ethereum/execution-apis/commits/main) |

The mutable API URLs establish how heads were selected; all code citations below are immutable blob URLs at those heads. Besu code was read as raw.githubusercontent.com text (including the source corresponding to each blob citation), not GitHub HTML. EELS was read from the Amsterdam directory on **forks/bogota**, not a nonexistent master branch.

The exact **scheduled-for-inclusion** list at this snapshot is the following 18 EIPs. “Version” means the immutable EIP file at the EIPs commit above, rather than an invented semantic version. [EIPS/eip-7773.md#L21-L40](https://github.com/ethereum/EIPs/blob/d4c575521d99ec881a444ab3af604e684b5f0743/EIPS/eip-7773.md#L21-L40) is the scheduling authority.

| EIP | Scheduled change | Current text version at review |
|---|---|---|
| 2780 | Resource-Based Intrinsic Transaction Gas | [EIP-2780@d4c575521d99](https://github.com/ethereum/EIPs/blob/d4c575521d99ec881a444ab3af604e684b5f0743/EIPS/eip-2780.md) |
| 7688 | Forward Compatible Consensus Data Structures | [EIP-7688@d4c575521d99](https://github.com/ethereum/EIPs/blob/d4c575521d99ec881a444ab3af604e684b5f0743/EIPS/eip-7688.md) |
| 7708 | ETH Transfers Emit a Log | [EIP-7708@d4c575521d99](https://github.com/ethereum/EIPs/blob/d4c575521d99ec881a444ab3af604e684b5f0743/EIPS/eip-7708.md) |
| 7732 | Enshrined Proposer-Builder Separation | [EIP-7732@d4c575521d99](https://github.com/ethereum/EIPs/blob/d4c575521d99ec881a444ab3af604e684b5f0743/EIPS/eip-7732.md) |
| 7778 | Block Gas Accounting without Refunds | [EIP-7778@d4c575521d99](https://github.com/ethereum/EIPs/blob/d4c575521d99ec881a444ab3af604e684b5f0743/EIPS/eip-7778.md) |
| 7843 | SLOTNUM Opcode | [EIP-7843@d4c575521d99](https://github.com/ethereum/EIPs/blob/d4c575521d99ec881a444ab3af604e684b5f0743/EIPS/eip-7843.md) |
| 7928 | Block-Level Access Lists | [EIP-7928@d4c575521d99](https://github.com/ethereum/EIPs/blob/d4c575521d99ec881a444ab3af604e684b5f0743/EIPS/eip-7928.md) |
| 7954 | Increase Maximum Contract Size | [EIP-7954@d4c575521d99](https://github.com/ethereum/EIPs/blob/d4c575521d99ec881a444ab3af604e684b5f0743/EIPS/eip-7954.md) |
| 7976 | Increase Calldata Floor Cost | [EIP-7976@d4c575521d99](https://github.com/ethereum/EIPs/blob/d4c575521d99ec881a444ab3af604e684b5f0743/EIPS/eip-7976.md) |
| 7981 | Increase Access List Cost | [EIP-7981@d4c575521d99](https://github.com/ethereum/EIPs/blob/d4c575521d99ec881a444ab3af604e684b5f0743/EIPS/eip-7981.md) |
| 7997 | Deterministic Factory Contract | [EIP-7997@d4c575521d99](https://github.com/ethereum/EIPs/blob/d4c575521d99ec881a444ab3af604e684b5f0743/EIPS/eip-7997.md) |
| 8024 | Backward Compatible SWAPN, DUPN, EXCHANGE | [EIP-8024@d4c575521d99](https://github.com/ethereum/EIPs/blob/d4c575521d99ec881a444ab3af604e684b5f0743/EIPS/eip-8024.md) |
| 8037 | State Creation Gas Cost Increase | [EIP-8037@d4c575521d99](https://github.com/ethereum/EIPs/blob/d4c575521d99ec881a444ab3af604e684b5f0743/EIPS/eip-8037.md) |
| 8038 | State-Access Gas Cost Update | [EIP-8038@d4c575521d99](https://github.com/ethereum/EIPs/blob/d4c575521d99ec881a444ab3af604e684b5f0743/EIPS/eip-8038.md) |
| 8045 | Exclude Slashed Validators from Proposing | [EIP-8045@d4c575521d99](https://github.com/ethereum/EIPs/blob/d4c575521d99ec881a444ab3af604e684b5f0743/EIPS/eip-8045.md) |
| 8061 | Increase Exit and Consolidation Churn | [EIP-8061@d4c575521d99](https://github.com/ethereum/EIPs/blob/d4c575521d99ec881a444ab3af604e684b5f0743/EIPS/eip-8061.md) |
| 8246 | Remove SELFDESTRUCT Burn | [EIP-8246@d4c575521d99](https://github.com/ethereum/EIPs/blob/d4c575521d99ec881a444ab3af604e684b5f0743/EIPS/eip-8246.md) |
| 8282 | Builder Execution Requests | [EIP-8282@d4c575521d99](https://github.com/ethereum/EIPs/blob/d4c575521d99ec881a444ab3af604e684b5f0743/EIPS/eip-8282.md) |

EELS independently names the 14 execution changes (2780, 7708, 7778, 7843, 7928, 7954, 7976, 7981, 7997, 8024, 8037, 8038, 8246, 8282): [src/ethereum/forks/amsterdam/__init__.py#L7-L20](https://github.com/ethereum/execution-specs/blob/7f2f4c9bf6d73b09ecb8b24eb14d08bf0cf0247b/src/ethereum/forks/amsterdam/__init__.py#L7-L20). This module still uses `Unscheduled(order_index=3)`: [src/ethereum/forks/amsterdam/__init__.py#L41-L43](https://github.com/ethereum/execution-specs/blob/7f2f4c9bf6d73b09ecb8b24eb14d08bf0cf0247b/src/ethereum/forks/amsterdam/__init__.py#L41-L43). This is a spec configuration marker, not evidence of mainnet activation.

Gloas's own feature list includes pinned versions of 7688, 7732, 7843, 8070, 8045, 8061, 8261, 8282 and explicitly warns: “Each link above points to the specific version targeted by this specification, which may differ from the latest published version of the EIPs.” [gloas/beacon-chain.md#L163-L186](https://github.com/ethereum/consensus-specs/blob/8a80ffa82bd49aac0dd6db17f9e8150aa257fbc2/specs/gloas/beacon-chain.md#L163-L186). Thus the lists are not silently conflated: 8070 is in the meta's **networking** section and 8261 its **informational** section, not the 18-entry scheduled section. The meta separately lists networking 7975, 8070, 8136, 8159, 8189 and informational 7904, 8261 ([EIPS/eip-7773.md#L42-L55](https://github.com/ethereum/EIPs/blob/d4c575521d99ec881a444ab3af604e684b5f0743/EIPS/eip-7773.md#L42-L55)).

The target normative pages read were [8037](https://eips.ethereum.org/EIPS/eip-8037), [7778](https://eips.ethereum.org/EIPS/eip-7778), and [8038](https://eips.ethereum.org/EIPS/eip-8038); their reviewed file versions are the snapshot links above. These proposals are Last Call with deadline 2026-11-01 in their front matter. EELS implementation version is independently fixed by its pin. Test reference versions must not be mistaken for current text: the Amsterdam test spec references pin 8037 to `19bdfb4f97064dfbeb3d41d31efac211265b49a6`, 7778 to `4897aec97160c72d2080acf928b132f2efc1a886`, and 8038 to `f83531466a3862853424a81d000727b3043ef2cc`:
[8037 test spec#L25-L27](https://github.com/ethereum/execution-specs/blob/7f2f4c9bf6d73b09ecb8b24eb14d08bf0cf0247b/tests/amsterdam/eip8037_state_creation_gas_cost_increase/spec.py#L25-L27),
[7778 test spec#L14-L16](https://github.com/ethereum/execution-specs/blob/7f2f4c9bf6d73b09ecb8b24eb14d08bf0cf0247b/tests/amsterdam/eip7778_block_gas_accounting_without_refunds/spec.py#L14-L16),
[8038 test spec#L14-L16](https://github.com/ethereum/execution-specs/blob/7f2f4c9bf6d73b09ecb8b24eb14d08bf0cf0247b/tests/amsterdam/eip8038_state_access_gas_cost_increase/spec.py#L14-L16).
The immutable EELS gas/fork implementation is the primary comparator for findings.

Mainnet applicability: the meta's activation table has an empty Mainnet row ([EIPS/eip-7773.md#L62-L70](https://github.com/ethereum/EIPs/blob/d4c575521d99ec881a444ab3af604e684b5f0743/EIPS/eip-7773.md#L62-L70)). The differences reported here require Amsterdam selection or its new state-gas dimension. No pre-Amsterdam vulnerability is asserted; no mainnet-active flaw details are included.

## Candidate 1 — convenience Amsterdam EVM factory selects Prague gas rules (known)

**1. Spec, verbatim.** EIP-8038's parameter table specifies the cold-account change: “`COLD_ACCOUNT_ACCESS` … 2,600 | 3,000”. Its prose states: “This EIP raises `COLD_ACCOUNT_ACCESS`, while `COLD_STORAGE_ACCESS` and `WARM_ACCESS` are unchanged”. [EIP-8038, cost components and parameters](https://eips.ethereum.org/EIPS/eip-8038#parameters); immutable [EIPS/eip-8038.md#L29-L53](https://github.com/ethereum/EIPs/blob/d4c575521d99ec881a444ab3af604e684b5f0743/EIPS/eip-8038.md#L29-L53). EELS is unambiguous:
```python
COLD_ACCOUNT_ACCESS: Final[ExecutionGas] = ExecutionGas(Uint(3000))
```
[src/ethereum/forks/amsterdam/vm/gas.py#L75-L85](https://github.com/ethereum/execution-specs/blob/7f2f4c9bf6d73b09ecb8b24eb14d08bf0cf0247b/src/ethereum/forks/amsterdam/vm/gas.py#L75-L85). For EIP-8037, EELS also defines 1530 per state byte and 120/64/23 bytes: [src/ethereum/forks/amsterdam/vm/gas.py#L47-L59](https://github.com/ethereum/execution-specs/blob/7f2f4c9bf6d73b09ecb8b24eb14d08bf0cf0247b/src/ethereum/forks/amsterdam/vm/gas.py#L47-L59).

**2. Besu, verbatim.** [evm/src/main/java/org/hyperledger/besu/evm/MainnetEVMs.java#L1096-L1098](https://github.com/besu-eth/besu/blob/aa06c4f8dfc461e483d46c6a1ac72b5bfef8d945/evm/src/main/java/org/hyperledger/besu/evm/MainnetEVMs.java#L1096-L1098):
```java
public static EVM amsterdam(final BigInteger chainId, final EvmConfiguration evmConfiguration) {
  return amsterdam(new PragueGasCalculator(), chainId, evmConfiguration);
}
```
The explicit overload then uses that supplied calculator with `EvmSpecVersion.AMSTERDAM` ([evm/src/main/java/org/hyperledger/besu/evm/MainnetEVMs.java#L1108-L1117](https://github.com/besu-eth/besu/blob/aa06c4f8dfc461e483d46c6a1ac72b5bfef8d945/evm/src/main/java/org/hyperledger/besu/evm/MainnetEVMs.java#L1108-L1117)).
[evm/src/main/java/org/hyperledger/besu/evm/fluent/EvmSpec.java#L486-L491](https://github.com/besu-eth/besu/blob/aa06c4f8dfc461e483d46c6a1ac72b5bfef8d945/evm/src/main/java/org/hyperledger/besu/evm/fluent/EvmSpec.java#L486-L491):
```java
final EvmSpec evmSpec = new EvmSpec(MainnetEVMs.amsterdam(chainId, evmConfiguration));
```
The AMSTERDAM enum dispatch selects this factory ([evm/src/main/java/org/hyperledger/besu/evm/fluent/EvmSpec.java#L120-L127](https://github.com/besu-eth/besu/blob/aa06c4f8dfc461e483d46c6a1ac72b5bfef8d945/evm/src/main/java/org/hyperledger/besu/evm/fluent/EvmSpec.java#L120-L127)). Prague extends Cancun ([evm/src/main/java/org/hyperledger/besu/evm/gascalculator/PragueGasCalculator.java#L34-L36](https://github.com/besu-eth/besu/blob/aa06c4f8dfc461e483d46c6a1ac72b5bfef8d945/evm/src/main/java/org/hyperledger/besu/evm/gascalculator/PragueGasCalculator.java#L34-L36)), retaining the older access schedule; the Berlin inherited cold-account constant is `2600L` and its accessor returns it ([evm/src/main/java/org/hyperledger/besu/evm/gascalculator/BerlinGasCalculator.java#L37-L42](https://github.com/besu-eth/besu/blob/aa06c4f8dfc461e483d46c6a1ac72b5bfef8d945/evm/src/main/java/org/hyperledger/besu/evm/gascalculator/BerlinGasCalculator.java#L37-L42), [evm/src/main/java/org/hyperledger/besu/evm/gascalculator/BerlinGasCalculator.java#L110-L113](https://github.com/besu-eth/besu/blob/aa06c4f8dfc461e483d46c6a1ac72b5bfef8d945/evm/src/main/java/org/hyperledger/besu/evm/gascalculator/BerlinGasCalculator.java#L110-L113)). The correct Amsterdam constant is 3000 ([evm/src/main/java/org/hyperledger/besu/evm/gascalculator/AmsterdamGasCalculator.java#L65-L74](https://github.com/besu-eth/besu/blob/aa06c4f8dfc461e483d46c6a1ac72b5bfef8d945/evm/src/main/java/org/hyperledger/besu/evm/gascalculator/AmsterdamGasCalculator.java#L65-L74)).

**3. Diverging condition, words only.** A library/tool caller selects AMSTERDAM through the convenience factory or fluent EvmSpec, then executes BALANCE on a cold ordinary account. The caller receives Prague cold-account charging instead of Amsterdam charging: 2600 rather than 3000 for that access. An execution budget between those requirements can also change success versus out-of-gas. This same wrong calculator selection prevents using the proper Amsterdam state-gas schedule; the cold BALANCE case alone is sufficient and does not depend on demonstrating every state-creation path.

**4. Geth comparator.** Geth's Amsterdam jump table explicitly enables 8037 and 8038 together:
```go
enable8037And8038(&instructionSet)
```
[core/vm/jump_table.go#L106-L111](https://github.com/ethereum/go-ethereum/blob/8817f99f92852f8ac53e596de6202dd9e3494065/core/vm/jump_table.go#L106-L111). Its BALANCE/EXTCODEHASH gas function returns:
```go
return GasCosts{ExecutionGas: params.ColdAccountAccessAmsterdam - params.WarmStorageReadCostEIP2929}, nil
```
with the warm base already charged ([core/vm/operations_acl.go#L196-L207](https://github.com/ethereum/go-ethereum/blob/8817f99f92852f8ac53e596de6202dd9e3494065/core/vm/operations_acl.go#L196-L207)). `ColdAccountAccessAmsterdam = 3000`: [params/protocol_params.go#L115-L125](https://github.com/ethereum/go-ethereum/blob/8817f99f92852f8ac53e596de6202dd9e3494065/params/protocol_params.go#L115-L125). This agrees with EELS, not the Besu convenience overload.

**5. Confidence and attempted disproof.** **High for the library factory; no normal-node consensus finding.** I checked whether the ordinary Amsterdam protocol builder calls the faulty overload: it does not. It supplies `AmsterdamGasCalculator` explicitly ([ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/MainnetProtocolSpecs.java#L1118-L1123](https://github.com/besu-eth/besu/blob/aa06c4f8dfc461e483d46c6a1ac72b5bfef8d945/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/MainnetProtocolSpecs.java#L1118-L1123)). The builder also installs the 2D strategy ([ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/MainnetProtocolSpecs.java#L1184-L1190](https://github.com/besu-eth/besu/blob/aa06c4f8dfc461e483d46c6a1ac72b5bfef8d945/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/MainnetProtocolSpecs.java#L1184-L1190)). That disproves the stronger claim that a normal Amsterdam node executes with Prague gas. The explicit-calculator overload itself is sound when passed the right calculator.

**6. Severity.** **Wrong gas or fee**, confined to a library/tool execution configured through the convenience overload; possible wrong execution outcome in that context. No network consensus split demonstrated.

**Known-check:** **known**, [Besu PR #11526](https://github.com/besu-eth/besu/pull/11526), **open** at review. Its body specifically names the Prague calculator in these Amsterdam overloads and states that node execution is unchanged. The PR's other SELFDESTRUCT work is outside this finding. Search: `repo:besu-eth/besu "amsterdam" "PragueGasCalculator"`; `repo:besu-eth/besu "MainnetEVMs" "Amsterdam"`, plus the broad EIP/name searches below. No public Hive result was identified as testing this convenience-factory path.

## Candidate 2 — auxiliary scalar maxUsedGas applies the floor to execution before adding state (known; RPC qualification)

**1. Spec, verbatim, and normative limit.** EIP-8037 defines:
```python
tx_gas_used_before_refund = tx.gas - tx_output.gas_left - tx_output.state_gas_reservoir
tx_gas_refund = min(tx_gas_used_before_refund // 5, tx_output.refund_counter)
tx_gas_used_after_refund = tx_gas_used_before_refund - tx_gas_refund
tx_gas_used = max(tx_gas_used_after_refund, calldata_floor_gas_cost)
```
[EIP-8037 transaction-level accounting](https://eips.ethereum.org/EIPS/eip-8037#transaction-level-gas-accounting), [EIPS/eip-8037.md#L225-L234](https://github.com/ethereum/EIPs/blob/d4c575521d99ec881a444ab3af604e684b5f0743/EIPS/eip-8037.md#L225-L234); EELS [src/ethereum/forks/amsterdam/vm/gas.py#L1211-L1227](https://github.com/ethereum/execution-specs/blob/7f2f4c9bf6d73b09ecb8b24eb14d08bf0cf0247b/src/ethereum/forks/amsterdam/vm/gas.py#L1211-L1227). This distinguishes the scalar total from the separately floored execution dimension used for blocks.

**Important qualification:** these three EIPs do not themselves normatively define an RPC field called `maxUsedGas`. This is a concrete known scalar-reporting/Geth-compatibility difference tied to their gas arithmetic, not proof of an independent EIP-mandated RPC requirement. The pre-refund scalar expected by this RPC comes from the public Besu report/API fixture and Geth below; do not read the post-refund spec quote as defining that field.

**2. Besu, verbatim.** [ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/TransactionGasAccounting.java#L91-L106](https://github.com/besu-eth/besu/blob/aa06c4f8dfc461e483d46c6a1ac72b5bfef8d945/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/TransactionGasAccounting.java#L91-L106):
```java
final long consumedGas = txGasLimit() - remainingGas() - stateGasReservoir();
final long stateGas = stateGasUsed();
final long executionGas = consumedGas - stateGas;
```
and:
```java
final long flooredExecutionGas = Math.max(executionGas, floorCost());
final long gasUsedByTransaction = flooredExecutionGas + stateGas;
final long usedGas = txGasLimit() - refundedGas();
return new GasResult(stateGas, gasUsedByTransaction, usedGas, flooredExecutionGas);
```
The simulate result passes `result.getEstimateGasUsedByTransaction()` as its fourth constructor argument ([ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/results/BlockStateCallResult.java#L134-L148](https://github.com/besu-eth/besu/blob/aa06c4f8dfc461e483d46c6a1ac72b5bfef8d945/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/results/BlockStateCallResult.java#L134-L148)), which is serialized as `maxUsedGas` ([ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/results/CallProcessingResult.java#L32-L54](https://github.com/besu-eth/besu/blob/aa06c4f8dfc461e483d46c6a1ac72b5bfef8d945/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/results/CallProcessingResult.java#L32-L54)). The estimate endpoint uses that estimate as a lower bound ([ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/EthEstimateGas.java#L85-L90](https://github.com/besu-eth/besu/blob/aa06c4f8dfc461e483d46c6a1ac72b5bfef8d945/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/EthEstimateGas.java#L85-L90)).

**3. Diverging condition, words only.** An Amsterdam simulated call creates enough state to have positive state gas, while its execution gas is below the calldata floor. Besu's auxiliary scalar is max(execution, floor) plus state, while the intended pre-refund scalar is max(execution plus state, floor). The public PR gives execution 24,145, floor 24,576, state 232,560: Besu 257,136 versus 256,705, an overcount of 431. These are source-report figures, not an independently executed transaction. The estimate lower bound can consequently be inflated.

**4. Geth comparator.** [core/state_transition.go#L1060-L1085](https://github.com/ethereum/go-ethereum/blob/8817f99f92852f8ac53e596de6202dd9e3494065/core/state_transition.go#L1060-L1085):
```go
gasUsedBeforeRefund := st.msg.GasLimit - gasLeft
```
```go
peakUsed = gasUsedBeforeRefund
```
and, if the post-refund floor binds:
```go
peakUsed = max(peakUsed, floorDataGas)
```
Geth separately computes `txExecutionGas := max(gasUsedBeforeRefund-txStateGas, floorDataGas)` at line 1066. It exposes the separate MaxUsedGas in simulation ([internal/ethapi/simulate.go#L148-L154](https://github.com/ethereum/go-ethereum/blob/8817f99f92852f8ac53e596de6202dd9e3494065/internal/ethapi/simulate.go#L148-L154), [internal/ethapi/simulate.go#L456-L466](https://github.com/ethereum/go-ethereum/blob/8817f99f92852f8ac53e596de6202dd9e3494065/internal/ethapi/simulate.go#L456-L466)). Geth agrees with the intended scalar treatment, while Besu reused the block-dimension calculation for an auxiliary scalar.

**5. Confidence and attempted disproof.** **High for this arithmetic/RPC difference; not a consensus candidate.** I followed the distinct `usedGas` and `flooredExecutionGas` values: actual gas paid and receipts use the refunded/floored total, and block execution accounting intentionally floors execution alone. Therefore it would be wrong to “fix” the block dimension to the scalar formula. The divergence disappears when state gas is zero or execution already exceeds the floor. I did not independently reproduce the PR's creation fixture.

**6. Severity.** **Wrong gas or fee** in the sense of a wrong reported estimate/auxiliary gas quantity, not an incorrect fee actually charged or a receipt/header mismatch.

**Known-check:** **known**, [Besu PR #11580](https://github.com/besu-eth/besu/pull/11580), **open**; [execution-apis #887](https://github.com/ethereum/execution-apis/issues/887), **open**. The PR explicitly names the example, scalar formula, `eth_estimateGas` lower bound, and Hive fixture `ethSimulate-override-block-num`. It states receipt and block accounting are unaffected. This fixture is distinct from the scoped EEST malformed-header cases discussed below.

## Candidate 3 — optional LIGHT body validation skips Amsterdam header gas_used (known; custom API only)

**1. Spec, verbatim.** EIP-8037:
```python
gas_used = max(block_output.block_execution_gas_used, block_output.block_state_gas_used)
```
[EIP-8037 block-level accounting](https://eips.ethereum.org/EIPS/eip-8037#block-level-gas-accounting), [EIPS/eip-8037.md#L252-L261](https://github.com/ethereum/EIPs/blob/d4c575521d99ec881a444ab3af604e684b5f0743/EIPS/eip-8037.md#L252-L261).
EELS additionally enforces the header equality:
```python
block_gas_used = max(
    block_output.block_gas_used,
    block_output.block_state_gas_used,
)
if block_gas_used != block.header.gas_used:
    raise InvalidBlock(f"{block_gas_used} != {block.header.gas_used}")
```
[src/ethereum/forks/amsterdam/fork.py#L335-L340](https://github.com/ethereum/execution-specs/blob/7f2f4c9bf6d73b09ecb8b24eb14d08bf0cf0247b/src/ethereum/forks/amsterdam/fork.py#L335-L340).

**2. Besu, verbatim.** [ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/BlockGasUsedValidator.java#L67-L72](https://github.com/besu-eth/besu/blob/aa06c4f8dfc461e483d46c6a1ac72b5bfef8d945/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/BlockGasUsedValidator.java#L67-L72):
```java
return blockGas.isEmpty() || header.getGasUsed() == blockGas.getAsLong();
```
The syncing validator supplies an absent processed-gas value:
```java
if (!blockBodyValidator.validateBodyLight(
    context, block, receipts, ommerValidationMode, OptionalLong.empty())) {
```
[ethereum/core/src/main/java/org/hyperledger/besu/ethereum/MainnetBlockValidator.java#L443-L455](https://github.com/besu-eth/besu/blob/aa06c4f8dfc461e483d46c6a1ac72b5bfef8d945/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/MainnetBlockValidator.java#L443-L455). Light body validation delegates to the configured gas validator ([ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/MainnetBlockBodyValidator.java#L118-L130](https://github.com/besu-eth/besu/blob/aa06c4f8dfc461e483d46c6a1ac72b5bfef8d945/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/MainnetBlockBodyValidator.java#L118-L130)). A successful import-for-syncing then appends the block ([ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/MainnetBlockImporter.java#L88-L104](https://github.com/besu-eth/besu/blob/aa06c4f8dfc461e483d46c6a1ac72b5bfef8d945/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/MainnetBlockImporter.java#L88-L104)).

**3. Diverging condition, words only.** A custom caller uses the public syncing/import API with LIGHT body validation on an otherwise consistent empty Amsterdam block, no transactions or receipts, but header gas used equal to one. System calls do not contribute block gas, so expected gas used is zero. With header validation disabled as permitted by this API, and matching empty roots, LIGHT body validation accepts the gas field. This is a statement about the optional API's validation coverage; choosing header validation NONE does not establish an untrusted network import exploit.

**4. Geth comparator.** Full processed-state validation always compares gas:
```go
if block.GasUsed() != res.GasUsed {
    return fmt.Errorf("invalid gas used (remote: %d local: %d)", block.GasUsed(), res.GasUsed)
}
```
[core/block_validator.go#L148-L155](https://github.com/ethereum/go-ethereum/blob/8817f99f92852f8ac53e596de6202dd9e3494065/core/block_validator.go#L148-L155). This agrees with EELS. I did not identify an analogous Geth LIGHT import API and do not claim that this compares equivalent syncing modes.

**5. Confidence and attempted disproof.** **High for the skipped optional check; low practical security impact.** Normal Besu block execution supplies the computed gas to body validation ([ethereum/core/src/main/java/org/hyperledger/besu/ethereum/MainnetBlockValidator.java#L287-L300](https://github.com/besu-eth/besu/blob/aa06c4f8dfc461e483d46c6a1ac72b5bfef8d945/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/MainnetBlockValidator.java#L287-L300)), so the same Amsterdam gas validator checks equality there. In-tree call-site review found Era1 import using `BodyValidationMode.NONE`, not LIGHT ([app/src/main/java/org/hyperledger/besu/chainimport/Era1BlockImporter.java#L156-L163](https://github.com/besu-eth/besu/blob/aa06c4f8dfc461e483d46c6a1ac72b5bfef8d945/app/src/main/java/org/hyperledger/besu/chainimport/Era1BlockImporter.java#L156-L163)). This disproves the broad claim that normal full nodes accept this block. The source's skip is deliberate and documented; it is not evidence of an accidental arithmetic failure. Restrict the finding to a plugin/custom importer treating LIGHT validation as checking this field.

**6. Severity.** **Invalid block accepted**, only by this partially validating API configuration. No full-node consensus split or network exploit established; low practical severity.

**Known-check:** **known**, [Besu issue #11655](https://github.com/besu-eth/besu/issues/11655), **open**. It describes the exact missing-value branch, empty-block example, intentional-skip comment, and restricted reachability. The Hive header failures below do not demonstrate this API gap; they take the engine/full-processing path and reject the blocks.

## Rules inspected and found consistent in the normal Amsterdam path

All Besu citations in this table are at the Besu pin above. Spec citations are at the EELS pin unless an EIP page is named. “Consistent” is limited to source inspection. The negative-net-state case is deliberately excluded and discussed separately.

| Rule / edge case | Spec source | Besu evidence and result |
|---|---|---|
| CPSB 1530; new account 120 bytes, storage 64, authorization base 23; costs 183600/97920/35190 | [gas.py#L47-L59](https://github.com/ethereum/execution-specs/blob/7f2f4c9bf6d73b09ecb8b24eb14d08bf0cf0247b/src/ethereum/forks/amsterdam/vm/gas.py#L47-L59) | [Eip8037StateGasCostCalculator.java#L23-L92](https://github.com/besu-eth/besu/blob/aa06c4f8dfc461e483d46c6a1ac72b5bfef8d945/evm/src/main/java/org/hyperledger/besu/evm/gascalculator/Eip8037StateGasCostCalculator.java#L23-L92); constants and multiplication agree. |
| Total transaction gas at most 2^32−1; execution allocation capped at 2^24 including intrinsic | [gas.py#L1105-L1161](https://github.com/ethereum/execution-specs/blob/7f2f4c9bf6d73b09ecb8b24eb14d08bf0cf0247b/src/ethereum/forks/amsterdam/vm/gas.py#L1105-L1161) | [AmsterdamTargetingGasLimitCalculator.java#L33-L56](https://github.com/besu-eth/besu/blob/aa06c4f8dfc461e483d46c6a1ac72b5bfef8d945/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/AmsterdamTargetingGasLimitCalculator.java#L33-L56); [MainnetTransactionValidator.java#L112-L121](https://github.com/besu-eth/besu/blob/aa06c4f8dfc461e483d46c6a1ac72b5bfef8d945/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/MainnetTransactionValidator.java#L112-L121); [MainnetTransactionProcessor.java#L354-L371](https://github.com/besu-eth/besu/blob/aa06c4f8dfc461e483d46c6a1ac72b5bfef8d945/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/MainnetTransactionProcessor.java#L354-L371). Excess belongs to reservoir, not executable gas. |
| Intrinsic/floor admission must fit both total transaction budget and executable cap | [transactions.py#L588-L688](https://github.com/ethereum/execution-specs/blob/7f2f4c9bf6d73b09ecb8b24eb14d08bf0cf0247b/src/ethereum/forks/amsterdam/transactions.py#L588-L688) | [MainnetTransactionValidator.java#L255-L280](https://github.com/besu-eth/besu/blob/aa06c4f8dfc461e483d46c6a1ac72b5bfef8d945/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/MainnetTransactionValidator.java#L255-L280). Uses the intrinsic/floor maximum and cap. |
| System limit 31,566,720: 30,000,000 executable plus 1,566,720 reservoir; no ordinary tx execution cap or block-gas contribution | [8037 system contracts](https://eips.ethereum.org/EIPS/eip-8037#system-contracts-and-system-transactions); [fork.py#L724-L781](https://github.com/ethereum/execution-specs/blob/7f2f4c9bf6d73b09ecb8b24eb14d08bf0cf0247b/src/ethereum/forks/amsterdam/fork.py#L724-L781) | [SystemCallProcessor.java#L50-L57](https://github.com/besu-eth/besu/blob/aa06c4f8dfc461e483d46c6a1ac72b5bfef8d945/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/systemcall/SystemCallProcessor.java#L50-L57); [SystemCallProcessor.java#L213-L253](https://github.com/besu-eth/besu/blob/aa06c4f8dfc461e483d46c6a1ac72b5bfef8d945/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/systemcall/SystemCallProcessor.java#L213-L253). 97920 × 16 placed in reservoir. |
| Cold account 3000; storage 2100; account-write 9000; storage-write 10000; CREATE_ACCESS 12000; prepaid address/key 2900/2000 | [8038 parameters](https://eips.ethereum.org/EIPS/eip-8038#parameters); [gas.py#L75-L90](https://github.com/ethereum/execution-specs/blob/7f2f4c9bf6d73b09ecb8b24eb14d08bf0cf0247b/src/ethereum/forks/amsterdam/vm/gas.py#L75-L90) | [AmsterdamGasCalculator.java#L65-L105](https://github.com/besu-eth/besu/blob/aa06c4f8dfc461e483d46c6a1ac72b5bfef8d945/evm/src/main/java/org/hyperledger/besu/evm/gascalculator/AmsterdamGasCalculator.java#L65-L105). Normal-node calculator agrees, unlike Candidate 1. |
| SSTORE first-change write surcharge, dirty rewrite/no-op access only | [storage.py#L68-L162](https://github.com/ethereum/execution-specs/blob/7f2f4c9bf6d73b09ecb8b24eb14d08bf0cf0247b/src/ethereum/forks/amsterdam/vm/instructions/storage.py#L68-L162) | [AmsterdamGasCalculator.java#L365-L376](https://github.com/besu-eth/besu/blob/aa06c4f8dfc461e483d46c6a1ac72b5bfef8d945/evm/src/main/java/org/hyperledger/besu/evm/gascalculator/AmsterdamGasCalculator.java#L365-L376). Tests current=original and new≠current; cold surcharge is at operation site. |
| SSTORE 0→x charge, 0→x→0 state refill, nonzero-original slots never allocate a new state leaf | [storage.py#L68-L162](https://github.com/ethereum/execution-specs/blob/7f2f4c9bf6d73b09ecb8b24eb14d08bf0cf0247b/src/ethereum/forks/amsterdam/vm/instructions/storage.py#L68-L162) | [StorageTransition.java#L53-L64](https://github.com/besu-eth/besu/blob/aa06c4f8dfc461e483d46c6a1ac72b5bfef8d945/evm/src/main/java/org/hyperledger/besu/evm/gascalculator/StorageTransition.java#L53-L64); [SStoreOperation.java#L110-L158](https://github.com/besu-eth/besu/blob/aa06c4f8dfc461e483d46c6a1ac72b5bfef8d945/evm/src/main/java/org/hyperledger/besu/evm/operation/SStoreOperation.java#L110-L158). State transitions are separate from refund-counter adjustments. |
| SSTORE sentry only executable gas, cold/warm charge before mutation; alternate V2 path inspected | [storage.py#L68-L162](https://github.com/ethereum/execution-specs/blob/7f2f4c9bf6d73b09ecb8b24eb14d08bf0cf0247b/src/ethereum/forks/amsterdam/vm/instructions/storage.py#L68-L162) | [SStoreOperation.java#L88-L103](https://github.com/besu-eth/besu/blob/aa06c4f8dfc461e483d46c6a1ac72b5bfef8d945/evm/src/main/java/org/hyperledger/besu/evm/operation/SStoreOperation.java#L88-L103); [SStoreOperationV2.java#L77-L137](https://github.com/besu-eth/besu/blob/aa06c4f8dfc461e483d46c6a1ac72b5bfef8d945/evm/src/main/java/org/hyperledger/besu/evm/v2/operation/SStoreOperationV2.java#L77-L137). Both handle state-gas charging/refill. |
| Clear refund 11616, reverse clear refund on re-set; refund 10000 when restoring original; no-op gets none | [8038 SSTORE pricing](https://eips.ethereum.org/EIPS/eip-8038#sstore-pricing) | [AmsterdamGasCalculator.java#L438-L466](https://github.com/besu-eth/besu/blob/aa06c4f8dfc461e483d46c6a1ac72b5bfef8d945/evm/src/main/java/org/hyperledger/besu/evm/gascalculator/AmsterdamGasCalculator.java#L438-L466); [AmsterdamGasCalculator.java#L91-L95](https://github.com/besu-eth/besu/blob/aa06c4f8dfc461e483d46c6a1ac72b5bfef8d945/evm/src/main/java/org/hyperledger/besu/evm/gascalculator/AmsterdamGasCalculator.java#L91-L95). Covers x→0→x, x→y→x and 0→x→0 separately. |
| State charge consumes reservoir first; insufficient spill fails atomically | [gas.py#L413-L457](https://github.com/ethereum/execution-specs/blob/7f2f4c9bf6d73b09ecb8b24eb14d08bf0cf0247b/src/ethereum/forks/amsterdam/vm/gas.py#L413-L457) | [MessageFrame.java#L1143-L1165](https://github.com/besu-eth/besu/blob/aa06c4f8dfc461e483d46c6a1ac72b5bfef8d945/evm/src/main/java/org/hyperledger/besu/evm/frame/MessageFrame.java#L1143-L1165). Checks affordability before changing gas. |
| State refill pays prior executable spill into gas_left first, then credits reservoir | [gas.py#L594-L648](https://github.com/ethereum/execution-specs/blob/7f2f4c9bf6d73b09ecb8b24eb14d08bf0cf0247b/src/ethereum/forks/amsterdam/vm/gas.py#L594-L648) | [MessageFrame.java#L1195-L1225](https://github.com/besu-eth/besu/blob/aa06c4f8dfc461e483d46c6a1ac72b5bfef8d945/evm/src/main/java/org/hyperledger/besu/evm/frame/MessageFrame.java#L1195-L1225). A 0→x→0 refill is not merely a refund-counter credit. |
| Child success merges gas and repays outstanding spill; failure restores state gas to entry; REVERT preserves remaining execution whereas exceptional halt burns it | [gas.py#L459-L556](https://github.com/ethereum/execution-specs/blob/7f2f4c9bf6d73b09ecb8b24eb14d08bf0cf0247b/src/ethereum/forks/amsterdam/vm/gas.py#L459-L556); [gas.py#L713-L735](https://github.com/ethereum/execution-specs/blob/7f2f4c9bf6d73b09ecb8b24eb14d08bf0cf0247b/src/ethereum/forks/amsterdam/vm/gas.py#L713-L735) | [AbstractMessageProcessor.java#L145-L182](https://github.com/besu-eth/besu/blob/aa06c4f8dfc461e483d46c6a1ac72b5bfef8d945/evm/src/main/java/org/hyperledger/besu/evm/processor/AbstractMessageProcessor.java#L145-L182); [AbstractCallOperation.java#L349-L359](https://github.com/besu-eth/besu/blob/aa06c4f8dfc461e483d46c6a1ac72b5bfef8d945/evm/src/main/java/org/hyperledger/besu/evm/operation/AbstractCallOperation.java#L349-L359); [MessageFrame.java#L1217-L1225](https://github.com/besu-eth/besu/blob/aa06c4f8dfc461e483d46c6a1ac72b5bfef8d945/evm/src/main/java/org/hyperledger/besu/evm/frame/MessageFrame.java#L1217-L1225). |
| Shared transaction state-gas counters restore on rollback, rather than double-counting child snapshots | [gas.py#L520-L592](https://github.com/ethereum/execution-specs/blob/7f2f4c9bf6d73b09ecb8b24eb14d08bf0cf0247b/src/ethereum/forks/amsterdam/vm/gas.py#L520-L592) | [TxValues.java#L60-L62](https://github.com/besu-eth/besu/blob/aa06c4f8dfc461e483d46c6a1ac72b5bfef8d945/evm/src/main/java/org/hyperledger/besu/evm/frame/TxValues.java#L60-L62); [TxValues.java#L144-L162](https://github.com/besu-eth/besu/blob/aa06c4f8dfc461e483d46c6a1ac72b5bfef8d945/evm/src/main/java/org/hyperledger/besu/evm/frame/TxValues.java#L144-L162). Undo-aware shared counters. |
| CALL account-creation charge requires nonzero value and non-alive recipient; charge before forwarding; soft failures refill | [system.py#L370-L590](https://github.com/ethereum/execution-specs/blob/7f2f4c9bf6d73b09ecb8b24eb14d08bf0cf0247b/src/ethereum/forks/amsterdam/vm/instructions/system.py#L370-L590) | [AbstractCallOperation.java#L239-L246](https://github.com/besu-eth/besu/blob/aa06c4f8dfc461e483d46c6a1ac72b5bfef8d945/evm/src/main/java/org/hyperledger/besu/evm/operation/AbstractCallOperation.java#L239-L246); [AbstractCallOperation.java#L271-L284](https://github.com/besu-eth/besu/blob/aa06c4f8dfc461e483d46c6a1ac72b5bfef8d945/evm/src/main/java/org/hyperledger/besu/evm/operation/AbstractCallOperation.java#L271-L284); [AbstractCallOperation.java#L371-L387](https://github.com/besu-eth/besu/blob/aa06c4f8dfc461e483d46c6a1ac72b5bfef8d945/evm/src/main/java/org/hyperledger/besu/evm/operation/AbstractCallOperation.java#L371-L387). |
| CREATE/CREATE2 new-account state charge conditional on target liveness; preflight failure does not consume it | [system.py#L59-L186](https://github.com/ethereum/execution-specs/blob/7f2f4c9bf6d73b09ecb8b24eb14d08bf0cf0247b/src/ethereum/forks/amsterdam/vm/instructions/system.py#L59-L186) | [AbstractCreateOperation.java#L106-L145](https://github.com/besu-eth/besu/blob/aa06c4f8dfc461e483d46c6a1ac72b5bfef8d945/evm/src/main/java/org/hyperledger/besu/evm/operation/AbstractCreateOperation.java#L106-L145); [AbstractCreateOperation.java#L266-L282](https://github.com/besu-eth/besu/blob/aa06c4f8dfc461e483d46c6a1ac72b5bfef8d945/evm/src/main/java/org/hyperledger/besu/evm/operation/AbstractCreateOperation.java#L266-L282). Failed child refills only an actual charge. |
| EIP-150 63/64 uses gas_left only, not the reservoir | [gas.py#L666-L687](https://github.com/ethereum/execution-specs/blob/7f2f4c9bf6d73b09ecb8b24eb14d08bf0cf0247b/src/ethereum/forks/amsterdam/vm/gas.py#L666-L687); [gas.py#L801-L862](https://github.com/ethereum/execution-specs/blob/7f2f4c9bf6d73b09ecb8b24eb14d08bf0cf0247b/src/ethereum/forks/amsterdam/vm/gas.py#L801-L862) | [AbstractCreateOperation.java#L217-L219](https://github.com/besu-eth/besu/blob/aa06c4f8dfc461e483d46c6a1ac72b5bfef8d945/evm/src/main/java/org/hyperledger/besu/evm/operation/AbstractCreateOperation.java#L217-L219); [AbstractCallOperation.java#L239-L246](https://github.com/besu-eth/besu/blob/aa06c4f8dfc461e483d46c6a1ac72b5bfef8d945/evm/src/main/java/org/hyperledger/besu/evm/operation/AbstractCallOperation.java#L239-L246). State charge precedes child executable-gas grant; [TangerineWhistleGasCalculator.java#L109-L126](https://github.com/besu-eth/besu/blob/aa06c4f8dfc461e483d46c6a1ac72b5bfef8d945/evm/src/main/java/org/hyperledger/besu/evm/gascalculator/TangerineWhistleGasCalculator.java#L109-L126) caps only frame.getRemainingGas(). |
| Code deposit: size/prefix checks then execution hashing cost and state-byte charge | [interpreter.py#L324-L393](https://github.com/ethereum/execution-specs/blob/7f2f4c9bf6d73b09ecb8b24eb14d08bf0cf0247b/src/ethereum/forks/amsterdam/vm/interpreter.py#L324-L393) | [ContractCreationProcessor.java#L176-L229](https://github.com/besu-eth/besu/blob/aa06c4f8dfc461e483d46c6a1ac72b5bfef8d945/evm/src/main/java/org/hyperledger/besu/evm/processor/ContractCreationProcessor.java#L176-L229); [Eip8037StateGasCostCalculator.java#L65-L92](https://github.com/besu-eth/besu/blob/aa06c4f8dfc461e483d46c6a1ac72b5bfef8d945/evm/src/main/java/org/hyperledger/besu/evm/gascalculator/Eip8037StateGasCostCalculator.java#L65-L92). Hash cost 6 per rounded-up 32-byte word; state charge per deposited byte. |
| Top-level creation state charge only for non-alive destination; value transfer new-account condition also applied | [interpreter.py#L119-L131](https://github.com/ethereum/execution-specs/blob/7f2f4c9bf6d73b09ecb8b24eb14d08bf0cf0247b/src/ethereum/forks/amsterdam/vm/interpreter.py#L119-L131); [interpreter.py#L235-L322](https://github.com/ethereum/execution-specs/blob/7f2f4c9bf6d73b09ecb8b24eb14d08bf0cf0247b/src/ethereum/forks/amsterdam/vm/interpreter.py#L235-L322) | [MainnetTransactionProcessor.java#L413-L415](https://github.com/besu-eth/besu/blob/aa06c4f8dfc461e483d46c6a1ac72b5bfef8d945/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/MainnetTransactionProcessor.java#L413-L415); [MainnetTransactionProcessor.java#L858-L866](https://github.com/besu-eth/besu/blob/aa06c4f8dfc461e483d46c6a1ac72b5bfef8d945/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/MainnetTransactionProcessor.java#L858-L866); [MainnetTransactionProcessor.java#L943-L954](https://github.com/besu-eth/besu/blob/aa06c4f8dfc461e483d46c6a1ac72b5bfef8d945/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/MainnetTransactionProcessor.java#L943-L954). |
| 7702 per-auth execution 7816; account-write/auth-base bookkeeping distinct from per-authority first-write tracking | [eoa_delegation.py#L155-L189](https://github.com/ethereum/execution-specs/blob/7f2f4c9bf6d73b09ecb8b24eb14d08bf0cf0247b/src/ethereum/forks/amsterdam/vm/eoa_delegation.py#L155-L189); [eoa_delegation.py#L231-L322](https://github.com/ethereum/execution-specs/blob/7f2f4c9bf6d73b09ecb8b24eb14d08bf0cf0247b/src/ethereum/forks/amsterdam/vm/eoa_delegation.py#L231-L322) | [AmsterdamGasCalculator.java#L133-L134](https://github.com/besu-eth/besu/blob/aa06c4f8dfc461e483d46c6a1ac72b5bfef8d945/evm/src/main/java/org/hyperledger/besu/evm/gascalculator/AmsterdamGasCalculator.java#L133-L134); [CodeDelegationProcessor.java#L77-L86](https://github.com/besu-eth/besu/blob/aa06c4f8dfc461e483d46c6a1ac72b5bfef8d945/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/CodeDelegationProcessor.java#L77-L86); [CodeDelegationProcessor.java#L133-L165](https://github.com/besu-eth/besu/blob/aa06c4f8dfc461e483d46c6a1ac72b5bfef8d945/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/CodeDelegationProcessor.java#L133-L165); [MainnetTransactionProcessor.java#L918-L929](https://github.com/besu-eth/besu/blob/aa06c4f8dfc461e483d46c6a1ac72b5bfef8d945/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/MainnetTransactionProcessor.java#L918-L929). Old delegation refund disabled. |
| Authorization preparation rollback versus committed authorizations when dispatch fails | [interpreter.py#L235-L322](https://github.com/ethereum/execution-specs/blob/7f2f4c9bf6d73b09ecb8b24eb14d08bf0cf0247b/src/ethereum/forks/amsterdam/vm/interpreter.py#L235-L322); [eoa_delegation.py#L231-L322](https://github.com/ethereum/execution-specs/blob/7f2f4c9bf6d73b09ecb8b24eb14d08bf0cf0247b/src/ethereum/forks/amsterdam/vm/eoa_delegation.py#L231-L322) | [MainnetTransactionProcessor.java#L308-L348](https://github.com/besu-eth/besu/blob/aa06c4f8dfc461e483d46c6a1ac72b5bfef8d945/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/MainnetTransactionProcessor.java#L308-L348); [MainnetTransactionProcessor.java#L454-L467](https://github.com/besu-eth/besu/blob/aa06c4f8dfc461e483d46c6a1ac72b5bfef8d945/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/MainnetTransactionProcessor.java#L454-L467); [MainnetTransactionProcessor.java#L501-L530](https://github.com/besu-eth/besu/blob/aa06c4f8dfc461e483d46c6a1ac72b5bfef8d945/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/MainnetTransactionProcessor.java#L501-L530). Preparation and execution failure handled separately. |
| Block execution dimension settled before ordinary refund; floor applies execution alone; receipt scalar after refund/floor | [gas.py#L1211-L1227](https://github.com/ethereum/execution-specs/blob/7f2f4c9bf6d73b09ecb8b24eb14d08bf0cf0247b/src/ethereum/forks/amsterdam/vm/gas.py#L1211-L1227); [8037 integration with 7778](https://eips.ethereum.org/EIPS/eip-8037#integration-with-eip-7778) | [TransactionGasAccounting.java#L91-L106](https://github.com/besu-eth/besu/blob/aa06c4f8dfc461e483d46c6a1ac72b5bfef8d945/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/TransactionGasAccounting.java#L91-L106); [AmsterdamGasCalculator.java#L418-L434](https://github.com/besu-eth/besu/blob/aa06c4f8dfc461e483d46c6a1ac72b5bfef8d945/evm/src/main/java/org/hyperledger/besu/evm/gascalculator/AmsterdamGasCalculator.java#L418-L434). Correct separate block/paid values; auxiliary reuse is Candidate 2. |
| Refund cap uses total consumed (execution + state), remaining reservoir returned to sender | [gas.py#L1211-L1214](https://github.com/ethereum/execution-specs/blob/7f2f4c9bf6d73b09ecb8b24eb14d08bf0cf0247b/src/ethereum/forks/amsterdam/vm/gas.py#L1211-L1214) | [AmsterdamGasCalculator.java#L418-L434](https://github.com/besu-eth/besu/blob/aa06c4f8dfc461e483d46c6a1ac72b5bfef8d945/evm/src/main/java/org/hyperledger/besu/evm/gascalculator/AmsterdamGasCalculator.java#L418-L434). Sum pools before applying capped refund and calldata floor. |
| 2D inclusion checks min(2^24, tx.gas) against remaining execution and tx.gas against remaining state capacity | [gas.py#L1038-L1103](https://github.com/ethereum/execution-specs/blob/7f2f4c9bf6d73b09ecb8b24eb14d08bf0cf0247b/src/ethereum/forks/amsterdam/vm/gas.py#L1038-L1103) | [BlockGasAccountingStrategy.java#L95-L125](https://github.com/besu-eth/besu/blob/aa06c4f8dfc461e483d46c6a1ac72b5bfef8d945/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/BlockGasAccountingStrategy.java#L95-L125). Independent capacity checks, not their sum. |
| Header gas_used max of cumulative execution and cumulative state; full processing enforces equality | [fork.py#L335-L340](https://github.com/ethereum/execution-specs/blob/7f2f4c9bf6d73b09ecb8b24eb14d08bf0cf0247b/src/ethereum/forks/amsterdam/fork.py#L335-L340) | [AbstractBlockProcessor.java#L302-L320](https://github.com/besu-eth/besu/blob/aa06c4f8dfc461e483d46c6a1ac72b5bfef8d945/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/AbstractBlockProcessor.java#L302-L320); [AbstractBlockProcessor.java#L506-L507](https://github.com/besu-eth/besu/blob/aa06c4f8dfc461e483d46c6a1ac72b5bfef8d945/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/AbstractBlockProcessor.java#L506-L507); [BlockGasUsedValidator.java#L67-L72](https://github.com/besu-eth/besu/blob/aa06c4f8dfc461e483d46c6a1ac72b5bfef8d945/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/BlockGasUsedValidator.java#L67-L72). Exception limited to absent processed value in Candidate 3. |
| Receipt cumulative gas uses paid scalar, not 2D header meter | [8037 receipt semantics](https://eips.ethereum.org/EIPS/eip-8037#receipt-semantics); [fork.py#L628-L663](https://github.com/ethereum/execution-specs/blob/7f2f4c9bf6d73b09ecb8b24eb14d08bf0cf0247b/src/ethereum/forks/amsterdam/fork.py#L628-L663) | [BlockGasAccountingStrategy.java#L140-L142](https://github.com/besu-eth/besu/blob/aa06c4f8dfc461e483d46c6a1ac72b5bfef8d945/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/BlockGasAccountingStrategy.java#L140-L142); [AbstractBlockProcessor.java#L302-L320](https://github.com/besu-eth/besu/blob/aa06c4f8dfc461e483d46c6a1ac72b5bfef8d945/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/AbstractBlockProcessor.java#L302-L320). Header/receipt divergence is intentional. |
| First Amsterdam base fee follows normal parent-header formula; no Amsterdam reset to initial base fee | [fork.py#L361-L421](https://github.com/ethereum/execution-specs/blob/7f2f4c9bf6d73b09ecb8b24eb14d08bf0cf0247b/src/ethereum/forks/amsterdam/fork.py#L361-L421); [fork.py#L424-L460](https://github.com/ethereum/execution-specs/blob/7f2f4c9bf6d73b09ecb8b24eb14d08bf0cf0247b/src/ethereum/forks/amsterdam/fork.py#L424-L460) | [LondonFeeMarket.java#L87-L111](https://github.com/besu-eth/besu/blob/aa06c4f8dfc461e483d46c6a1ac72b5bfef8d945/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/feemarket/LondonFeeMarket.java#L87-L111); [BaseFeeMarketBlockHeaderGasPriceValidationRule.java#L39-L63](https://github.com/besu-eth/besu/blob/aa06c4f8dfc461e483d46c6a1ac72b5bfef8d945/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/headervalidationrules/BaseFeeMarketBlockHeaderGasPriceValidationRule.java#L39-L63). Initial special case is London, not Amsterdam. |
| One Amsterdam protocol selects the related calculator/accounting together, not independent partially enabled 8037/7778/8038 rules | [__init__.py#L7-L20](https://github.com/ethereum/execution-specs/blob/7f2f4c9bf6d73b09ecb8b24eb14d08bf0cf0247b/src/ethereum/forks/amsterdam/__init__.py#L7-L20) | [MainnetProtocolSpecs.java#L1118-L1123](https://github.com/besu-eth/besu/blob/aa06c4f8dfc461e483d46c6a1ac72b5bfef8d945/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/MainnetProtocolSpecs.java#L1118-L1123); [MainnetProtocolSpecs.java#L1184-L1190](https://github.com/besu-eth/besu/blob/aa06c4f8dfc461e483d46c6a1ac72b5bfef8d945/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/MainnetProtocolSpecs.java#L1184-L1190). Convenience overload remains the explicit exception. |

| SELFDESTRUCT beneficiary new-account charge only when balance transfer creates a non-alive account; executable charge first; no state refund merely for deletion | [EELS system.py#L705-L778](https://github.com/ethereum/execution-specs/blob/7f2f4c9bf6d73b09ecb8b24eb14d08bf0cf0247b/src/ethereum/forks/amsterdam/vm/instructions/system.py#L705-L778) | [SelfDestructOperation.java#L92-L157](https://github.com/besu-eth/besu/blob/aa06c4f8dfc461e483d46c6a1ac72b5bfef8d945/evm/src/main/java/org/hyperledger/besu/evm/operation/SelfDestructOperation.java#L92-L157). State charge is conditional and the later refund bookkeeping is a balance transfer record, not a state-gas refill. |

## Strongest apparent differences that did not become findings

**Negative net state gas: unresolved reachability, not a confirmed candidate.** EELS explicitly clamps at settlement:
```python
settled_state_gas_used = StateGas(Uint(max(0, state_gas_used)))
```
[gas.py#L1211-L1227](https://github.com/ethereum/execution-specs/blob/7f2f4c9bf6d73b09ecb8b24eb14d08bf0cf0247b/src/ethereum/forks/amsterdam/vm/gas.py#L1211-L1227).
Besu instead takes `final long stateGas = stateGasUsed();` without a clamp in [TransactionGasAccounting.java#L91-L106](https://github.com/besu-eth/besu/blob/aa06c4f8dfc461e483d46c6a1ac72b5bfef8d945/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/TransactionGasAccounting.java#L91-L106).
Geth rejects a negative topmost frame:
```go
if st.gasRemaining.UsedStateGas < 0 {
    return 0, 0, fmt.Errorf("negative topmost frame state gas usage, %d", st.gasRemaining.UsedStateGas)
}
```
[state_transition.go#L1046-L1049](https://github.com/ethereum/go-ethereum/blob/8817f99f92852f8ac53e596de6202dd9e3494065/core/state_transition.go#L1046-L1049).

These are different defensive policies, but I found **no valid transaction/state condition producing a negative global settled state-gas total**. I tried the set/reset round trip across frames, reverted child writes, and successful child spill repayment. A frame-local negative adjustment can reverse an ancestor's charge; it does not prove the whole transaction has net negative creation. Besu's shared undo-aware counters and refill ordering described above defeat the simple examples. Do not promote the missing clamp to a consensus bug without a reachable transaction. Geth's rejection is not evidence Besu agrees with EELS; it is an additional comparator difference. Nethermind was not audited in this bounded item, so the brief's statement about its rejection was not independently established here. Search `repo:besu-eth/besu "negative state"` returned no matches; absence is not a proof of novelty.

**Pre/post-refund apparent conflict: disproved.** EIP-8037's standalone block formula uses after-refund gas, but its explicit “Integration with EIP-7778” subsection overrides it with:
```python
tx_execution_gas = max(tx_gas_used_before_refund - tx_state_gas, calldata_floor_gas_cost)
```
[EIP-8037#integration-with-eip-7778](https://eips.ethereum.org/EIPS/eip-8037#integration-with-eip-7778);
[immutable EIP#L270-L282](https://github.com/ethereum/EIPs/blob/d4c575521d99ec881a444ab3af604e684b5f0743/EIPS/eip-8037.md#L270-L282).
Besu uses that pre-refund formula. Reporting its difference from the standalone formula as a bug would ignore the requested combined fork.

**Previously fixed spill/CALLCODE concerns: not outstanding at the reviewed pin.** [Besu PR #11243](https://github.com/besu-eth/besu/pull/11243) is closed/merged and covers spill repayment. [PR #11107](https://github.com/besu-eth/besu/pull/11107) is closed/merged and fixes CALLCODE refund targeting, with [#11298](https://github.com/besu-eth/besu/pull/11298) a closed/merged backport. Current frame and call code were inspected rather than treating old reports as current bugs.

## Known-check method and public result reconciliation

GitHub issue search used **no open-only restriction**, so both open and closed issues and PRs were included. Search result counts are observations at review, not stable promises; an issue whose numeric ID equals an EIP can be irrelevant. The broad queries, with all pages for results above 100, were:

| Query (GitHub search API q) | Results observed |
|---|---:|
| `repo:besu-eth/besu 8037` | 67 |
| `repo:besu-eth/besu 7778` | 17 |
| `repo:besu-eth/besu 8038` | 15 |
| `repo:besu-eth/besu "state gas"` | 113 |
| `repo:besu-eth/besu "state creation"` | 28 |
| `repo:besu-eth/besu "block gas accounting"` | 21 |
| `repo:besu-eth/besu "state access"` | 105 |
| `repo:ethereum/execution-specs "Test Release Tracker"` | 36 |

Queries can be repeated through [GitHub issues search API](https://api.github.com/search/issues) with those exact q values, or [Besu issues/PR search](https://github.com/besu-eth/besu/issues?q=8037). Candidate-specific known matches and states are given in each candidate. They supersede any inference of novelty from missing Hive coverage.

Additional closed/merged relevant Besu work inspected: [#10930](https://github.com/besu-eth/besu/pull/10930) (creation liveness/SSTORE order/floor), [#11414](https://github.com/besu-eth/besu/pull/11414) (total transaction cap), [#11140](https://github.com/besu-eth/besu/pull/11140) and [#10764](https://github.com/besu-eth/besu/pull/10764) (8038 repricing), [#10907](https://github.com/besu-eth/besu/pull/10907) (2D accounting), [#11579](https://github.com/besu-eth/besu/pull/11579) (simulation execution cap). Their existence does not prove all edge cases correct.

**Execution-spec-tests releases.** [Tracker #3217](https://github.com/ethereum/execution-specs/issues/3217), **open**, tracks tests@v21.0.0/Glamsterdam Testnet, with final execute/consume sweeps and latest-spec-reference work still unchecked when read. Its coverage links include spill repayment, transaction total caps, system calls, failed creation to an existing account, authorization rollback, repricing, and receipt cumulative gas. [Tracker #3518](https://github.com/ethereum/execution-specs/issues/3518), **closed**, covers devnet v8.1.4 and the spill-repayment specification change without repricing. No tracker entry was found specifically establishing the three limited-path candidates as EEST consensus failures. Only these relevant full tracker bodies are relied on; search titles alone are not test execution evidence.

**Hive index read:** [glamsterdam/listing.jsonl](https://hive.ethpandaops.io/glamsterdam/listing.jsonl), 999 indexed records at review. Latest indexed Besu suites:

| Public suite/result | Besu version suffix | Outcome |
|---|---|---|
| [consume-enginex result](https://hive.ethpandaops.io/glamsterdam/results/1793018005-fa5bfa67da513c8de132d620958d92dc.json), 2026-10-26 | fc46028 | 83,258 total; 83,189 pass; 69 fail |
| [consume-engine result](https://hive.ethpandaops.io/glamsterdam/results/1793007262-bcaea78021015fd4b0776e606b920c4d.json), ended 2026-10-26 | bdb9e5c | 44,225 total; 44,216 pass; 9 fail |
| execute, 2026-10-26, as indexed | fc46028 | 173 pass, 0 fail |
| consume-rlp, ended 2026-10-26, as indexed | bdb9e5c | 44,161 pass, 0 fail |

**These versions are not the Besu head reviewed here.** I did not rerun the suites. The nine/69 failures are not nine/69 new state-gas bugs.

Three scoped malformed-header variants appear in each engine-family failing suite: `test_reject_incorrect_two_dimensional_header` with `header_rule_receipts`, `header_rule_transaction_maxima`, and `header_rule_combined`, from `tests/amsterdam/eip8037_state_creation_gas_cost_increase/test_block_2d_gas_accounting.py`. The enginex result contains 1,253 tests whose names match 8037/8038/7778, with three failures. This is a name-based subset, not a claim of exhaustive rule coverage.

I read the relevant result-detail log ranges. They say:
> Client returned unexpected validation error: got:  
> "[BlockException.INVALID_LOG_BLOOM | BlockException.INVALID_RECEIPTS_ROOT] failed to validate output of imported block"  
> expected: "BlockException.INVALID_GAS_USED"

Sources: [consume-engine detail log](https://hive.ethpandaops.io/glamsterdam/results/details/1792898816-210b17669146e957359b4c1c109700c8779a45cac10780ac068061cd33156e58-0.log), bytes 20004613–20009420; [consume-enginex detail log](https://hive.ethpandaops.io/glamsterdam/results/details/1793007988-3b982933be7d840b168a7a0fb24dbf65fc34b1be8fdb318ffe73be9ce39f9264-0.log), bytes 42904347–42908444. HTTP Range reads were used; no commands contained in the logs were executed.

This **disproves acceptance of those malformed headers in these public runs**: the engine returned INVALID and the harness objected to the error classification. The evidence supports a known cosmetic/diagnostic classification mismatch, not Candidate 3's LIGHT-path acceptance. Unrelated failures were not expanded into findings outside this item.

## Source inventory and limits

All linked immutable code excerpts and normative pages above were read as public source. The principal raw-source families are:

- `https://raw.githubusercontent.com/besu-eth/besu/aa06c4f8dfc461e483d46c6a1ac72b5bfef8d945/` plus each exact Besu file path cited above.
- `https://raw.githubusercontent.com/ethereum/execution-specs/7f2f4c9bf6d73b09ecb8b24eb14d08bf0cf0247b/src/ethereum/forks/amsterdam/` plus `vm/gas.py`, `vm/instructions/storage.py`, `vm/instructions/system.py`, `vm/interpreter.py`, `vm/eoa_delegation.py`, `transactions.py`, `fork.py`, and `__init__.py`.
- `https://raw.githubusercontent.com/ethereum/go-ethereum/8817f99f92852f8ac53e596de6202dd9e3494065/` plus the comparator paths cited in each candidate.
- The EIP canonical pages, immutable EIP files, Gloas feature list, test reference files, issue/PR APIs, release trackers, Hive index, result JSON, and two detail-log ranges linked above.

Known status is a public-search result as of this review, not an assurance that all discussions or unpublished tests were found. I found no public result proving a new consensus split at the pinned Besu head. The strongest surviving difference is a known factory misconfiguration outside normal node processing; the scalar RPC finding lacks an explicit field mandate in the three EIPs; the LIGHT finding concerns an intentionally partial API. Those qualifications are part of the findings, not omitted exploit prerequisites.

