diff --git a/build/checksums.txt b/build/checksums.txt index b153b6c108..2eaede7e1c 100644 --- a/build/checksums.txt +++ b/build/checksums.txt @@ -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/ diff --git a/build/ci.go b/build/ci.go index d6e3af1ac0..6f9c200e80 100644 --- a/build/ci.go +++ b/build/ci.go @@ -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) diff --git a/core/vm/evm.go b/core/vm/evm.go index 9330d72aa5..3bc8335040 100644 --- a/core/vm/evm.go +++ b/core/vm/evm.go @@ -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 diff --git a/core/vm/gascosts.go b/core/vm/gascosts.go index 7dc384f3b7..bba5211fb0 100644 --- a/core/vm/gascosts.go +++ b/core/vm/gascosts.go @@ -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} }