Skip to content

accounts/external, signer: EIP-7702 set-code transactions lose authorization list when signed by external signer #35092

@cuiweixie

Description

@cuiweixie

System information

Geth version: master (commit 7a73ffe)
OS & Version: all

Description

When a SetCodeTx (EIP-7702, tx type 0x04) is signed through the external
signer path (Clef / ExternalSigner), its authorization list is silently
dropped, and the transaction is round-tripped through a struct that cannot
represent a set-code transaction. The result is a signed transaction that is
either missing its authorizations or reconstructed as the wrong type.

There are two related gaps:

1. ExternalSigner.SignTx never serializes the authorization list.

In accounts/external/backend.go, SetCodeTxType is folded into the same
case as dynamic-fee and blob transactions, so only the fee fields and access
list are copied into SendTxArgs:

// accounts/external/backend.go:215
switch tx.Type() {
case types.LegacyTxType, types.AccessListTxType:
    args.GasPrice = (*hexutil.Big)(tx.GasPrice())
case types.DynamicFeeTxType, types.BlobTxType, types.SetCodeTxType:
    args.MaxFeePerGas = (*hexutil.Big)(tx.GasFeeCap())
    args.MaxPriorityFeePerGas = (*hexutil.Big)(tx.GasTipCap())
...

tx.SetCodeAuthorizations() is never read, so the authorizations are not sent
to the external signer at all.

2. apitypes.SendTxArgs / ToTransaction cannot represent a set-code tx.

SendTxArgs (signer/core/apitypes/types.go:86) has no field for the
authorization list, and ToTransaction (signer/core/apitypes/types.go:137)
has no SetCodeTx branch. Because the switch is ordered
BlobHashes != nil -> MaxFeePerGas != nil -> AccessList != nil -> legacy, a
set-code transaction (which has MaxFeePerGas set) is reconstructed as a plain
DynamicFeeTx. The transaction type changes and any authorizations are lost.

Impact

A wallet that delegates SetCodeTxType signing to Clef / an external signer
gets back a transaction that has lost its EIP-7702 authorizations, or has been
turned into a dynamic-fee transaction. The intended delegation/account-code
change does not take effect.

Suggested fix

  • Add an authorization-list field to SendTxArgs, e.g.
    AuthorizationList []types.SetCodeAuthorization \json:"authorizationList,omitempty"``.
  • In ExternalSigner.SignTx, add a dedicated case types.SetCodeTxType that
    also sets args.AuthorizationList = tx.SetCodeAuthorizations().
  • In ToTransaction, add a branch that builds a *types.SetCodeTx when the
    authorization list is present.

Steps to reproduce

External-sign a set-code transaction carrying one authorization and assert the
returned transaction's type is still SetCodeTxType and its authorization list
is preserved.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions