core: new tests, behavior on exceptional halt

This commit is contained in:
MariusVanDerWijden 2026-04-30 18:43:30 +02:00
parent 6c1c599804
commit fc0e03c667
4 changed files with 55 additions and 12 deletions

View file

@ -5,10 +5,10 @@
# https://github.com/ethereum/execution-spec-tests/releases/download/v5.1.0
a3192784375acec7eaec492799d5c5d0c47a2909a3cc40178898e4ecd20cc416 fixtures_develop.tar.gz
# version:spec-tests-bal v6.0.0
# version:spec-tests-bal v1.0.0
# https://github.com/ethereum/execution-spec-tests/releases
# https://github.com/ethereum/execution-spec-tests/releases/download/bal%40v6.0.0
683fe9a741480ca3a3b1eb98b6caaa72d461dede490358688f7194686edc2196 fixtures_bal.tar.gz
# https://github.com/ethereum/execution-spec-tests/releases/download/snobal-devnet-6%40v1.0.0
f7f29bd7a3dd90215dfe6b403f7deda1d1bac540c64f2c476e0f7fb35c9e3fa7 fixtures_snobal-devnet-6.tar.gz
# version:golang 1.25.9
# https://go.dev/dl/

View file

@ -455,7 +455,7 @@ func downloadSpecTestFixtures(csdb *download.ChecksumDB, cachedir string) string
func downloadBALSpecTestFixtures(csdb *download.ChecksumDB, cachedir string) string {
ext := ".tar.gz"
base := "fixtures_bal"
base := "fixtures_snobal-devnet-6"
archivePath := filepath.Join(cachedir, base+ext)
if err := csdb.DownloadFileFromKnownURL(archivePath); err != nil {
log.Fatal(err)

View file

@ -246,6 +246,7 @@ func (evm *EVM) Call(caller common.Address, addr common.Address, input []byte, g
evm.captureEnd(evm.depth, startGas, leftOverGas, ret, err)
}(gas)
}
initialStateGas := gas.StateGas
// Fail if we're trying to execute above the call depth limit
if evm.depth > int(params.CallCreateDepth) {
return nil, gas, GasUsed{}, ErrDepth
@ -322,8 +323,12 @@ func (evm *EVM) Call(caller common.Address, addr common.Address, input []byte, g
if evm.Config.Tracer != nil && evm.Config.Tracer.OnGasChange != nil {
evm.Config.Tracer.OnGasChange(gas.RegularGas, 0, tracing.GasChangeCallFailedExecution)
}
gasUsed.RegularGas += gas.RegularGas
gas.Exhaust()
if evm.chainRules.IsAmsterdam {
gas.HaltReset(&gasUsed, initialStateGas)
} else {
gasUsed.RegularGas += gas.RegularGas
gas.Exhaust()
}
}
}
return ret, gas, gasUsed, err
@ -344,6 +349,7 @@ func (evm *EVM) CallCode(caller common.Address, addr common.Address, input []byt
evm.captureEnd(evm.depth, startGas, leftOverGas, ret, err)
}(gas)
}
initialStateGas := gas.StateGas
// Fail if we're trying to execute above the call depth limit
if evm.depth > int(params.CallCreateDepth) {
return nil, gas, GasUsed{}, ErrDepth
@ -379,8 +385,12 @@ func (evm *EVM) CallCode(caller common.Address, addr common.Address, input []byt
if evm.Config.Tracer != nil && evm.Config.Tracer.OnGasChange != nil {
evm.Config.Tracer.OnGasChange(gas.RegularGas, 0, tracing.GasChangeCallFailedExecution)
}
gasUsed.RegularGas += gas.RegularGas
gas.Exhaust()
if evm.chainRules.IsAmsterdam {
gas.HaltReset(&gasUsed, initialStateGas)
} else {
gasUsed.RegularGas += gas.RegularGas
gas.Exhaust()
}
}
}
return ret, gas, gasUsed, err
@ -400,6 +410,7 @@ func (evm *EVM) DelegateCall(originCaller common.Address, caller common.Address,
evm.captureEnd(evm.depth, startGas, leftOverGas, ret, err)
}(gas)
}
initialStateGas := gas.StateGas
// Fail if we're trying to execute above the call depth limit
if evm.depth > int(params.CallCreateDepth) {
return nil, gas, GasUsed{}, ErrDepth
@ -429,8 +440,12 @@ func (evm *EVM) DelegateCall(originCaller common.Address, caller common.Address,
if evm.Config.Tracer != nil && evm.Config.Tracer.OnGasChange != nil {
evm.Config.Tracer.OnGasChange(gas.RegularGas, 0, tracing.GasChangeCallFailedExecution)
}
gasUsed.RegularGas += gas.RegularGas
gas.Exhaust()
if evm.chainRules.IsAmsterdam {
gas.HaltReset(&gasUsed, initialStateGas)
} else {
gasUsed.RegularGas += gas.RegularGas
gas.Exhaust()
}
}
}
return ret, gas, gasUsed, err
@ -448,6 +463,7 @@ func (evm *EVM) StaticCall(caller common.Address, addr common.Address, input []b
evm.captureEnd(evm.depth, startGas, leftOverGas, ret, err)
}(gas)
}
initialStateGas := gas.StateGas
// Fail if we're trying to execute above the call depth limit
if evm.depth > int(params.CallCreateDepth) {
return nil, gas, GasUsed{}, ErrDepth
@ -478,8 +494,12 @@ func (evm *EVM) StaticCall(caller common.Address, addr common.Address, input []b
if evm.Config.Tracer != nil && evm.Config.Tracer.OnGasChange != nil {
evm.Config.Tracer.OnGasChange(gas.RegularGas, 0, tracing.GasChangeCallFailedExecution)
}
gasUsed.RegularGas += gas.RegularGas
gas.Exhaust()
if evm.chainRules.IsAmsterdam {
gas.HaltReset(&gasUsed, initialStateGas)
} else {
gasUsed.RegularGas += gas.RegularGas
gas.Exhaust()
}
}
}
return ret, gas, gasUsed, err
@ -487,6 +507,7 @@ func (evm *EVM) StaticCall(caller common.Address, addr common.Address, input []b
// create creates a new contract using code as deployment code.
func (evm *EVM) create(caller common.Address, code []byte, gas GasBudget, value *uint256.Int, address common.Address, typ OpCode) (ret []byte, createAddress common.Address, leftOverGas GasBudget, used GasUsed, err error) {
initialStateGas := gas.StateGas
// Depth check execution. Fail if we're trying to execute above the
// limit.
var nonce uint64
@ -596,6 +617,9 @@ func (evm *EVM) create(caller common.Address, code []byte, gas GasBudget, value
evm.StateDB.RevertToSnapshot(snapshot)
if err != ErrExecutionReverted {
contract.UseGas(GasCosts{RegularGas: contract.Gas.RegularGas}, evm.Config.Tracer, tracing.GasChangeCallFailedExecution)
if evm.chainRules.IsAmsterdam {
contract.Gas.HaltReset(&contract.GasUsed, initialStateGas)
}
}
}
return ret, address, contract.Gas, contract.GasUsed, err

View file

@ -80,6 +80,25 @@ func (g *GasBudget) Exhaust() {
g.RegularGas = 0
}
// HaltReset resets the frame to (0, initialStateGas) on exceptional halt:
// regular gas is burned and the reservoir is restored to its value at frame
// entry. Any state gas above R0 — either spill that drained the reservoir, or
// state refunded above R0 by a child revert — is re-classified as regular and
// added to gasUsed.RegularGas. gasUsed.StateGas is cleared so the parent's
// reservoir is left unchanged when this frame's leftover propagates upward.
func (g *GasBudget) HaltReset(gasUsed *GasUsed, initialStateGas uint64) {
gasUsed.RegularGas += g.RegularGas
if gasUsed.StateGas > int64(initialStateGas) {
gasUsed.RegularGas += uint64(gasUsed.StateGas) - initialStateGas
}
if g.StateGas > initialStateGas {
gasUsed.RegularGas += g.StateGas - initialStateGas
}
g.RegularGas = 0
g.StateGas = initialStateGas
gasUsed.StateGas = 0
}
func (g *GasBudget) Copy() GasBudget {
return GasBudget{RegularGas: g.RegularGas, StateGas: g.StateGas}
}