EIP-7851: Deactivate/Reactivate a Delegated EOA's Key

Discussion topic for EIP-7851

Update Log

External Reviews

None as of 2024-12-27.

Outstanding Issues

None as of 2024-12-27.

3 Likes

Strong thanks to @jochem-brouwer and @thegaram33 for the valuable reviews of the draft PR.

Here’s a summary of some open discussions for broader visibility:

  1. Extra Storage Read During Transaction Validation
    This EIP introduces an account code read during transaction validation when txpool is adding new transactions as noted in this discussion. Alternatives include:

    • Adding a new Boolean field in the account state.
    • Encoding the “active/deactivated” status into the nonce.
  2. Concerns About Reactivation
    Concerns (e.g., comment link) that users might not keep their private keys secure after deactivation. Possible solutions:

    • Users need to keep and back up their private keys as they used to. Nothing changes after they are deactivated since the main purpose is safeguarding the delegated EOA in one chain instead of deactivating the private key globally in a multi-EVM-compatible chains ecosystem.
    • Not supporting private key reactivation.
    • Allowing redelegation through a precompiled contract instead of supporting private key reactivation.
  3. Permit Extension
    The permit extension concern is mentioned in the relevant section of this EIP and also in this X post. Possible solutions:

    • Modify ecRecover precompile to check the deactivated status and if the recovered address is deactivated: return a precompile contract error (or, if not adding an error return, return a zero address or a designated magic address).
    • Trace transactions and check if the Permit function is invoked, if so, check the signer’s deactivated status, this solution would like to introduce a heavy check for clients.
    • The contracts upgrade the implementation and deactivate the Permit function. However, some ERC-20 contracts cannot be upgraded.
2 Likes

I believe another issue that needs to be addressed is the behavior of ecrecover, specifically expected behavior should be that it doesn’t work anymore if the pk is deactivated, right?

1 Like

Interesting. also have considered this, This method also sounds promising to address the Permit Extension issue listed above. since Permit usually utilizes ecrecover to verify EOA’s signature. while when I first thought of changing the behavior of ecrecover, it may be a bit unintuitive since this precompile does not do a “single job” (signature recovery) anymore. not sure. it’s worth discussing. so you think it’s more natural to consider the “deactivated” status in ecrecover? any considerations?

btw, I added the possible solutions in the previous Permit Extension issue session.

1 Like

yes I definitely agree on this making ecrecover more complex (and stateful). however, to me relying on contracts to implement correct behaviour (ie checking codesize and doing 1271 before ecrecover) feels hacky and not like a fully complete solution

1 Like

Totally agree with @kopykat here! Definitely think it would be worthwhile to restrict EOA signatures as without it, an attacker could work around this EIP.

3 Likes

I am not sure this has to be addressed. Anyone can implement ECDSA signature verification natively in Solidity. Yes, this would be more expensive, but changing ecrecover behavior introduces a leaky abstraction that doesn’t fix the problem completely.


Nevertheless, the deactivation concept sounds really cool to me as it relaxes the “god mode” access of delegated multisigs.

1 Like

yes this is a good point. you’re completely right that there’s no way to modify ECDSA to conform to this behavior.

however, I understand this proposal to be about making it possible to activate/deactivate a private key from the perspective of the EVM. currently, this includes mainly transactions (with the exception of addressing permit-based systems), but to me it feels like this change should also address any out-of-the-box features the EVM provides for ECDSA operations, namely ecrecover.

You know, ecrecover still accepts signatures with S values from both halves of the curve, while transaction can only be sent with S <= N / 2 (EIP-2). So this distinction has already been done before :slight_smile:.

1 Like

I merged a new PR based on some newly found fixes, recent EIP-7702 updates, and discussions in this thread, summarization of changes is as follows:

  • Adding fact fixes in the “Additional Transaction Validation Overhead” section, because due to EIP-3607 and EIP-7702, there is already a code loading operation during transaction validation before executing the transaction, so this EIP introduces no additional code loading in this step. This EIP only introduces an extra code read when the transaction pool is validating a transaction to be added to the pool, narrowing DoS attack vectors.
  • Changing PRECOMPILE_GAS_COST from 5000 to 13000, and adding gas cost decomposition of PRECOMPILE_GAS_COST.
  • Adding more details and potential solutions in the “Contracts Using ECDSA Secp256k1 Signatures” section, aligning with the discussion in this thread.
  • Adding “how a contract can check the deactivation status of private key” as it is now doable without adding a new opcode, based on the latest change of EXTCODESIZE and EXTCODECOPY in EIP-7702.
  • Removing “delegating to malicious wallet implementations” related discussions, as it is in the scope of EIP-7702, instead of this EIP.
  • Adding “replaying the same authorization” discussions in the “Deactivation and Reactivation Replay” section.
  • Rephrases, section restructures and code refactors.
2 Likes

There is a motivation for this EIP in the context of Post Quantum crypto. If one can deactivate its eoA prior to Quantum computing, then 7702 can be used for PQ migration. Otherwise it is possible for the quantum attacker to take control of the account via the EOA. This include the ‘Keyless’ Nicks technique, where quantum computing can recover the private key, which is impossible when ECDLP holds.

We used 7702 delegation to FALCON for testing purpose, but it has no real meaning while 7851 is not enforced.

1 Like

It solves some of the issues for PQ but not all of them because of the possibility of signing messages using the EOA and using them in any contract that does not check ERC-1271 signatures first. So you are only quantum secure against contracts that also apply a flow that is compatible. Is there an ERC that enforces this mechanism today? If not, then maybe EIP-7851 needs a companion ERC that will do the following flow:

  1. If contract code exists, check 1271 signature only
  2. Otherwise, check ecRecover on address
    With these 2 things you might be able to operate in a pq protected environment by only signing proper 712 messages.

Maybe also something can be done to identify compatible 712 messages using the domain separator or something like that

1 Like

Thanks for the feedback from practice. Yeah, that’s one of the motivations of this EIP, will add it explicitly in the next refinement.

Thanks. It’s a valid concern and good suggestion. From my point of view, no matter the signature types. e.g. EIP-712, ERC-1271, etc. A new ERC can be added to support signature verification based on the EOA private key’s active/inactive statuses (may not be mandatory, but providing compatibility support). e.g., for ERC-1271, when it comes to an ECDSA signature, the contract should check the status of this EOA private key first (EIP-7851 supports on-chain checks by checking EXTCODESIZE of the address), such checks are not mandatory, they can be enabled by a flag in the signer list of the contract, based on the contract’s actual use scenario.

For the off-chain services, this EIP also provides a way to check if the private key is disabled or not. They can also add optional hooks before signature validation based on security considerations.

Another issue is that there are some ERC20 contracts which support ERC-2612, the permit function. e.g., DAI. The ERC to support EIP-7851 above cannot add checks in existing contracts (if they cannot be upgraded). One aggressive method is to modify the ecrecover precompile to check the private key’s activation status first. Some pushbacks are: (i) this will make this precompile stateful; (ii) this still cannot defend cases where ECDSA signature verification is implemented in other methods, e.g., self-implemented by Solidity. Thus I’m still hesitant if it’s proper to add this change into this EIP.

Yes, and this is better that no contract at all.

For now not having the ability to deactivate means all effort in this direction are meaningless.

Hi all — I’ve opened an update PR for EIP-7851 to reflect a design change toward delayed, irreversible ECDSA key deactivation (PR: Update EIP-7851: Move to Draft by colinlyguo · Pull Request #11316 · ethereum/EIPs · GitHub ). This is based on previous discussions in this Magicians thread, as well as recent conversations with @nicocsgy, incorporating some new context and ideas from PQ team.

This update changes EIP-7851 from a deactivate/reactivate precompile (encoding status via a trailing byte on the 7702 delegation designator) to an irreversible ECDSA key deactivation with a 7-day delay. Concretely: reactivation is removed to preserve post-quantum security guarantees (allowing an ECDSA key to come back would weaken the goal), and deactivation is no longer instant, it is scheduled with a 7-day cancellation window during which the current ECDSA key can call cancel() to prevent accidental or malicious lockout before finalization.

Because the delay requires storing a per-account finalizationTimestamp, the design moves from a precompile to a system contract. Compared to other minimalist designs, for example, (i) adding an account-state field (managed by a precompile), which would require complicated and error-prone RLP/p2p changes, and (ii) relying on a precompile, which has no natural storage mechanism. A system contract (following the EIP-4788 / EIP-2935 / EIP-7002 pattern) with interfaces deactivate/cancel/status as a single on-chain source of truth is more implementation-friendly and self-explanatory, and likely more backward-compatible.

About ecrecover for legacy immutable, non-upgradable contracts: to keep concerns separated, EIP-7851 itself does not depend on changing ecrecover. I opened a companion draft EIP to explore making ecrecover respect private-key deactivation status (for contracts relying on ECDSA signatures), here: EIP-8151: Private Key Deactivation Aware ecRecover - #4 by bbjubjub .

1 Like

Thank you, I haven’t fully reviewed your draft yet, but I think we could trade the benefit of a delay for a more unified mechanism. EIP-7819 introduces a code-based authorization structure, which allows contracts to use the 7702 authorization indicator as a minimal upgradeable proxy. By connecting the ECDSA disabling of this proposal and EIP-7819, we will have a pipeline linking the two designs together.
My idea is as follows: We will use an identifier to recognize the ECDSA disabling, such as ef0101. All addresses using the SETDELEGATE opcode will switch to this identifier if it is an empty account or an EIP-7702 indicator or this identifier. No additional delays are being added here as we’ll be moving to code-based implementation; however, EIP-8141 will most likely be added in the Hegota update, making this process seamless. We accept skipping the waiting time because EIP-7702 has given us time to do so.

Thanks for the insights. I think that even if we go with the current design, it doesn’t necessarily conflict with EIP-7819. EIP-7819 can still serve as the wallet-side code-based upgradeability pipeline, while EIP-7851 focuses purely on defining protocol-level ECDSA validity once deactivation is finalized.

Consequently, to me, the fundamental trade-off here boils down to: The 7-day grace period (UX/Safety) vs. A unified code-based mechanism.

The 7-day delay is primarily an operational safety buffer for the 7702-to-PQ migration flow. To keep this buffer, we have to minimally introduce a state read (e.g., a system contract for the timestamp) in validation steps of block building, 7702 authorizations and mempool checks.

The code-based approach (either using the original 7851’s append 0x00 or the ef0101/ef01ef identifier, these are details of leaving 3rd byte of code field for other use cases or reusing it) can only introduce extra state read in mempool and reuse account state read of 7702 in block building and 7702 authorizations, but as you mentioned, it means we explicitly trade away this 7-day safety consideration. The minimal change to switch toward code-based approach would be “cancel reactivation”.

I might be wrong or miss something above. Would like to hear your thoughts and more input.

Thank you for your feedback. I think setting up code 7702 and then waiting until the user decides to cancel the private key is also an approach, although the user operation might be a bit more complex. However, in return, we obtain a unified path to the smart account regardless of the implementation method (EOA, CREATE/CREATE2, etc.). The general trend in the network will be to phase out ECDSA in favor of PQ, and 7702 has given us that transition period, so the next step should be a choice between using or not using ECDSA anymore. Your contract-based approach may become outdated in the future as most wallets have switched to PQ, while upgrades via code will continue to play a crucial role even if ECDSA disappears.
The choice of specific delegated identifiers will need further discussion, but I expect them to be the same in both the contract and the EOA that has canceled the private key.

Thanks for your reply. A clarification: I’ve evaluated both minimal approaches (code-based approach as the initial draft vs. system contract-based approach in the refactored version). And I’ve documented both so that there is sufficient information on “design readiness” to discuss.

Regarding the claim: “contract-based approach may become outdated in the future as most wallets have switched to PQ, while upgrades via code will continue to play a crucial role even if ECDSA disappears”, I don’t think I agree because the system contract also provides a status check. The motivation for using a system contract is that alternative approaches: (i) adding an account-state field, or (ii) introducing an unprecedented stateful precompile (not read-only), seem significantly more complex to implement.

Also, checking the deactivation status of an account by querying the system contract’s status() or by querying EXTCODESIZE, in my opinion, neither method is inherently tied to “upgrades via code will continue to play a crucial role even if ECDSA disappears”, both approaches simply offer a way to check the deactivation status of a private key, which enables integration with the upgrade toolkit of EIP-7702 + EIP-8141. So I’m not sure where the “outdated” characterization comes from. Could you elaborate?

So the fundamental trade-off would be “7-day delay” vs. “extra storage read + status check gas difference + dapp integration difference + etc” as mentioned here: EIP-7851: Deactivate/Reactivate a Delegated EOA's Key - #18 by colinlyguo

That said, I completely agree that a unified code-based path offers certain practical conveniences, such as unified DApp integration and tooling implementation. I would love to hear more feedback from the community on how to weigh these trade-offs.