Native Ephemeral Key Rotation via Frame Transactions

Native Ephemeral Key Rotation via Frame Transactions

Thanks to @mvicari for his contributions and to @asanso for his feedback

Abstract

This is a follow up to our previous post Achieving Quantum Safety Through Ephemeral Key Pairs and Account Abstraction.

We propose integrating ephemeral key rotation directly into the frame transaction format (EIP-8141), without requiring a separate Account Abstraction layer. By adding a singleton registry contract, signing authority can be decoupled from onchain identity at the protocol level, and native bundling from Frame Transactions enables us to add a frame to rotate signer to each transaction, enabling disposable ECDSA keys with minimal overhead and maximum uniformity, making key rotation available uniformly to all senders.

Motivation

EIP-8141 introduces frame transactions, which decouple validation logic from the transaction sender, opening the door to arbitrary signature schemes. Independently, in our prior work we show that key rotation after every transaction, implemented at the AA layer, effectively neutralizes the quantum threat to ECDSA by making every exposed key immediately useless.

Frame transactions already provide a natural home for this rotation logic: rather than implementing key rotation inside each smart contract wallet independently, we can bake it into the transaction format itself, making it available uniformly to all senders.

Design

The proposal requires two components to work:

1. A Signer Registry Contract

A singleton contract deployed at a well-known address maintains a mapping from account address to its current authorized signer:

mapping(address account => address signer) public signerOf;

We built an example implementation of this registry contract at our git repo.

In the future, we plan on upgrading this contract to also contain the code necessary to handle the whole VERIFY process of frame transactions using ECDSA signatures.

2. An Additional Frame in the Frame Transaction

To achieve the rotation it is necessary to add a frame which targets the singleton contract, changing the authorized signer to the next signer. Bundling is native in frame transactions, so this frame can be added to any transaction without requiring protocol changes.

Validation Flow

In the VERIFY frame, the current signer for tx.sender is looked up in the registry. The transaction signature is verified against that signer (rather than against tx.sender directly).

  • If signerOf[sender] == address(0), the user signature is verified against tx.sender directly, preserving EOA-like behavior as the default.
  • If validation passes, the registry entry for tx.sender is updated to nextSigner, completing the rotation:
signerOf[tx.sender] = nextSigner;

This last step is done in an additional frame, as the validation frame cannot make state changes.

This rotation must occur even if other execution frames revert, mirroring the same invariant identified in the AA-based approach: a failed transaction must not leave the current signer exposed without rotating it.

Rotation Toggle

If no rotation frame is included in the transaction, no signer rotation will occur, making the key rotation feature completely optional. The user can decide to switch it on and off on any Ethereum account simply by adding the appropriate frame to a transaction.

Properties

  • Decoupled signing from onchain identity: the account address never changes; only the authorized signer rotates.
  • Quantum mitigation: each private key is used exactly once; even if later recovered by a quantum computer, it cannot authorize future transactions.
  • Opt-in by default: accounts that never write to the registry (or set nextSigner = 0 permanently) experience standard behavior with no overhead.
  • No per-wallet logic required: sender-signer decoupling is handled at the transaction validation layer, not inside each contract, removing the need for custom smart wallet implementations.
  • BIP44 compatibility: the nextSigner address can be derived from a BIP44 path, making the scheme compatible with existing HD wallet infrastructure.

Comparison with AA-Based Rotation

The AA-based approach from our previous post implements this same rotation inside the smart contract wallet’s validateUserOp, showing that this approach is viable today and demonstrated at ~136k gas for an ERC20 transfer. This frame transaction approach differs in that:

  • Rotation is a first-class protocol feature, not a per-wallet convention.
  • All frame-transaction senders benefit without needing to deploy or upgrade a smart wallet.
6 Likes

Hi, I’m Ivan from ethrex. I considered this proposal to be included in our current demo implementation of EIP-8141, and found a gap in it.

I tried two ways to make ephemeral key rotation work without per-user contract deployment. Both fail under the current spec.

If you set frame.target to the registry, the registry can verify the signature against signerOf[sender]. But APPROVE(scope=1) checks frame.target == tx.sender, and the registry’s address is not the sender’s. APPROVE reverts.

If you set frame.target to the sender (an EOA) and rely on the default code, ecrecover runs and checks recovered_address == frame.target. The signing key is an ephemeral key whose address differs from the sender’s. The default code has no registry lookup. Verification fails.

Both paths lead to the same conclusion: the sender needs deployed code that queries the registry during VERIFY. A per-user contract calling registry.resolve(address(this)) works, but reintroduces the deployment step.

The root cause is that sender approval (scope 1) requires frame.target == tx.sender, while payer approval (scope 2) does not. A shared contract can approve as payer for anyone but cannot approve sender identity for a different address.

1 Like

Hi Ivan, thanks for taking the time to consider this!
You’re right, we missed that restriction on the sender verification. This idea with frame transactions as currently defined in the EIP would work only with a smart contract wallet per account implementation.
For this to work with frame txs and the global registry we would need the frame txs to either relax the check frame.target == tx.sender when targeting the registry contract, or change the default account to read the signer from the registry.
I think it would be interesting to include this feature, as it is a way to decouple signing from sender address in a very easy and lightweight manner. We are aware that allowing EOAs to act in such a way is a bit out of the scope of the frame tx proposal, which would aim to have a smart contract wallet for each user, but we think that this addition could help the average Ethereum user to have a smoother transition to a fully AA (and post-quantum) future.

Anyways, this proposal still benefits from frame txs, as the capability of using custom verification logic would simplify the managment of the smart contract wallets that would be required. We are thrilled to work with you to build a demo of this!

2 Likes

Separate from the APPROVE gap, I have a question about the registry architecture itself.

A smart account contract that stores currentSigner in its own storage does the same job. VERIFY reads self.currentSigner, verifies ecrecover, calls APPROVE. A SENDER frame writes self.currentSigner = nextSigner. No shared contract needed.

EIP-8141 smart accounts already support this. You swap a fixed public key for a rotatable signer address in one storage slot. Each account manages its own key chain.

The registry routes every signer lookup and rotation through a single contract. Your post doesn’t argue for cross-account signer visibility or shared rotation infrastructure, so I’m curious what the registry adds over per-account storage.

1 Like

Yep thanks for the question, as you noted the core of this idea is perfectly doable with per-account storage.
Anyways, I think the main merit of having one single contract that handles this verification logic is having a trusted verification target besides default account.
At the moment allowing each user to write custom logic in each smart contract wallet possibly opens the possibility of DOS by submitting calls to malicious verification logic and puts the burden of protecting themselves from this on nodes applying stricter admission rules.
Having VERIFY frames target the singleton contract instead could help identifying transactions that use this very common verification logic as safe.

2 Likes

We found another issue with the current state of our proposal using the registry.
The default code as is defined in the current EIP-8141 checks the validity of the transaction with a simple ecrecover versus the EOA address that sent it.
This means that once the EOA has signed the first transaction to initialize the registry, the original public key is exposed, and the default code can be used to authenticate an attacker who stole the original key via quantum computer.
The issue is that the registry must be initialized by someone with signing authority over the EOA, making it impossible to initialize it safely by using ECDSA.

This is similar to what happens in EIP-7702, if you can’t deactivate your original key as EIP-7851 proposes, the whole original account is compromised by having signed one transaction with the EOA key.
If we’re not wrong this goes beyond the scope of our registry proposal, as it means that frame transactions cannot be used to retroactively make EOAs quantum-resistent, as the default code would still make them accessible via ECDSA if implemented as described in the EIP.

Hey guys, I’ve been following this thread and I really like the ideas being explored here. I’m actually working on a PR that addresses a lot of the same issues that you are attempting to address: Update EIP-8141: Allow using by derekchiang · Pull Request #11482 · ethereum/EIPs · GitHub

My goal is to enable accounts (both EOAs and smart accounts) to use precompiles to verify sigs. This extends beyond the current EIP where only EOAs can use precompiles, and with this approach we can remove the default code while retaining the same support for EOAs. The precompiles would read the public key from slot 0 of the account, so key rotation can be done simply by overriding slot 0. Even EOAs can rotate keys by overriding slot 0, presumably by running code via a 7702 delegation.

And I encourage you to take a look at the rationale section, to get a sense of the goals I’m trying to achieve: Update EIP-8141: Allow using by derekchiang · Pull Request #11482 · ethereum/EIPs · GitHub

Edit: updated links to the main EIP repo since I figured out how to stop it from over-merging.

2 Likes