EIP-7851 - Code-Controlled EOA Delegation

Created 2024-12-27
Status Draft
Category Core
Type Standards Track
Authors
Requires

Abstract

This EIP extends EIP-7702 with an ECDSA-disabled delegation prefix 0xef0101 and a self-only opcode SETSELFDELEGATE. EIP-7702 bootstraps delegation by writing 0xef0100 || delegate_address through the original EOA key. Delegated wallet code can then call SETSELFDELEGATE to write 0xef0101 || delegate_address, permanently disabling residual ECDSA authority while preserving code-controlled delegate updates.

Motivation

EIP-7702 bootstraps delegation with the original EOA key, but after control has moved into wallet code, users may operate the account through the wallet code itself. This EIP lets wallet code control the delegation lifecycle and burn residual ECDSA authority.

Specification

|| denotes byte concatenation.

0xef0100 || delegate_address is an ECDSA-enabled delegation, and 0xef0101 || delegate_address is an ECDSA-disabled delegation. ECDSA-disabled means the original ECDSA key can no longer authorize transactions or EIP-7702 delegation changes. It does not mean the delegate target is frozen forever: wallet code is capable of updating the delegate while staying ECDSA-disabled. The irreversible invariant is that once ECDSA authority is disabled, it can never be restored.

Parameters

Parameter Value
SETSELFDELEGATE_OPCODE TBD
SETSELFDELEGATE_GAS 9500

Delegated Code Execution

Clients must treat 0xef0101 || delegate_address identically to 0xef0100 || delegate_address for delegated code execution.

SETSELFDELEGATE

SETSELFDELEGATE(delegate_address) takes one stack item. The low 160 bits of the stack item are interpreted as delegate_address.

Before execution:

[..., delegate_address]

After execution:

[..., success]

success is 1 on success and 0 when no state change is made.

The opcode costs SETSELFDELEGATE_GAS for each execution attempt.

If executed in a static context, SETSELFDELEGATE must cause an exceptional halt.

Let authority be the current execution-context address. Let code be the raw account code stored in state for authority, not the resolved delegated code currently being executed. A successful update affects only future delegated-code resolution; it does not change the code executing in the current frame.

SETSELFDELEGATE is self-only. It must not accept a target account and must not modify any account other than authority.

State changes made by SETSELFDELEGATE follow normal EVM revert semantics. If the frame or transaction reverts, the delegation update reverts.

Execution proceeds as follows:

  1. If delegate_address == address(0), push 0 and make no state change.
  2. If code is exactly 23 bytes long and starts with either 0xef0100 or 0xef0101, set code(authority) = 0xef0101 || delegate_address and push 1.
  3. Otherwise, push 0 and make no state change.

Calling SETSELFDELEGATE from an ECDSA-enabled delegation disables ECDSA authority and sets the delegate. Calling it from an ECDSA-disabled delegation redelegates while keeping ECDSA authority disabled.

Validation

During EIP-7702 authorization processing, if authority currently has code that is exactly 23 bytes long and starts with 0xef0101, any authorization signed by authority must be considered invalid and skipped.

An ECDSA-authenticated transaction whose recovered sender has code that is exactly 23 bytes long and starts with 0xef0101 must not be included in a block. Transaction pools must reject such transactions.

Rationale

EIP-7702 bootstraps delegation with the original EOA key. After bootstrap, the account may be controlled through wallet code, passkeys, multisig, social recovery, or modules. The ECDSA-disabled lifecycle should therefore be available from the delegated account's execution path.

SETSELFDELEGATE moves this decision into wallet code. The first successful call permanently disables residual ECDSA authority. Later calls may update the delegate, but always remain ECDSA-disabled. The permanent property is not that the delegate target is frozen forever; the permanent property is that residual ECDSA authority is disabled forever.

SETSELFDELEGATE_GAS is 9500, equal to PER_AUTH_BASE_COST from EIP-7702 minus the 3000 gas attributed to recovering the authority address. The opcode writes one 23-byte delegation indicator for the current execution-context account after delegation has already resolved, and does not verify a signature, process an authorization tuple, increment the account nonce, or touch another account.

Backwards Compatibility

Existing 0xef0100 || delegate_address delegations are unchanged. Clients that implement this EIP must recognize 0xef0101 || delegate_address as a delegation for execution and as an ECDSA-disabled authority for validation.

Security Considerations

Entering ECDSA-disabled delegation is irreversible with respect to ECDSA authority. The original EOA key can never restore ECDSA authority after 0xef0101 is set.

Wallet code can still update the delegate while remaining ECDSA-disabled. Wallets should expose SETSELFDELEGATE only after explicit user confirmation and treat it as the highest privilege.

The execution load change is small. Execution paths that already resolve delegated code can reuse the existing delegation-code lookup. Transaction pools may need one additional account-code read for the sender to reject ECDSA-authenticated transactions from ECDSA-disabled authorities.

This EIP only invalidates protocol-level ECDSA-authenticated transactions and EIP-7702 authorizations. Contracts that verify ECDSA signatures directly, such as token permit functions, will not automatically reject signatures from an ECDSA-disabled authority. For addressing the behavior of the ecrecover precompile with ECDSA-disabled authorities, see companion proposal EIP-8151.

Copyright

Copyright and related rights waived via CC0.