diff --git a/core/state_processor_test.go b/core/state_processor_test.go index 045102329ab1..01d91c88081b 100644 --- a/core/state_processor_test.go +++ b/core/state_processor_test.go @@ -498,8 +498,8 @@ func TestProcessVerkle(t *testing.T) { txCost1 := params.TxGas txCost2 := params.TxGas - contractCreationCost := intrinsicContractCreationGas + uint64(5600+700+700+700 /* creation with value */ +2739 /* execution costs */) - codeWithExtCodeCopyGas := intrinsicCodeWithExtCodeCopyGas + uint64(5600+700 /* creation */ +198644 /* execution costs */) + contractCreationCost := intrinsicContractCreationGas + uint64(5600+700+700+700 /* creation with value */ +1439 /* execution costs */) + codeWithExtCodeCopyGas := intrinsicCodeWithExtCodeCopyGas + uint64(5600+700 /* creation */ +56344 /* execution costs */) blockGasUsagesExpected := []uint64{ txCost1*2 + txCost2, txCost1*2 + txCost2 + contractCreationCost + codeWithExtCodeCopyGas, diff --git a/core/vm/evm.go b/core/vm/evm.go index 06849043873c..2bfc2e233264 100644 --- a/core/vm/evm.go +++ b/core/vm/evm.go @@ -504,20 +504,26 @@ func (evm *EVM) create(caller ContractRef, codeAndHash *codeAndHash, gas uint64, // be stored due to not enough gas set an error and let it be handled // by the error checking condition below. if err == nil { - createDataGas := uint64(len(ret)) * params.CreateDataGas - if contract.UseGas(createDataGas) { - evm.StateDB.SetCode(address, ret) + if !evm.chainRules.IsEIP4762 { + createDataGas := uint64(len(ret)) * params.CreateDataGas + if contract.UseGas(createDataGas) { + } else { + err = ErrCodeStoreOutOfGas + } } else { - err = ErrCodeStoreOutOfGas + // Contract creation completed, touch the missing field in the contract + if len(ret) > 0 { + if !contract.UseGas(evm.Accesses.TouchCodeChunkRangeAndChargeGas(address.Bytes(), 0, uint64(len(ret)), uint64(len(ret)), true)) { + err = ErrOutOfGas + } + } + if err == nil && !contract.UseGas(evm.Accesses.TouchFullAccount(address.Bytes()[:], true)) { + err = ErrOutOfGas + } } - } - if err == nil && evm.chainRules.IsEIP4762 { - if len(ret) > 0 { - evm.Accesses.TouchCodeChunksRangeOnReadAndChargeGas(address.Bytes(), 0, uint64(len(ret)), uint64(len(ret))) - } - if !contract.UseGas(evm.Accesses.TouchFullAccount(address.Bytes()[:], true)) { - err = ErrOutOfGas + if err == nil { + evm.StateDB.SetCode(address, ret) } } diff --git a/core/vm/instructions.go b/core/vm/instructions.go index bf12978a6836..a0ae280df437 100644 --- a/core/vm/instructions.go +++ b/core/vm/instructions.go @@ -371,7 +371,7 @@ func opCodeCopy(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([ contractAddr := scope.Contract.Address() paddedCodeCopy, copyOffset, nonPaddedCopyLength := getDataAndAdjustedBounds(scope.Contract.Code, uint64CodeOffset, length.Uint64()) if interpreter.evm.chainRules.IsEIP4762 && !scope.Contract.IsDeployment { - statelessGas := interpreter.evm.Accesses.TouchCodeChunksRangeOnReadAndChargeGas(contractAddr[:], copyOffset, nonPaddedCopyLength, uint64(len(scope.Contract.Code))) + statelessGas := interpreter.evm.Accesses.TouchCodeChunkRangeAndChargeGas(contractAddr[:], copyOffset, nonPaddedCopyLength, uint64(len(scope.Contract.Code)), false) if !scope.Contract.UseGas(statelessGas) { scope.Contract.Gas = 0 return nil, ErrOutOfGas @@ -401,7 +401,7 @@ func opExtCodeCopy(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) self: AccountRef(addr), } paddedCodeCopy, copyOffset, nonPaddedCopyLength := getDataAndAdjustedBounds(code, uint64CodeOffset, length.Uint64()) - statelessGas := interpreter.evm.Accesses.TouchCodeChunksRangeOnReadAndChargeGas(addr[:], copyOffset, nonPaddedCopyLength, uint64(len(contract.Code))) + statelessGas := interpreter.evm.Accesses.TouchCodeChunkRangeAndChargeGas(addr[:], copyOffset, nonPaddedCopyLength, uint64(len(contract.Code)), false) statelessGas += interpreter.evm.Accesses.TouchVersion(addr[:], false) statelessGas += interpreter.evm.Accesses.TouchCodeSize(addr[:], false) if !scope.Contract.UseGas(statelessGas) { @@ -954,7 +954,7 @@ func opPush1(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]by // touch next chunk if PUSH1 is at the boundary. if so, *pc has // advanced past this boundary. contractAddr := scope.Contract.Address() - statelessGas := interpreter.evm.Accesses.TouchCodeChunksRangeOnReadAndChargeGas(contractAddr[:], *pc+1, uint64(1), uint64(len(scope.Contract.Code))) + statelessGas := interpreter.evm.Accesses.TouchCodeChunkRangeAndChargeGas(contractAddr[:], *pc+1, uint64(1), uint64(len(scope.Contract.Code)), false) if !scope.Contract.UseGas(statelessGas) { scope.Contract.Gas = 0 return nil, ErrOutOfGas @@ -983,7 +983,7 @@ func makePush(size uint64, pushByteSize int) executionFunc { if !scope.Contract.IsDeployment && interpreter.evm.chainRules.IsPrague { contractAddr := scope.Contract.Address() - statelessGas := interpreter.evm.Accesses.TouchCodeChunksRangeOnReadAndChargeGas(contractAddr[:], uint64(startMin), uint64(pushByteSize), uint64(len(scope.Contract.Code))) + statelessGas := interpreter.evm.Accesses.TouchCodeChunkRangeAndChargeGas(contractAddr[:], uint64(startMin), uint64(pushByteSize), uint64(len(scope.Contract.Code)), false) if !scope.Contract.UseGas(statelessGas) { scope.Contract.Gas = 0 return nil, ErrOutOfGas diff --git a/core/vm/interpreter.go b/core/vm/interpreter.go index 93750de2ca3a..eb52a2080e69 100644 --- a/core/vm/interpreter.go +++ b/core/vm/interpreter.go @@ -183,7 +183,7 @@ func (in *EVMInterpreter) Run(contract *Contract, input []byte, readOnly bool) ( // if the PC ends up in a new "chunk" of verkleized code, charge the // associated costs. contractAddr := contract.Address() - contract.Gas -= in.evm.TxContext.Accesses.TouchCodeChunksRangeOnReadAndChargeGas(contractAddr[:], pc, 1, uint64(len(contract.Code))) + contract.Gas -= in.evm.TxContext.Accesses.TouchCodeChunkRangeAndChargeGas(contractAddr[:], pc, 1, uint64(len(contract.Code)), false) } // Get the operation from the jump table and validate the stack to ensure there are