Skip to content

Commit 43d5229

Browse files
committed
core/vm: update 7702 gas calculation on impacted OpCode
CALL, CALLCODE, STATICCALL, DELEGATECALL. EXTCODE... opcodes are aligned with the EIP update ethereum/EIPs#9248
1 parent 6f3f778 commit 43d5229

File tree

2 files changed

+77
-0
lines changed

2 files changed

+77
-0
lines changed

core/vm/eips.go

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ var activators = map[int]func(*JumpTable){
3737
1884: enable1884,
3838
1344: enable1344,
3939
1153: enable1153,
40+
7702: enable7702,
4041
}
4142

4243
// EnableEIP enables the given EIP on the config.
@@ -319,3 +320,11 @@ func enable6780(jt *JumpTable) {
319320
halts: true,
320321
}
321322
}
323+
324+
// enable7702 the EIP-7702 changes to support delegation designators.
325+
func enable7702(jt *JumpTable) {
326+
jt[CALL].dynamicGas = gasCallEIP7702
327+
jt[CALLCODE].dynamicGas = gasCallCodeEIP7702
328+
jt[STATICCALL].dynamicGas = gasStaticCallEIP7702
329+
jt[DELEGATECALL].dynamicGas = gasDelegateCallEIP7702
330+
}

core/vm/operations_acl.go

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ import (
2121

2222
"github.com/ethereum/go-ethereum/common"
2323
"github.com/ethereum/go-ethereum/common/math"
24+
"github.com/ethereum/go-ethereum/core/types"
2425
"github.com/ethereum/go-ethereum/params"
2526
)
2627

@@ -247,3 +248,70 @@ func makeSelfdestructGasFn(refundsEnabled bool) gasFunc {
247248
}
248249
return gasFunc
249250
}
251+
252+
var (
253+
gasCallEIP7702 = makeCallVariantGasCallEIP7702(gasCall)
254+
gasDelegateCallEIP7702 = makeCallVariantGasCallEIP7702(gasDelegateCall)
255+
gasStaticCallEIP7702 = makeCallVariantGasCallEIP7702(gasStaticCall)
256+
gasCallCodeEIP7702 = makeCallVariantGasCallEIP7702(gasCallCode)
257+
)
258+
259+
func makeCallVariantGasCallEIP7702(oldCalculator gasFunc) gasFunc {
260+
return func(evm *EVM, contract *Contract, stack *Stack, mem *Memory, memorySize uint64) (uint64, error) {
261+
var (
262+
total uint64 // total dynamic gas used
263+
addr = common.Address(stack.Back(1).Bytes20())
264+
)
265+
266+
// Check slot presence in the access list
267+
if !evm.StateDB.AddressInAccessList(addr) {
268+
evm.StateDB.AddAddressToAccessList(addr)
269+
// The WarmStorageReadCostEIP2929 (100) is already deducted in the form of a constant cost, so
270+
// the cost to charge for cold access, if any, is Cold - Warm
271+
coldCost := params.ColdAccountAccessCostEIP2929 - params.WarmStorageReadCostEIP2929
272+
// Charge the remaining difference here already, to correctly calculate available
273+
// gas for call
274+
if !contract.UseGas(coldCost) {
275+
return 0, ErrOutOfGas
276+
}
277+
total += coldCost
278+
}
279+
280+
// Check if code is a delegation and if so, charge for resolution.
281+
if target, ok := types.ParseDelegation(evm.StateDB.GetCode(addr)); ok {
282+
var cost uint64
283+
if evm.StateDB.AddressInAccessList(target) {
284+
cost = params.WarmStorageReadCostEIP2929
285+
} else {
286+
evm.StateDB.AddAddressToAccessList(target)
287+
cost = params.ColdAccountAccessCostEIP2929
288+
}
289+
if !contract.UseGas(cost) {
290+
return 0, ErrOutOfGas
291+
}
292+
total += cost
293+
}
294+
295+
// Now call the old calculator, which takes into account
296+
// - create new account
297+
// - transfer value
298+
// - memory expansion
299+
// - 63/64ths rule
300+
old, err := oldCalculator(evm, contract, stack, mem, memorySize)
301+
if err != nil {
302+
return old, err
303+
}
304+
305+
// Temporarily add the gas charge back to the contract and return value. By
306+
// adding it to the return, it will be charged outside of this function, as
307+
// part of the dynamic gas. This will ensure it is correctly reported to
308+
// tracers.
309+
contract.Gas += total
310+
311+
var overflow bool
312+
if total, overflow = math.SafeAdd(old, total); overflow {
313+
return 0, ErrGasUintOverflow
314+
}
315+
return total, nil
316+
}
317+
}

0 commit comments

Comments
 (0)