Abstract
On EIP-8130 chains, EIP-2930 and EIP-1559
transactions authenticate through the Keystore instead of treating secp256k1 ecrecover as
authority. A 65-byte signature is always k1 and is checked against the account's default EOA,
with from unspecified ā the same empty-sender path EIP-8130 uses for AA transactions. Any other
signature is account || authenticator || data and is checked against that account's Keystore
actors. Old wallets keep working until the default EOA is revoked; after that those types can be
post-quantum, and aggregatable if the authenticator allows it.
Legacy (type-0) transactions and the EIP-7702 transaction type are not supported. The 7702 delegation indicator remains; EIP-8130 is the sole authority that may set or clear it.
Motivation
EIP-8130 makes accounts crypto-agile: actors point at authenticators, and a post-quantum authenticator
can be authorized without changing the account address. That agility only applies to the AA transaction
type. EIP-2930 and EIP-1559 transactions still treat
ecrecover(hash, v, r, s) == from as sufficient authority. An account that has rotated to a PQ key
ā or revoked its default EOA ā cannot originate a 1559 transfer with that key, and a k1 key that the
account intended to retire can still spend via those types.
This EIP closes that hole for type-1 and type-2. secp256k1 remains the 65-byte default-EOA path so unmodified wallets continue to work for accounts that have not revoked it. Configured-actor signatures use the same authenticator interface as EIP-8130, so a PQ (or aggregatable) authenticator that is valid on the AA path is valid on these types too.
Type-0 is not supported: wallets use type-2 (or 8130). The EIP-7702 transaction
type is deprecated on these chains; the delegation indicator stays, and only 8130 (auto-delegation
and account_changes) may apply it. A chain that wants blobs uses that specialized transaction type.
The 8130 transaction type stays separate from that use case.
Specification
The key words "MUST", "MUST NOT", "SHOULD", "SHOULD NOT", and "MAY" in this document are to be interpreted as described in RFC 2119 and RFC 8174.
This EIP applies only on chains that implement EIP-8130, from the activation of this EIP. Pre-fork
blocks are unchanged. EIP-8130 AA transactions (AA_TX_TYPE) are unchanged; they
already authenticate through the Keystore.
Signature encoding
After activation, the covered transaction types carry a signature as a
byte string sig over the type's existing signing hash H (the hash secp256k1 currently signs;
sig is not part of H). Specialized types (blobs, and any future dedicated envelope) are out of
scope.
Where a type currently encodes secp256k1 as trailing RLP integers (yParity, r, s), clients MUST
also accept that historical encoding and canonicalize it to a 65-byte sig before the rules below:
sig = r (32) || s (32) || y_parity (1)y_parity is 0 or 1.
A type MAY instead encode a single trailing RLP bytes item sig directly.
Two shapes
sig is interpreted by length. Every shape is checked against the Keystore. secp256k1 recovery
alone is never sufficient.
65-byte: default EOA (k1)
If len(sig) == 65, the signature is always secp256k1. from is unspecified and recovered, matching
EIP-8130's empty-sender path:
- Require
sig[64] ā {0, 1}. Letr = sig[0:32],s = sig[32:64],y_parity = sig[64]. - Recover
account = ecrecover(H, y_parity, r, s). Reject if recovery fails. - Set
from = accountandactorId = bytes32(uint256(uint160(account))). - Authorize as EIP-8130's self-actor (native secp256k1) rule: reject if
DEFAULT_EOA_REVOKEDis set onaccount; otherwise takescopeandexpiryfrom the inline default-EOA fields (all-zero = unrestricted, non-expiring admin). Ifexpiryis non-zero, requireblock.timestamp <= expiry.
An unmodified EOA (no Keystore writes, flag unset) therefore keeps working: the implicit default EOA is admin. An account that has revoked the default EOA cannot originate a covered type with a 65-byte k1 signature.
Otherwise: account || authenticator || data
If len(sig) != 65, require len(sig) >= 40 and decode:
account = sig[0:20] // 20 bytes; this is `from`
authenticator = sig[20:40] // 20 bytes
data = sig[40:] // authenticator-specificlen(sig) == 65 is reserved for the default-EOA path, so a configured-actor blob MUST NOT be 65
bytes. An authenticator whose natural data would make 40 + len(data) == 65 MUST use a different
data length (pad or length-prefix).
Then authenticate exactly as EIP-8130's configured-actor path, with sender = account:
- Set
from = account. - If
authenticator == K1_AUTHENTICATOR, native-ecrecoverdataasr || s || vand setactorId = bytes32(uint256(uint160(recovered_address))). OtherwiseSTATICCALLauthenticator.authenticate(H, data)with the same canonical-vs-permissive acceptance policy as EIP-8130 (including theMAX_AUTHENTICATION_GASbound), and take the returnedactorId. - Authorize against the Keystore of
account: the secp256k1 self-actor rule if this was the native k1 path andactorIdis the self-actorId; otherwise SLOADactor_config(account, actorId), require the stored authenticator matches, and enforceexpiry. address(0)is never a valid authenticator selector.
Scope
These transaction types always self-pay and always consume the account's EVM nonce. After authentication, require:
scope == 0x00 || ((scope & SENDER) != 0 && (scope & SELF_PAYER) != 0 && (scope & POLICY) == 0)That is admin, or SENDER and SELF_PAYER without POLICY. POLICY actors MUST NOT
originate these types; gated initiation stays on the EIP-8130 AA path, where the protocol can enforce
call.to == manager. This is not Scopes.isOperator alone (isOperator is admin or SENDER
without POLICY, and does not require SELF_PAYER).
NONCE is not consulted: it gates EIP-8130 2D nonce keys, not the EVM nonce these types use.
SPONSOR_PAYER is not consulted: these types have no payer field.
Aggregation
data is authenticator-defined. An authenticator that supports aggregation MAY encode in data a
share, a proof, or a handle into an aggregate. authenticate(H, data) MUST still return the
actorId that authorized this transaction's hash. How shares are combined at block level (a
sidecar, an aggregate blob, a precompile) is defined by that authenticator; this EIP does not add a
transaction-type-specific aggregation envelope. An authenticator that does not support aggregation
is verified standalone, as on the EIP-8130 AA path.
Covered transaction types
This EIP amends type 0x01 and type 0x02. EIP-8130 AA_TX_TYPE is unchanged
(already Keystore-authenticated).
| Type | Spec | Signing hash H | Historical ECDSA fields |
|---|---|---|---|
0x01 | EIP-2930 | type-1 payload hash | yParity, r, s |
0x02 | EIP-1559 | type-2 payload hash | yParity, r, s |
Not supported: type 0. Legacy transactions are invalid after activation. Wallets use type 0x02
or AA_TX_TYPE.
Deprecated: EIP-7702 transaction type. Type 0x04 is invalid after activation.
The 7702 delegation indicator (0xef0100 || target) remains, including code-loading semantics.
EIP-8130 is the sole authority that may set or clear it: auto-delegation to
DEFAULT_ACCOUNT_ADDRESS and the delegation entry in account_changes. No authorization_list, and
no other transaction type, may write the indicator.
Out of scope: blob transactions. EIP-4844 type 0x03 remains the specialized
blob envelope. A chain that wants blobs uses that type; 8130 stays separate from that use case.
Out of scope: ecrecover. The secp256k1 recovery precompile is unchanged. It remains a pure
function of (hash, v, r, s) and MUST NOT consult the Keystore. In-contract signature checks that
need Keystore authority use EIP-8130 validateSignature / account isValidSignature (and, if
enshrined, the native validateSignature precompile EIP-8130 already sketches). A companion EIP MAY
expose that precompile; this EIP MUST NOT retarget ecrecover.
Gas
Authentication is metered as EIP-8130 sender_auth_cost (canonical authenticators: the enshrined
constant; others: STATICCALL bounded by MAX_AUTHENTICATION_GAS). The 65-byte default-EOA path is
native ecrecover plus the default-EOA slot read, same as EIP-8130's empty-sender path. Exact numbers
follow the chain's EIP-8130 adoption profile. Additional intrinsic
gas for this EIP: TBD.
Rationale
Why Keystore on type-1 and type-2, not a new type. A new PQ transaction type would leave 1559 as a k1 backdoor. Rotating off secp256k1 on ordinary calls and value transfers only works if those origin paths consult the Keystore.
Why type 0 is not supported. Legacy encoding puts chain id in v and has no typed envelope.
Type-2 already covers the same execution; wallets migrate to it (or to 8130). Rejecting type 0 avoids
a second signature encoding and a k1-only path that would otherwise have to be Keystore-checked.
Why the 7702 transaction type is deprecated, and why the indicator stays. The alternative to
deprecation is keeping type 0x04 and Keystore-checking authorization_list (same 65-byte /
account || authenticator || data shapes as origin). That would close the k1 hole on inner
authorities, but it would keep a second writer of the indicator next to 8130, and a second
envelope wallets have to implement. 8130 already has the Keystore-authenticated replacement:
auto-delegation and the delegation entry in account_changes (authorized by sender_auth).
This EIP takes deprecation. Type 0x04 is invalid after activation. The indicator
(0xef0100 || target) and code-loading remain; 8130 is the sole writer. Non-8130 chains keep
using type 0x04 as today. A Keystore-checked authorization_list is out of scope.
Why not blobs here, and why not on 8130. Blob data is a different job and already has a dedicated
type. 8130 is the AA execution envelope; it does not carry blob signatures or versioned hashes.
Chains that do not care about blobs never implement type 0x03. Jamming blob fields into 8130 ā or
rewriting 4844 inside this EIP ā couples unrelated adoption. PQ blob originators, if needed, are a
companion change on the blob type.
Why 65 bytes is always k1 default EOA. That is the EIP-8130 empty-sender shape: from is not
on the wire, ecrecover yields it, the default EOA authorizes it. Reusing it means unmodified wallets
keep sending type-2 transactions for accounts that have not revoked k1. Length is the distinguisher
because type-1 and type-2 have no sender field.
Why account || authenticator || data otherwise. EIP-8130 configured-actor signatures are
authenticator || data with sender set separately. Type-1 and type-2 have no sender field, so the
account address is prepended. The rest of authentication ā canonical set, actor_config bind,
expiry, adoption-profile acceptance ā is identical, including aggregation wherever the authenticator
already allows it on the AA path.
Why not ecrecover here. Transaction origin and in-EVM recovery are different layers.
ecrecover is a pure cryptographic primitive with a fixed (hash, v, r, s) ABI: it cannot carry
authenticator || data, so it cannot authenticate a PQ actor no matter what Keystore rule is bolted
on. Existing bytecode also uses it for keys that are not accounts (ephemeral signing keys, not 8130
actors). Tying it to DEFAULT_EOA_REVOKED would mix "whose secp256k1 key" with "does this account
still speak k1." EIP-8130 already specifies the replacement: validateSignature, optionally as a
native precompile. That is a separate EIP.
PQ deprecation path. Authorize a PQ actor (8130 AA tx or a Keystore call signed with the still-live
default EOA). Start originating type-2 transactions with account || pq_authenticator || data.
Revoke the default EOA. 65-byte k1 signatures fail on type-1 and type-2. The account address does not
change. Type 0 and type 0x04 are already invalid. Blob origin, if the chain implements it, is
unchanged until a blob-type companion applies the same rule.
Backwards Compatibility
Pre-fork blocks are unchanged. After activation:
- Type 0 and type
0x04are invalid. Wallets that sent legacy or 7702 transactions switch to type0x02orAA_TX_TYPE. Existing 7702 indicators persist; only 8130 may update them. - Accounts that have not set
DEFAULT_EOA_REVOKEDstill originate type-1 and type-2 with a 65-byte k1 signature (historicalyParity, r, sencodings included). Vanilla EOAs are unaffected on those types. - Accounts that have revoked the default EOA, or were created without a k1 self-actor, MUST use
account || authenticator || dataon type-1 and type-2. Wallets that only produce 65-byte signatures cannot originate for those accounts ā that is the deprecation. - EIP-8130 AA transactions are unaffected.
- EIP-4844 type
0x03is unaffected. - The
ecrecoverprecompile is unaffected. - Non-8130 chains are unaffected (type 0 and type
0x04remain valid there).
Security Considerations
k1 is not authority. ecrecover identifies a candidate from; the default-EOA slot decides
whether that key still speaks for the account. Clients MUST NOT accept a 65-byte signature for an
account with DEFAULT_EOA_REVOKED.
Length collision. len(sig) == 65 is exclusively the default-EOA path. A configured-actor
encoding of total length 65 is invalid as that path (and would ecrecover garbage). Authenticators
MUST NOT emit 25-byte data without padding.
Scope. Require admin, or SENDER | SELF_PAYER with POLICY unset. A SENDER actor without
SELF_PAYER cannot self-pay an EIP-8130 AA transaction and MUST NOT self-pay a type-2 transaction
either. POLICY keys cannot originate these types (no tx.to gate here; they stay on the AA path).
No authorization_list. Type 0x04 is invalid. This EIP does not Keystore-upgrade inner
7702 tuples; it removes the type that carried them. Delegation on these chains is only 8130
auto-delegation and account_changes, which already Keystore-authenticate the sender. There is
no remaining k1-only path to set or clear code delegation.
Authenticator acceptance. The same EIP-8130 adoption-profile rules apply. A canonical-only chain MUST NOT accept a non-canonical authenticator on a type-2 transaction any more than on an AA transaction.
In-contract ecrecover. This EIP closes k1 as transaction origin for the covered types. It
does not close k1 as in-EVM recovery: a revoked default EOA can still satisfy ecrecover in
Permit, Permit2, and similar callers. That is intentional and residual. Callers that mean "does this
account authorize this hash" MUST use EIP-8130 validateSignature / ERC-1271. Enshrining that as a
precompile is a companion EIP.
Replay. Signing hashes and EVM nonces are unchanged. A signature valid for type 2 is not valid for
type 1; a Keystore-authorized actor cannot replay across types. Chain id remains in H.
Copyright
Copyright and related rights waived via CC0.
