diff --git a/core/state/access_witness.go b/core/state/access_witness.go index 95737c789b6b..a3eb21f31ba4 100644 --- a/core/state/access_witness.go +++ b/core/state/access_witness.go @@ -111,12 +111,15 @@ func (aw *AccessWitness) TouchAndChargeMessageCall(addr []byte, availableGas uin } func (aw *AccessWitness) TouchAndChargeValueTransfer(callerAddr, targetAddr []byte, availableGas uint64) uint64 { - chargedGas1, _ := aw.touchAddressAndChargeGas(callerAddr, zeroTreeIndex, utils.BasicDataLeafKey, true, availableGas) - chargedGas2, _ := aw.touchAddressAndChargeGas(targetAddr, zeroTreeIndex, utils.BasicDataLeafKey, true, availableGas-chargedGas1) - if chargedGas1+chargedGas2 == 0 { + _, wanted1 := aw.touchAddressAndChargeGas(callerAddr, zeroTreeIndex, utils.BasicDataLeafKey, true, availableGas) + if wanted1 > availableGas { + return wanted1 + } + _, wanted2 := aw.touchAddressAndChargeGas(targetAddr, zeroTreeIndex, utils.BasicDataLeafKey, true, availableGas-wanted1) + if wanted1+wanted2 == 0 { return params.WarmStorageReadCostEIP2929 } - return chargedGas1 + chargedGas2 + return wanted1 + wanted2 } // TouchAndChargeContractCreateCheck charges access costs before diff --git a/core/vm/gas_table.go b/core/vm/gas_table.go index ac56353d2cc6..acdc5e432b6f 100644 --- a/core/vm/gas_table.go +++ b/core/vm/gas_table.go @@ -403,17 +403,6 @@ func gasCall(evm *EVM, contract *Contract, stack *Stack, mem *Memory, memorySize return 0, ErrGasUintOverflow } - if evm.chainRules.IsEIP4762 { - // If value is transferred, it is charged before 1/64th - // is subtracted from the available gas pool. - if transfersValue { - gas, overflow = math.SafeAdd(gas, evm.Accesses.TouchAndChargeValueTransfer(contract.Address().Bytes()[:], address.Bytes()[:], contract.Gas-gas)) - if overflow { - return 0, ErrGasUintOverflow - } - } - } - evm.callGasTemp, err = callGas(evm.chainRules.IsEIP150, contract.Gas, gas, stack.Back(0)) if err != nil { return 0, err diff --git a/core/vm/operations_verkle.go b/core/vm/operations_verkle.go index 6cc7d108344c..1e0fef78a5db 100644 --- a/core/vm/operations_verkle.go +++ b/core/vm/operations_verkle.go @@ -55,12 +55,24 @@ func gasExtCodeHash4762(evm *EVM, contract *Contract, stack *Stack, mem *Memory, func makeCallVariantGasEIP4762(oldCalculator gasFunc) gasFunc { return func(evm *EVM, contract *Contract, stack *Stack, mem *Memory, memorySize uint64) (uint64, error) { - target := common.Address(stack.Back(1).Bytes20()) - - _, isPrecompile := evm.precompile(target) - isSystemContract := evm.isSystemContract(target) - if isPrecompile || isSystemContract { - return params.WarmStorageReadCostEIP2929, nil + var ( + target = common.Address(stack.Back(1).Bytes20()) + transfersValue = !stack.Back(2).IsZero() + witnessGas uint64 + _, isPrecompile = evm.precompile(target) + isSystemContract = evm.isSystemContract(target) + ) + + // If value is transferred, it is charged before 1/64th + // is subtracted from the available gas pool. + if transfersValue { + wantedValueTransferWitnessGas := evm.Accesses.TouchAndChargeValueTransfer(contract.Address().Bytes()[:], target[:], contract.Gas) + if wantedValueTransferWitnessGas > contract.Gas { + return wantedValueTransferWitnessGas, nil + } + witnessGas = wantedValueTransferWitnessGas + } else if isPrecompile || isSystemContract { + witnessGas = params.WarmStorageReadCostEIP2929 } // The charging for the value transfer is done BEFORE subtracting @@ -68,16 +80,23 @@ func makeCallVariantGasEIP4762(oldCalculator gasFunc) gasFunc { // (so before we get to this point) // But the message call is part of the subcall, for which only 63/64th // of the gas should be available. - wantedWitnessGas := evm.Accesses.TouchAndChargeMessageCall(target.Bytes(), contract.Gas) - if wantedWitnessGas > contract.Gas { - return wantedWitnessGas, nil + wantedMessageCallWitnessGas := evm.Accesses.TouchAndChargeMessageCall(target.Bytes(), contract.Gas-witnessGas) + var overflow bool + if witnessGas, overflow = math.SafeAdd(witnessGas, wantedMessageCallWitnessGas); overflow { + return 0, ErrGasUintOverflow + } + if witnessGas > contract.Gas { + return witnessGas, nil } gas, err := oldCalculator(evm, contract, stack, mem, memorySize) if err != nil { return 0, err } - return wantedWitnessGas + gas, nil + if gas, overflow = math.SafeAdd(gas, witnessGas); overflow { + return 0, ErrGasUintOverflow + } + return gas, nil } }