From d23c5e5e62eed5a46e4304df16fa1cf387b952f7 Mon Sep 17 00:00:00 2001 From: Marius van der Wijden Date: Thu, 26 Sep 2024 13:07:15 +0200 Subject: [PATCH] core: special case on creation for eof code --- core/state_transition.go | 12 +++++++++--- core/vm/errors.go | 1 + core/vm/evm.go | 2 +- core/vm/instructions.go | 2 +- core/vm/runtime/runtime.go | 1 + 5 files changed, 13 insertions(+), 5 deletions(-) diff --git a/core/state_transition.go b/core/state_transition.go index d285d03fe2..cd2c65ebd5 100644 --- a/core/state_transition.go +++ b/core/state_transition.go @@ -17,6 +17,7 @@ package core import ( + "errors" "fmt" "math" "math/big" @@ -444,10 +445,15 @@ func (st *StateTransition) TransitionDb() (*ExecutionResult, error) { vmerr error // vm errors do not effect consensus and are therefore not assigned to err ) if contractCreation { - ret, _, st.gasRemaining, vmerr = st.evm.Create(sender, msg.Data, st.gasRemaining, value) + ret, _, st.gasRemaining, vmerr = st.evm.Create(sender, msg.Data, st.gasRemaining, value, rules.IsPrague) + // Special case for EOF, if the initcode or deployed code is + // invalid, the tx is considered valid (so update nonce), but + // gas for initcode execution is not consumed. + // Only intrinsic creation transaction costs are charged. + if errors.Is(vmerr, vm.ErrInvalidEOFInitcode) { + st.state.SetNonce(msg.From, st.state.GetNonce(sender.Address())+1) + } } else { - // Increment the nonce for the next transaction - st.state.SetNonce(msg.From, st.state.GetNonce(sender.Address())+1) ret, st.gasRemaining, vmerr = st.evm.Call(sender, st.to(), msg.Data, st.gasRemaining, value) } diff --git a/core/vm/errors.go b/core/vm/errors.go index 839bf56a1a..0cfdcd7d74 100644 --- a/core/vm/errors.go +++ b/core/vm/errors.go @@ -37,6 +37,7 @@ var ( ErrReturnDataOutOfBounds = errors.New("return data out of bounds") ErrGasUintOverflow = errors.New("gas uint64 overflow") ErrInvalidCode = errors.New("invalid code: must not begin with 0xef") + ErrInvalidEOFInitcode = errors.New("invalid eof initcode") ErrNonceUintOverflow = errors.New("nonce uint64 overflow") // errStopToken is an internal token indicating interpreter loop termination, diff --git a/core/vm/evm.go b/core/vm/evm.go index c717f55826..009bb6aaf3 100644 --- a/core/vm/evm.go +++ b/core/vm/evm.go @@ -564,7 +564,7 @@ func (evm *EVM) initNewContract(contract *Contract, address common.Address, valu } // Create creates a new contract using code as deployment code. -func (evm *EVM) Create(caller ContractRef, code []byte, gas uint64, value *uint256.Int) (ret []byte, contractAddr common.Address, leftOverGas uint64, err error) { +func (evm *EVM) Create(caller ContractRef, code []byte, gas uint64, value *uint256.Int, allowEOF bool) (ret []byte, contractAddr common.Address, leftOverGas uint64, err error) { contractAddr = crypto.CreateAddress(caller.Address(), evm.StateDB.GetNonce(caller.Address())) return evm.create(caller, &codeAndHash{code: code}, gas, value, contractAddr, CREATE) } diff --git a/core/vm/instructions.go b/core/vm/instructions.go index 35d6393fba..2196a689f0 100644 --- a/core/vm/instructions.go +++ b/core/vm/instructions.go @@ -682,7 +682,7 @@ func opCreate(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]b scope.Contract.UseGas(gas, interpreter.evm.Config.Tracer, tracing.GasChangeCallContractCreation) - res, addr, returnGas, suberr := interpreter.evm.Create(scope.Contract, input, gas, &value) + res, addr, returnGas, suberr := interpreter.evm.Create(scope.Contract, input, gas, &value, false) // Push item on the stack based on the returned error. If the ruleset is // homestead we must check for CodeStoreOutOfGasError (homestead only // rule) and treat as an error, if the ruleset is frontier we must diff --git a/core/vm/runtime/runtime.go b/core/vm/runtime/runtime.go index f83ed682cd..84e21ef358 100644 --- a/core/vm/runtime/runtime.go +++ b/core/vm/runtime/runtime.go @@ -184,6 +184,7 @@ func Create(input []byte, cfg *Config) ([]byte, common.Address, uint64, error) { input, cfg.GasLimit, uint256.MustFromBig(cfg.Value), + rules.IsPrague, ) return code, address, leftOverGas, err }