@@ -18,6 +18,7 @@ package vm
18
18
19
19
import (
20
20
"errors"
21
+ "fmt"
21
22
22
23
"github.com/ethereum/go-ethereum/common"
23
24
"github.com/ethereum/go-ethereum/common/math"
@@ -318,12 +319,25 @@ var (
318
319
gasCallCodeEIP7907 = makeCallVariantGasCallEIP7907 (gasCallCode )
319
320
)
320
321
321
- func getColdCodeAccessGasCost (evm * EVM , addr common.Address ) uint64 {
322
- codeSize := evm .StateDB .GetCodeSize (addr )
323
- if codeSize <= params .MaxCodeSizeEIP7907 {
322
+ // Rounds n up to the nearest multiple of 32.
323
+ func ceil32 (n int ) uint64 {
324
+ r := n % 32
325
+ if r == 0 {
326
+ return uint64 (n )
327
+ } else {
328
+ return uint64 (n + 32 - r )
329
+ }
330
+ }
331
+
332
+ func calcColdCodeAccessGasCost (evm * EVM , addr common.Address ) uint64 {
333
+ size := evm .StateDB .GetCodeSize (addr )
334
+ // Only charge additional access cost for contracts larger than old limit.
335
+ if size <= params .MaxCodeSizeEIP170 {
324
336
return 0
325
337
}
326
- return (uint64 (codeSize ) - params .MaxCodeSizeEIP7907 ) * 2 / 32
338
+ excess := ceil32 (size - params .MaxCodeSizeEIP170 )
339
+ fmt .Println ("excess" , excess , "cost" , (excess * params .CodeReadPerWordGasEIP7907 )/ 32 )
340
+ return (excess * params .CodeReadPerWordGasEIP7907 ) / 32
327
341
}
328
342
329
343
func makeCallVariantGasCallEIP7907 (oldCalculator gasFunc ) gasFunc {
@@ -346,16 +360,20 @@ func makeCallVariantGasCallEIP7907(oldCalculator gasFunc) gasFunc {
346
360
}
347
361
total += coldCost
348
362
}
363
+
349
364
// Check code presence in the access list
350
365
if ! evm .StateDB .AddressCodeInAccessList (addr ) {
351
- cost := getColdCodeAccessGasCost (evm , addr )
366
+ cost := calcColdCodeAccessGasCost (evm , addr )
352
367
evm .StateDB .AddAddressCodeToAccessList (addr )
353
368
if ! contract .UseGas (cost , evm .Config .Tracer , tracing .GasChangeCallStorageColdAccess ) {
354
369
return 0 , ErrOutOfGas
355
370
}
356
371
total += cost
357
372
}
358
373
374
+ // TODO: reading code here would defeat the purpose of separate charging, so
375
+ // we should first see if the code size is 23 bytes before parsing.
376
+
359
377
// Check if code is a delegation and if so, charge for resolution.
360
378
if target , ok := types .ParseDelegation (evm .StateDB .GetCode (addr )); ok {
361
379
var cost uint64
@@ -370,7 +388,7 @@ func makeCallVariantGasCallEIP7907(oldCalculator gasFunc) gasFunc {
370
388
}
371
389
total += cost
372
390
if ! evm .StateDB .AddressCodeInAccessList (target ) {
373
- cost = getColdCodeAccessGasCost (evm , target )
391
+ cost = calcColdCodeAccessGasCost (evm , target )
374
392
evm .StateDB .AddAddressCodeToAccessList (target )
375
393
if ! contract .UseGas (cost , evm .Config .Tracer , tracing .GasChangeCallStorageColdAccess ) {
376
394
return 0 , ErrOutOfGas
@@ -410,27 +428,25 @@ func gasExtCodeCopyEIP7907(evm *EVM, contract *Contract, stack *Stack, mem *Memo
410
428
return 0 , err
411
429
}
412
430
addr := common .Address (stack .peek ().Bytes20 ())
413
- var total uint64
414
431
// Check slot presence in the access list
415
432
if ! evm .StateDB .AddressInAccessList (addr ) {
416
433
evm .StateDB .AddAddressToAccessList (addr )
434
+ var overflow bool
417
435
// We charge (cold-warm), since 'warm' is already charged as constantGas
418
-
419
- if ! contract .UseGas (gas , evm .Config .Tracer , tracing .GasChangeCallStorageColdAccess ) {
420
- return 0 , ErrOutOfGas
436
+ if gas , overflow = math .SafeAdd (gas , params .ColdAccountAccessCostEIP2929 - params .WarmStorageReadCostEIP2929 ); overflow {
437
+ return 0 , ErrGasUintOverflow
421
438
}
422
- total += gas
423
439
}
424
440
425
441
// Check address code presence in the access list
426
442
if ! evm .StateDB .AddressCodeInAccessList (addr ) {
427
- cost := getColdCodeAccessGasCost (evm , addr )
443
+ cost := calcColdCodeAccessGasCost (evm , addr )
428
444
evm .StateDB .AddAddressCodeToAccessList (addr )
429
- if ! contract .UseGas (cost , evm .Config .Tracer , tracing .GasChangeCallStorageColdAccess ) {
430
- return 0 , ErrOutOfGas
445
+ var overflow bool
446
+ // We charge (cold-warm), since 'warm' is already charged as constantGas
447
+ if gas , overflow = math .SafeAdd (gas , cost ); overflow {
448
+ return 0 , ErrGasUintOverflow
431
449
}
432
- total += cost
433
450
}
434
-
435
- return total , nil
451
+ return gas , nil
436
452
}
0 commit comments