core: fixed issues from devnet

This commit is contained in:
Marius van der Wijden 2026-03-05 17:46:14 +01:00
parent d27b174680
commit 964a117ea7
3 changed files with 48 additions and 17 deletions

View file

@ -781,7 +781,10 @@ func (st *stateTransition) blockGasUsed(intrinsicGas, execGasStart vm.GasCosts)
totalExecUsed := (execGasStart.RegularGas + execGasStart.StateGas) -
(st.gasRemaining.RegularGas + st.gasRemaining.StateGas)
execStateUsed := st.gasRemaining.TotalStateGasCharged
execRegularUsed := totalExecUsed - execStateUsed
// Exclude state gas that was charged from regular gas but then reverted.
// This gas was consumed from the regular pool but was for state operations
// that didn't persist, so it shouldn't count in the regular dimension.
execRegularUsed := totalExecUsed - execStateUsed - st.gasRemaining.RevertedStateGasSpill
txRegular := intrinsicGas.RegularGas + execRegularUsed
txState := intrinsicGas.StateGas + execStateUsed - st.stateGasRefund

View file

@ -316,7 +316,8 @@ func (evm *EVM) Call(caller common.Address, addr common.Address, input []byte, g
// when we're in homestead this also counts for code storage gas errors.
if err != nil {
evm.StateDB.RevertToSnapshot(snapshot)
if err != ErrExecutionReverted {
isRevert := err == ErrExecutionReverted
if !isRevert {
if evm.Config.Tracer != nil && evm.Config.Tracer.OnGasChange != nil {
evm.Config.Tracer.OnGasChange(gas.RegularGas, 0, tracing.GasChangeCallFailedExecution)
}
@ -325,8 +326,7 @@ func (evm *EVM) Call(caller common.Address, addr common.Address, input []byte, g
// State changes are rolled back on any error, so state gas charges
// from the reverted execution should not count toward block accounting.
// Also restore the state gas reservoir since state creation was undone.
gas.TotalStateGasCharged = savedTotalStateGas
gas.StateGas = savedStateGas
gas.RevertStateGas(savedTotalStateGas, savedStateGas, isRevert)
// TODO: consider clearing up unused snapshots:
//} else {
// evm.StateDB.DiscardSnapshot(snapshot)
@ -381,14 +381,14 @@ func (evm *EVM) CallCode(caller common.Address, addr common.Address, input []byt
}
if err != nil {
evm.StateDB.RevertToSnapshot(snapshot)
if err != ErrExecutionReverted {
isRevert := err == ErrExecutionReverted
if !isRevert {
if evm.Config.Tracer != nil && evm.Config.Tracer.OnGasChange != nil {
evm.Config.Tracer.OnGasChange(gas.RegularGas, 0, tracing.GasChangeCallFailedExecution)
}
gas.RegularGas = 0
}
gas.TotalStateGasCharged = savedTotalStateGas
gas.StateGas = savedStateGas
gas.RevertStateGas(savedTotalStateGas, savedStateGas, isRevert)
}
return ret, gas, err
}
@ -433,14 +433,14 @@ func (evm *EVM) DelegateCall(originCaller common.Address, caller common.Address,
}
if err != nil {
evm.StateDB.RevertToSnapshot(snapshot)
if err != ErrExecutionReverted {
isRevert := err == ErrExecutionReverted
if !isRevert {
if evm.Config.Tracer != nil && evm.Config.Tracer.OnGasChange != nil {
evm.Config.Tracer.OnGasChange(gas.RegularGas, 0, tracing.GasChangeCallFailedExecution)
}
gas.RegularGas = 0
}
gas.TotalStateGasCharged = savedTotalStateGas
gas.StateGas = savedStateGas
gas.RevertStateGas(savedTotalStateGas, savedStateGas, isRevert)
}
return ret, gas, err
}
@ -496,15 +496,14 @@ func (evm *EVM) StaticCall(caller common.Address, addr common.Address, input []b
}
if err != nil {
evm.StateDB.RevertToSnapshot(snapshot)
if err != ErrExecutionReverted {
isRevert := err == ErrExecutionReverted
if !isRevert {
if evm.Config.Tracer != nil && evm.Config.Tracer.OnGasChange != nil {
evm.Config.Tracer.OnGasChange(gas.RegularGas, 0, tracing.GasChangeCallFailedExecution)
}
gas.RegularGas = 0
}
gas.TotalStateGasCharged = savedTotalStateGas
gas.StateGas = savedStateGas
gas.RevertStateGas(savedTotalStateGas, savedStateGas, isRevert)
}
return ret, gas, err
}
@ -615,14 +614,14 @@ func (evm *EVM) create(caller common.Address, code []byte, gas GasCosts, value *
ret, err = evm.initNewContract(contract, address)
if err != nil && (evm.chainRules.IsHomestead || err != ErrCodeStoreOutOfGas) {
evm.StateDB.RevertToSnapshot(snapshot)
if err != ErrExecutionReverted {
isRevert := err == ErrExecutionReverted
if !isRevert {
contract.UseGas(contract.Gas, evm.Config.Tracer, tracing.GasChangeCallFailedExecution)
}
// State changes are rolled back, so state gas charges from the
// reverted execution should not count toward block accounting.
// Also restore the state gas reservoir since state creation was undone.
contract.Gas.TotalStateGasCharged = savedTotalStateGas
contract.Gas.StateGas = savedStateGas
contract.Gas.RevertStateGas(savedTotalStateGas, savedStateGas, isRevert)
}
return ret, address, contract.Gas, err
}

View file

@ -11,6 +11,13 @@ type GasCosts struct {
// This is needed for EIP-8037 block gas accounting where the state gas
// dimension counts ALL state creation charges, not just reservoir consumption.
TotalStateGasCharged uint64
// RevertedStateGasSpill tracks state gas that was charged from regular gas
// (spilled) during execution of a call that subsequently reverted. When a
// call fails, its state changes are undone, but the regular gas was already
// consumed. Block gas accounting must exclude this amount from the regular
// gas dimension since it was for state operations that didn't persist.
RevertedStateGasSpill uint64
}
func (g GasCosts) Max() uint64 {
@ -52,6 +59,28 @@ func (g *GasCosts) Add(b GasCosts) {
g.RegularGas += b.RegularGas
g.StateGas += b.StateGas
g.TotalStateGasCharged += b.TotalStateGasCharged
g.RevertedStateGasSpill += b.RevertedStateGasSpill
}
// RevertStateGas handles state gas accounting when a call reverts (EIP-8037).
// It computes how much state gas was charged from regular gas (spill) during the
// call, and either returns it for REVERT errors or tracks it for non-REVERT errors.
func (g *GasCosts) RevertStateGas(savedTotalStateGas, savedStateGas uint64, isRevert bool) {
chargedDuringCall := g.TotalStateGasCharged - savedTotalStateGas
fromReservoir := savedStateGas - g.StateGas
spilledFromRegular := chargedDuringCall - fromReservoir
if isRevert {
// REVERT: return the spilled state gas to regular gas since the caller
// keeps unused gas and state operations were undone.
g.RegularGas += spilledFromRegular
} else {
// Non-REVERT: regular gas is zeroed, but block accounting must exclude
// the spill from the regular gas dimension.
g.RevertedStateGasSpill += spilledFromRegular
}
g.TotalStateGasCharged = savedTotalStateGas
g.StateGas = savedStateGas
}
func (g GasCosts) String() string {