From 2133e014ae24553561066cd1c4677eeff5f986a8 Mon Sep 17 00:00:00 2001 From: ozpool <151670776+ozpool@users.noreply.github.com> Date: Wed, 8 Jul 2026 23:27:31 +0530 Subject: [PATCH] internal/ethapi: reject gasPrice together with authorizationList (#35320) Closes #35314. ### Problem `TransactionArgs.ToTransaction` selects `SetCodeTxType` when an `authorizationList` is present, but then unconditionally downgrades to `LegacyTxType` when `gasPrice` is set: ```go case args.AuthorizationList != nil || defaultType == types.SetCodeTxType: usedType = types.SetCodeTxType ... if args.GasPrice != nil { usedType = types.LegacyTxType } ``` A legacy transaction cannot carry an EIP-7702 authorization list, so the list is silently dropped. `eth_sendTransaction`, `eth_signTransaction` and `eth_fillTransaction` can then return a plain legacy transaction/hash even though the requested delegation update or revocation was never included. The downgrade also masks a latent issue: `setFeeDefaults` returns early once `gasPrice` is set (without `authorizationList`) and never fills `MaxFeePerGas`/`MaxPriorityFeePerGas`. Building the `SetCodeTx` without the downgrade would hit `uint256.MustFromBig((*big.Int)(args.MaxFeePerGas))` with a nil fee cap and panic. Erroring early is therefore the correct behavior. ### Fix Reject the `gasPrice` + `authorizationList` combination in `setFeeDefaults`, mirroring the existing `gasPrice` / EIP-1559 guard, so the request fails explicitly instead of producing a transaction that omits the authorization list. ### Test Added a `setFeeDefaults` case asserting the new error. Verified fail-on-main: with the guard reverted the test fails (`expected error: both gasPrice and authorizationList specified`); with the guard it passes. Full `internal/ethapi` package, `go vet` and `gofmt` are clean. ### Note The same silent-drop applies to `gasPrice` + `blobVersionedHashes` (blob transactions also cannot be legacy). I scoped this PR to the reported `authorizationList` case; happy to extend the guard to blob hashes in the same spot if preferred. --- internal/ethapi/transaction_args.go | 6 ++++++ internal/ethapi/transaction_args_test.go | 8 ++++++++ 2 files changed, 14 insertions(+) diff --git a/internal/ethapi/transaction_args.go b/internal/ethapi/transaction_args.go index 1a7cf1c118..586df48759 100644 --- a/internal/ethapi/transaction_args.go +++ b/internal/ethapi/transaction_args.go @@ -195,6 +195,12 @@ func (args *TransactionArgs) setFeeDefaults(ctx context.Context, b Backend, head if args.GasPrice != nil && (args.MaxFeePerGas != nil || args.MaxPriorityFeePerGas != nil) { return errors.New("both gasPrice and (maxFeePerGas or maxPriorityFeePerGas) specified") } + // An EIP-7702 set-code transaction cannot be a legacy transaction, so gasPrice + // is incompatible with an authorization list. Reject the combination instead of + // silently dropping the authorization list in ToTransaction. + if args.GasPrice != nil && args.AuthorizationList != nil { + return errors.New("both gasPrice and authorizationList specified") + } // If the tx has completely specified a fee mechanism, no default is needed. // This allows users who are not yet synced past London to get defaults for // other tx values. See https://github.com/ethereum/go-ethereum/pull/23274 diff --git a/internal/ethapi/transaction_args_test.go b/internal/ethapi/transaction_args_test.go index f3fc16dcbb..1d587032bb 100644 --- a/internal/ethapi/transaction_args_test.go +++ b/internal/ethapi/transaction_args_test.go @@ -58,6 +58,7 @@ func TestSetFeeDefaults(t *testing.T) { fortytwo = (*hexutil.Big)(big.NewInt(42)) maxFee = (*hexutil.Big)(new(big.Int).Add(new(big.Int).Mul(b.current.BaseFee, big.NewInt(2)), fortytwo.ToInt())) al = &types.AccessList{types.AccessTuple{Address: common.Address{0xaa}, StorageKeys: []common.Hash{{0x01}}}} + authList = []types.SetCodeAuthorization{{Address: common.Address{0xbb}}} ) tests := []test{ @@ -208,6 +209,13 @@ func TestSetFeeDefaults(t *testing.T) { nil, errors.New("both gasPrice and (maxFeePerGas or maxPriorityFeePerGas) specified"), }, + { + "set gas price and authorization list", + "london", + &TransactionArgs{GasPrice: fortytwo, AuthorizationList: authList}, + nil, + errors.New("both gasPrice and authorizationList specified"), + }, // EIP-4844 { "set gas price and maxFee for blob transaction",