From 514bde14da1b3a233a7e2ee91dc999f3da802684 Mon Sep 17 00:00:00 2001 From: qu0b Date: Wed, 4 Feb 2026 11:22:20 +0000 Subject: [PATCH] core: fix EIP-7778 block gas accounting to exclude refunds The miner accumulates result.UsedGas (post-refund) into the block header's GasUsed via ApplyTransactionWithEVM, but the validator accumulates receipt.GasUsed (which is result.MaxUsedGas = pre-refund for Amsterdam) into its local gas total. This causes every proposed block containing refund-generating transactions to be rejected with "invalid gas used" after the Gloas fork. Use result.MaxUsedGas (pre-refund gas) for block gas accumulation when Amsterdam is active, matching EIP-7778's requirement that block gas accounting excludes refunds. Co-Authored-By: Claude Opus 4.5 --- core/state_processor.go | 8 +++++++- internal/ethapi/simulate.go | 7 ++++++- 2 files changed, 13 insertions(+), 2 deletions(-) diff --git a/core/state_processor.go b/core/state_processor.go index 510d5fa1ab..7c396d5498 100644 --- a/core/state_processor.go +++ b/core/state_processor.go @@ -189,7 +189,13 @@ func ApplyTransactionWithEVM(msg *Message, gp *GasPool, statedb *state.StateDB, } else { root = statedb.IntermediateRoot(evm.ChainConfig().IsEIP158(blockNumber)).Bytes() } - *usedGas += result.UsedGas + // EIP-7778: block gas accounting excludes refunds. Use MaxUsedGas + // (pre-refund gas) for Amsterdam, preserving post-refund for earlier forks. + if evm.ChainConfig().IsAmsterdam(blockNumber, blockTime) { + *usedGas += result.MaxUsedGas + } else { + *usedGas += result.UsedGas + } // Merge the tx-local access event into the "block-local" one, in order to collect // all values, so that the witness can be built. diff --git a/internal/ethapi/simulate.go b/internal/ethapi/simulate.go index deaaafadb0..c64b2508a2 100644 --- a/internal/ethapi/simulate.go +++ b/internal/ethapi/simulate.go @@ -300,7 +300,12 @@ func (sim *simulator) processBlock(ctx context.Context, block *simBlock, header, } else { root = sim.state.IntermediateRoot(sim.chainConfig.IsEIP158(blockContext.BlockNumber)).Bytes() } - gasUsed += result.UsedGas + // EIP-7778: block gas accounting excludes refunds. + if sim.chainConfig.IsAmsterdam(blockContext.BlockNumber, blockContext.Time) { + gasUsed += result.MaxUsedGas + } else { + gasUsed += result.UsedGas + } receipts[i] = core.MakeReceipt(evm, result, sim.state, blockContext.BlockNumber, common.Hash{}, blockContext.Time, tx, gasUsed, root) blobGasUsed += receipts[i].BlobGasUsed logs := tracer.Logs()