From 16ba4de5a08e2fbff8afd962b5068224d79bd312 Mon Sep 17 00:00:00 2001 From: MariusVanDerWijden Date: Fri, 17 Apr 2026 17:38:48 +0200 Subject: [PATCH] core: implement eip-7981: Increase Access List Cost --- cmd/evm/internal/t8ntool/transaction.go | 2 +- core/state_processor_test.go | 2 +- core/state_transition.go | 39 ++++++++++++++++++------- core/txpool/validation.go | 2 +- tests/block_test_util.go | 24 +++++++-------- tests/transaction_test_util.go | 2 +- 6 files changed, 45 insertions(+), 26 deletions(-) diff --git a/cmd/evm/internal/t8ntool/transaction.go b/cmd/evm/internal/t8ntool/transaction.go index f4b462572c..d8eb86523a 100644 --- a/cmd/evm/internal/t8ntool/transaction.go +++ b/cmd/evm/internal/t8ntool/transaction.go @@ -148,7 +148,7 @@ func Transaction(ctx *cli.Context) error { } // For Prague txs, validate the floor data gas. if rules.IsPrague { - floorDataGas, err := core.FloorDataGas(rules, tx.Data()) + floorDataGas, err := core.FloorDataGas(rules, tx.Data(), tx.AccessList()) if err != nil { r.Error = err results = append(results, r) diff --git a/core/state_processor_test.go b/core/state_processor_test.go index 7b3877b96a..7cb5963086 100644 --- a/core/state_processor_test.go +++ b/core/state_processor_test.go @@ -487,7 +487,7 @@ func TestEIP8037MaxRegularGasValidation(t *testing.T) { } // Verify that floor data gas exceeds MaxTxGas - floorGas, err := FloorDataGas(rules, largeData) + floorGas, err := FloorDataGas(rules, largeData, nil) if err != nil { t.Fatalf("Failed to calculate floor data gas: %v", err) } diff --git a/core/state_transition.go b/core/state_transition.go index 27fe8055b6..2ea4641a56 100644 --- a/core/state_transition.go +++ b/core/state_transition.go @@ -114,22 +114,38 @@ func IntrinsicGas(data []byte, accessList types.AccessList, authList []types.Set } } if accessList != nil { - gas.RegularGas += uint64(len(accessList)) * params.TxAccessListAddressGas - gas.RegularGas += uint64(accessList.StorageKeys()) * params.TxAccessListStorageKeyGas - } - if authList != nil { + addresses := uint64(len(accessList)) + storageKeys := uint64(accessList.StorageKeys()) + if (math.MaxUint64-gas.RegularGas)/params.TxAccessListAddressGas < addresses { + return vm.GasCosts{}, ErrGasUintOverflow + } + gas.RegularGas += addresses * params.TxAccessListAddressGas + if (math.MaxUint64-gas.RegularGas)/params.TxAccessListStorageKeyGas < storageKeys { + return vm.GasCosts{}, ErrGasUintOverflow + } + gas.RegularGas += storageKeys * params.TxAccessListStorageKeyGas + + // EIP-7981: access list data is charged in addition to the base charge. if rules.IsAmsterdam { - gas.RegularGas += uint64(len(authList)) * params.TxAuthTupleRegularGas - gas.StateGas += uint64(len(authList)) * (params.AuthorizationCreationSize + params.AccountCreationSize) * costPerStateByte - } else { - gas.RegularGas += uint64(len(authList)) * params.CallNewAccountGas + const ( + addressCost = common.AddressLength * params.TxCostFloorPerToken7976 * params.TxTokenPerNonZeroByte + storageKeyCost = common.HashLength * params.TxCostFloorPerToken7976 * params.TxTokenPerNonZeroByte + ) + if (math.MaxUint64-gas.RegularGas)/addressCost < addresses { + return vm.GasCosts{}, ErrGasUintOverflow + } + gas.RegularGas += addresses * addressCost + if (math.MaxUint64-gas.RegularGas)/storageKeyCost < storageKeys { + return vm.GasCosts{}, ErrGasUintOverflow + } + gas.RegularGas += storageKeys * storageKeyCost } } return gas, nil } // FloorDataGas computes the minimum gas required for a transaction based on its data tokens (EIP-7623). -func FloorDataGas(rules params.Rules, data []byte) (uint64, error) { +func FloorDataGas(rules params.Rules, data []byte, accessList types.AccessList) (uint64, error) { var ( tokens uint64 tokenCost uint64 @@ -139,6 +155,9 @@ func FloorDataGas(rules params.Rules, data []byte) (uint64, error) { // From 10/40 to 64/64 for zero/non-zero bytes. tokens = uint64(len(data)) * params.TxTokenPerNonZeroByte tokenCost = params.TxCostFloorPerToken7976 + // EIP-7981 adds additional tokens for every entry in the accesslist + tokens += uint64(len(accessList)) * common.AddressLength * params.TxTokenPerNonZeroByte + tokens += uint64(accessList.StorageKeys()) * common.HashLength * params.TxTokenPerNonZeroByte } else { var ( z = uint64(bytes.Count(data, []byte{0})) @@ -486,7 +505,7 @@ func (st *stateTransition) execute() (*ExecutionResult, error) { // Compute the floor data cost (EIP-7623), needed for both Prague and Amsterdam validation. if rules.IsPrague { - floorDataGas, err = FloorDataGas(rules, msg.Data) + floorDataGas, err = FloorDataGas(rules, msg.Data, msg.AccessList) if err != nil { return nil, err } diff --git a/core/txpool/validation.go b/core/txpool/validation.go index 4155d9e12d..1b65d0c80f 100644 --- a/core/txpool/validation.go +++ b/core/txpool/validation.go @@ -144,7 +144,7 @@ func ValidateTransaction(tx *types.Transaction, head *types.Header, signer types // Ensure the transaction can cover floor data gas. if rules.IsPrague { - floorDataGas, err := core.FloorDataGas(rules, tx.Data()) + floorDataGas, err := core.FloorDataGas(rules, tx.Data(), tx.AccessList()) if err != nil { return err } diff --git a/tests/block_test_util.go b/tests/block_test_util.go index f0b64266a5..900b108623 100644 --- a/tests/block_test_util.go +++ b/tests/block_test_util.go @@ -214,18 +214,18 @@ func (t *BlockTest) Network() string { func (t *BlockTest) genesis(config *params.ChainConfig) *core.Genesis { return &core.Genesis{ - Config: config, - Nonce: t.json.Genesis.Nonce.Uint64(), - Timestamp: t.json.Genesis.Timestamp, - ParentHash: t.json.Genesis.ParentHash, - ExtraData: t.json.Genesis.ExtraData, - GasLimit: t.json.Genesis.GasLimit, - GasUsed: t.json.Genesis.GasUsed, - Difficulty: t.json.Genesis.Difficulty, - Mixhash: t.json.Genesis.MixHash, - Coinbase: t.json.Genesis.Coinbase, - Alloc: t.json.Pre, - BaseFee: t.json.Genesis.BaseFeePerGas, + Config: config, + Nonce: t.json.Genesis.Nonce.Uint64(), + Timestamp: t.json.Genesis.Timestamp, + ParentHash: t.json.Genesis.ParentHash, + ExtraData: t.json.Genesis.ExtraData, + GasLimit: t.json.Genesis.GasLimit, + GasUsed: t.json.Genesis.GasUsed, + Difficulty: t.json.Genesis.Difficulty, + Mixhash: t.json.Genesis.MixHash, + Coinbase: t.json.Genesis.Coinbase, + Alloc: t.json.Pre, + BaseFee: t.json.Genesis.BaseFeePerGas, BlobGasUsed: t.json.Genesis.BlobGasUsed, ExcessBlobGas: t.json.Genesis.ExcessBlobGas, SlotNumber: t.json.Genesis.SlotNumber, diff --git a/tests/transaction_test_util.go b/tests/transaction_test_util.go index 8d7a7c717a..f141a34534 100644 --- a/tests/transaction_test_util.go +++ b/tests/transaction_test_util.go @@ -93,7 +93,7 @@ func (tt *TransactionTest) Run() error { if rules.IsPrague { var floorDataGas uint64 - floorDataGas, err = core.FloorDataGas(rules, tx.Data()) + floorDataGas, err = core.FloorDataGas(rules, tx.Data(), tx.AccessList()) if err != nil { return }