From e93ddc03b7c1f698fcae6e189bd7e67a683a27a2 Mon Sep 17 00:00:00 2001 From: Marius van der Wijden Date: Tue, 10 Mar 2026 14:36:52 +0100 Subject: [PATCH] core: fix floor calculation --- core/state_transition.go | 6 +++++- core/vm/evm.go | 24 ++++++++++++++++-------- 2 files changed, 21 insertions(+), 9 deletions(-) diff --git a/core/state_transition.go b/core/state_transition.go index e1f942424e..4b2cd7989f 100644 --- a/core/state_transition.go +++ b/core/state_transition.go @@ -582,7 +582,11 @@ func (st *stateTransition) execute() (*ExecutionResult, error) { // After EIP-7623: Data-heavy transactions pay the floor gas. if st.gasUsed() < floorDataGas { prev := st.gasRemaining.RegularGas - st.gasRemaining.RegularGas = st.initialGas.RegularGas - floorDataGas + // When the calldata floor exceeds actual gas used, any + // remaining state gas must also be consumed + targetRemaining := (st.initialGas.RegularGas + st.initialGas.StateGas) - floorDataGas + st.gasRemaining.StateGas = 0 + st.gasRemaining.RegularGas = targetRemaining if t := st.evm.Config.Tracer; t != nil && t.OnGasChange != nil { t.OnGasChange(prev, st.gasRemaining.RegularGas, tracing.GasChangeTxDataFloor) } diff --git a/core/vm/evm.go b/core/vm/evm.go index 10ef39ce92..049ea40f54 100644 --- a/core/vm/evm.go +++ b/core/vm/evm.go @@ -622,16 +622,24 @@ func (evm *EVM) initNewContract(contract *Contract, address common.Address) ([]b // Charge code storage gas. if !evm.chainRules.IsEIP4762 { - createDataGas := GasCosts{RegularGas: uint64(len(ret)) * params.CreateDataGas} if evm.chainRules.IsAmsterdam { - words := (uint64(len(ret)) + 31) / 32 - createDataGas = GasCosts{ - RegularGas: words * params.Keccak256WordGas, - StateGas: uint64(len(ret)) * evm.Context.CostPerGasByte, + // EIP-8037: spec charges state gas first (charge_state_gas), then + // regular gas (charge_gas). If state gas succeeds but regular gas + // fails, state_gas_used is still recorded. + stateGas := GasCosts{StateGas: uint64(len(ret)) * evm.Context.CostPerGasByte} + if !contract.UseGas(stateGas, evm.Config.Tracer, tracing.GasChangeCallCodeStorage) { + return ret, ErrCodeStoreOutOfGas + } + words := (uint64(len(ret)) + 31) / 32 + regularGas := GasCosts{RegularGas: words * params.Keccak256WordGas} + if !contract.UseGas(regularGas, evm.Config.Tracer, tracing.GasChangeCallCodeStorage) { + return ret, ErrCodeStoreOutOfGas + } + } else { + createDataGas := GasCosts{RegularGas: uint64(len(ret)) * params.CreateDataGas} + if !contract.UseGas(createDataGas, evm.Config.Tracer, tracing.GasChangeCallCodeStorage) { + return ret, ErrCodeStoreOutOfGas } - } - if !contract.UseGas(createDataGas, evm.Config.Tracer, tracing.GasChangeCallCodeStorage) { - return ret, ErrCodeStoreOutOfGas } } else { consumed, wanted := evm.AccessEvents.CodeChunksRangeGas(address, 0, uint64(len(ret)), uint64(len(ret)), true, contract.Gas.RegularGas)