diff --git a/core/vm/contract.go b/core/vm/contract.go index beb4c3ff52..0901d07f6e 100644 --- a/core/vm/contract.go +++ b/core/vm/contract.go @@ -141,7 +141,7 @@ func (c *Contract) UseGas(gas GasCosts, logger *tracing.Hooks, reason tracing.Ga // RefundGas refunds gas to the contract. gasUsed carries the child frame's // accumulated gas usage metrics (EIP-8037), incorporated on both success and error. -func (c *Contract) RefundGas(err error, gas GasCosts, gasUsed GasUsed, logger *tracing.Hooks, reason tracing.GasChangeReason) { +func (c *Contract) RefundGas(err error, initialRegularGasUsed uint64, gas GasCosts, gasUsed GasUsed, logger *tracing.Hooks, reason tracing.GasChangeReason) { // If the preceding call errored, return the state gas // to the parent call if err != nil { @@ -157,7 +157,7 @@ func (c *Contract) RefundGas(err error, gas GasCosts, gasUsed GasUsed, logger *t c.Gas.RegularGas += gas.RegularGas c.Gas.StateGas = gas.StateGas c.GasUsed.StateGasCharged += gasUsed.StateGasCharged - c.GasUsed.RegularGasUsed += gasUsed.RegularGasUsed + c.GasUsed.RegularGasUsed = initialRegularGasUsed + gasUsed.RegularGasUsed } // Address returns the contracts address diff --git a/core/vm/instructions.go b/core/vm/instructions.go index 0ab2d0609a..c0f9ad12cb 100644 --- a/core/vm/instructions.go +++ b/core/vm/instructions.go @@ -673,8 +673,8 @@ func opCreate(pc *uint64, evm *EVM, scope *ScopeContext) ([]byte, error) { // reuse size int for stackvalue stackvalue := size + regularGasUsed := scope.Contract.GasUsed.RegularGasUsed scope.Contract.UseGas(GasCosts{RegularGas: gas.RegularGas}, evm.Config.Tracer, tracing.GasChangeCallContractCreation) - scope.Contract.GasUsed.RegularGasUsed -= gas.RegularGas // escrow: undo parent's RGU for forwarded gas res, addr, returnGas, childGasUsed, suberr := evm.Create(scope.Contract.Address(), input, GasCosts{RegularGas: gas.RegularGas, StateGas: scope.Contract.Gas.StateGas}, &value) // Push item on the stack based on the returned error. If the ruleset is @@ -690,7 +690,7 @@ func opCreate(pc *uint64, evm *EVM, scope *ScopeContext) ([]byte, error) { } scope.Stack.push(&stackvalue) - scope.Contract.RefundGas(suberr, returnGas, childGasUsed, evm.Config.Tracer, tracing.GasChangeCallLeftOverRefunded) + scope.Contract.RefundGas(suberr, regularGasUsed, returnGas, childGasUsed, evm.Config.Tracer, tracing.GasChangeCallLeftOverRefunded) if suberr == ErrExecutionReverted { evm.returnData = res // set REVERT data to return data buffer @@ -724,8 +724,9 @@ func opCreate2(pc *uint64, evm *EVM, scope *ScopeContext) ([]byte, error) { } } + regularGasUsed := scope.Contract.GasUsed.RegularGasUsed scope.Contract.UseGas(GasCosts{RegularGas: gas.RegularGas}, evm.Config.Tracer, tracing.GasChangeCallContractCreation2) - scope.Contract.GasUsed.RegularGasUsed -= gas.RegularGas // escrow: undo parent's RGU for forwarded gas + // reuse size int for stackvalue stackvalue := size res, addr, returnGas, childGasUsed, suberr := evm.Create2(scope.Contract.Address(), input, GasCosts{RegularGas: gas.RegularGas, StateGas: scope.Contract.Gas.StateGas}, @@ -738,7 +739,7 @@ func opCreate2(pc *uint64, evm *EVM, scope *ScopeContext) ([]byte, error) { } scope.Stack.push(&stackvalue) - scope.Contract.RefundGas(suberr, returnGas, childGasUsed, evm.Config.Tracer, tracing.GasChangeCallLeftOverRefunded) + scope.Contract.RefundGas(suberr, regularGasUsed, returnGas, childGasUsed, evm.Config.Tracer, tracing.GasChangeCallLeftOverRefunded) if suberr == ErrExecutionReverted { evm.returnData = res // set REVERT data to return data buffer @@ -766,7 +767,7 @@ func opCall(pc *uint64, evm *EVM, scope *ScopeContext) ([]byte, error) { if !value.IsZero() { gas += params.CallStipend } - scope.Contract.GasUsed.RegularGasUsed -= gas // escrow: undo parent's RGU for forwarded gas + regularGasUsed := scope.Contract.GasUsed.RegularGasUsed ret, returnGas, childGasUsed, err := evm.Call(scope.Contract.Address(), toAddr, args, GasCosts{RegularGas: gas, StateGas: scope.Contract.Gas.StateGas}, &value) if err != nil { @@ -779,7 +780,7 @@ func opCall(pc *uint64, evm *EVM, scope *ScopeContext) ([]byte, error) { scope.Memory.Set(retOffset.Uint64(), retSize.Uint64(), ret) } - scope.Contract.RefundGas(err, returnGas, childGasUsed, evm.Config.Tracer, tracing.GasChangeCallLeftOverRefunded) + scope.Contract.RefundGas(err, regularGasUsed, returnGas, childGasUsed, evm.Config.Tracer, tracing.GasChangeCallLeftOverRefunded) evm.returnData = ret return ret, nil @@ -801,7 +802,7 @@ func opCallCode(pc *uint64, evm *EVM, scope *ScopeContext) ([]byte, error) { gas += params.CallStipend } - scope.Contract.GasUsed.RegularGasUsed -= gas // escrow + regularGasUsed := scope.Contract.GasUsed.RegularGasUsed ret, returnGas, childGasUsed, err := evm.CallCode(scope.Contract.Address(), toAddr, args, GasCosts{RegularGas: gas, StateGas: scope.Contract.Gas.StateGas}, &value) if err != nil { temp.Clear() @@ -813,7 +814,7 @@ func opCallCode(pc *uint64, evm *EVM, scope *ScopeContext) ([]byte, error) { scope.Memory.Set(retOffset.Uint64(), retSize.Uint64(), ret) } - scope.Contract.RefundGas(err, returnGas, childGasUsed, evm.Config.Tracer, tracing.GasChangeCallLeftOverRefunded) + scope.Contract.RefundGas(err, regularGasUsed, returnGas, childGasUsed, evm.Config.Tracer, tracing.GasChangeCallLeftOverRefunded) evm.returnData = ret return ret, nil @@ -831,7 +832,7 @@ func opDelegateCall(pc *uint64, evm *EVM, scope *ScopeContext) ([]byte, error) { // Get arguments from the memory. args := scope.Memory.GetPtr(inOffset.Uint64(), inSize.Uint64()) - scope.Contract.GasUsed.RegularGasUsed -= gas // escrow + regularGasUsed := scope.Contract.GasUsed.RegularGasUsed ret, returnGas, childGasUsed, err := evm.DelegateCall(scope.Contract.Caller(), scope.Contract.Address(), toAddr, args, GasCosts{RegularGas: gas, StateGas: scope.Contract.Gas.StateGas}, scope.Contract.value) if err != nil { temp.Clear() @@ -843,7 +844,7 @@ func opDelegateCall(pc *uint64, evm *EVM, scope *ScopeContext) ([]byte, error) { scope.Memory.Set(retOffset.Uint64(), retSize.Uint64(), ret) } - scope.Contract.RefundGas(err, returnGas, childGasUsed, evm.Config.Tracer, tracing.GasChangeCallLeftOverRefunded) + scope.Contract.RefundGas(err, regularGasUsed, returnGas, childGasUsed, evm.Config.Tracer, tracing.GasChangeCallLeftOverRefunded) evm.returnData = ret return ret, nil @@ -861,7 +862,7 @@ func opStaticCall(pc *uint64, evm *EVM, scope *ScopeContext) ([]byte, error) { // Get arguments from the memory. args := scope.Memory.GetPtr(inOffset.Uint64(), inSize.Uint64()) - scope.Contract.GasUsed.RegularGasUsed -= gas // escrow + regularGasUsed := scope.Contract.GasUsed.RegularGasUsed ret, returnGas, childGasUsed, err := evm.StaticCall(scope.Contract.Address(), toAddr, args, GasCosts{RegularGas: gas, StateGas: scope.Contract.Gas.StateGas}) if err != nil { temp.Clear() @@ -873,7 +874,7 @@ func opStaticCall(pc *uint64, evm *EVM, scope *ScopeContext) ([]byte, error) { scope.Memory.Set(retOffset.Uint64(), retSize.Uint64(), ret) } - scope.Contract.RefundGas(err, returnGas, childGasUsed, evm.Config.Tracer, tracing.GasChangeCallLeftOverRefunded) + scope.Contract.RefundGas(err, regularGasUsed, returnGas, childGasUsed, evm.Config.Tracer, tracing.GasChangeCallLeftOverRefunded) evm.returnData = ret return ret, nil