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.
System information
Geth version: master (commit 7a73ffe)
OS & Version: all
Description
When a
SetCodeTx(EIP-7702, tx type0x04) is signed through the externalsigner path (Clef /
ExternalSigner), its authorization list is silentlydropped, 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.SignTxnever serializes the authorization list.In
accounts/external/backend.go,SetCodeTxTypeis folded into the samecaseas dynamic-fee and blob transactions, so only the fee fields and accesslist are copied into
SendTxArgs:tx.SetCodeAuthorizations()is never read, so the authorizations are not sentto the external signer at all.
2.
apitypes.SendTxArgs/ToTransactioncannot represent a set-code tx.SendTxArgs(signer/core/apitypes/types.go:86) has no field for theauthorization list, and
ToTransaction(signer/core/apitypes/types.go:137)has no
SetCodeTxbranch. Because the switch is orderedBlobHashes != nil -> MaxFeePerGas != nil -> AccessList != nil -> legacy, aset-code transaction (which has
MaxFeePerGasset) is reconstructed as a plainDynamicFeeTx. The transaction type changes and any authorizations are lost.Impact
A wallet that delegates
SetCodeTxTypesigning to Clef / an external signergets 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
SendTxArgs, e.g.AuthorizationList []types.SetCodeAuthorization \json:"authorizationList,omitempty"``.ExternalSigner.SignTx, add a dedicatedcase types.SetCodeTxTypethatalso sets
args.AuthorizationList = tx.SetCodeAuthorizations().ToTransaction, add a branch that builds a*types.SetCodeTxwhen theauthorization list is present.
Steps to reproduce
External-sign a set-code transaction carrying one authorization and assert the
returned transaction's type is still
SetCodeTxTypeand its authorization listis preserved.