Alert Source Discuss
⚠️ Draft Standards Track: ERC

ERC-7947: 账户抽象恢复接口

通过自定义恢复提供者恢复智能账户所有权的通用机制。

Authors Artem Chystiakov (@arvolear) <artem@rarilabs.com>
Created 2025-05-07
Discussion Link https://ethereum-magicians.org/t/eip-7947-account-abstraction-recovery-interface-aari/24080

摘要

引入通用的账户抽象恢复机制 recoverOwnership(newOwner, provider, proof) 以及用于智能账户的恢复提供者管理功能,以安全地更新其所有者。

动机

账户抽象和 EOA 的“合约化”是重要的以太坊里程碑,旨在改善链上用户体验和链下安全性。每天涌现出各种各样的智能账户,旨在简化新用户的陡峭入门曲线。最终的智能账户体验是永远不要让他们处理私钥,但仍然允许完全的账户控制和所有权恢复。随着零知识人工智能 (ZKAI) 和零知识双因素身份验证 (ZK2FA) 领域的发展,确定一种通用机制甚至可能为“账户恢复提供商市场”的出现打开大门。

本提案中描述的账户恢复方法允许多个恢复提供商共存并提供各种独特的恢复服务。简而言之,智能账户变成了“恢复提供商聚合器”,使用户无需依赖中心化服务或项目。

账户抽象恢复接口 (AARI) 旨在为任何智能账户定义一个灵活的接口,允许用户主动管理其账户恢复提供商,并在私钥丢失的情况下恢复账户的所有权。

规范

本文档中的关键词“必须”、“不得”、“必需”、“应该”、“不应该”、“推荐”、“可以”和“可选”应按照 RFC 2119 中的描述进行解释。

希望支持 AARI 的智能账户必须实现以下接口:

pragma solidity ^0.8.20;

/**
 * @notice Defines a common account recovery interface for smart accounts to implement.
 * @notice 定义了一个通用的账户恢复接口,供智能账户实现。
 */
interface IAccountRecovery {
    /**
     * MUST be emitted whenever the owner of the account changes as a result 
     * of account recovery (e.g. in the `recoverOwnership` function).
     * MUST 在账户所有者因账户恢复而发生更改时发出(例如,在 `recoverOwnership` 函数中)。
     */
    event OwnershipRecovered(address indexed oldOwner, address indexed newOwner);
    
    /**
     * MUST be emitted whenever a new recovery provider is added to
     * the account (e.g. in the `addRecoveryProvider` function).
     * MUST 在向账户添加新的恢复提供商时发出(例如,在 `addRecoveryProvider` 函数中)。
     */
    event RecoveryProviderAdded(address indexed provider);

    /**
     * MUST be emitted whenever a recovery provider is removed from
     * the account (e.g. in the `removeRecoveryProvider` function).
     * MUST 在从账户中删除恢复提供商时发出(例如,在 `removeRecoveryProvider` 函数中)。
     */
    event RecoveryProviderRemoved(address indexed provider);

    /**
     * @notice A function to add a new recovery provider.
     * @notice 用于添加新的恢复提供商的函数。
     * SHOULD be access controlled.
     * SHOULD 应该是访问控制的。
     * MUST check that `provider` is not `address(0)`.
     * MUST 检查 `provider` 不是 `address(0)`。
     * MUST call `subscribe` on the `provider`.
     * MUST 调用 `provider` 上的 `subscribe`。
     * MUST pass `recoveryData` to the `subscribe` function.
     * MUST 将 `recoveryData` 传递给 `subscribe` 函数。
     * 
     * @param provider the address of a recovery provider (ZKP verifier) to add.
     * @param provider 要添加的恢复提供商(ZKP 验证器)的地址。
     * @param recoveryData custom data (commitment) for the recovery provider.
     * @param recoveryData 恢复提供商的自定义数据(承诺)。
     */
    function addRecoveryProvider(address provider, bytes memory recoveryData) external;

    /**
     * @notice A function to remove an existing recovery provider.
     * @notice 用于删除现有恢复提供商的函数。
     * SHOULD be access controlled.
     * SHOULD 应该是访问控制的。
     * MUST call `unsubscribe` on the `provider`.
     * MUST 调用 `provider` 上的 `unsubscribe`。
     * 
     * @param provider the address of a previously added recovery provider to remove.
     * @param provider 要删除的先前添加的恢复提供商的地址。
     */
    function removeRecoveryProvider(address provider) external;

    /**
     * @notice A view function to check if a provider has been previously added.
     * @notice 用于检查提供商是否已先前添加的视图函数。
     * 
     * @param provider the provider to check.
     * @param provider 要检查的提供商。
     * @return true if the provider exists in the account, false otherwise.
     * @return 如果提供商存在于账户中,则返回 true,否则返回 false。
     */
    function recoveryProviderAdded(address provider) external view returns (bool);

    /**
     * @notice A non-view function to recover ownership of a smart account.
     * @notice 用于恢复智能账户所有权的非视图函数。
     * MUST check that `provider` exists in the account.
     * MUST 检查 `provider` 是否存在于账户中。
     * MUST call `recover` on the `provider`.
     * MUST 调用 `provider` 上的 `recover`。
     * MUST update the account owner to `newOwner` if `proof` verification succeeds.
     * MUST 如果 `proof` 验证成功,则将账户所有者更新为 `newOwner`。
     * MUST return `true` if the ownership recovery is successful.
     * MUST 如果所有权恢复成功,则返回 `true`。
     * 
     * @param newOwner the address of a new owner.
     * @param newOwner 新所有者的地址。
     * @param provider the address of a recovery provider.
     * @param provider 恢复提供商的地址。
     * @param proof an encoded proof of recovery (ZKP/ZKAI, signature, etc).
     * @param proof 恢复的编码证明(ZKP/ZKAI、签名等)。
     * @return `true` if recovery is successful, `false` (or revert) otherwise.
     * @return 如果恢复成功,则返回 `true`,否则返回 `false`(或 revert)。
     */
    function recoverOwnership(
        address newOwner,
        address provider,
        bytes memory proof
    ) external returns (bool);
}

恢复提供商必须实现以下接口:

/**
 * @notice Defines a common recovery provider interface.
 * @notice 定义了一个通用的恢复提供商接口。
 */
interface IRecoveryProvider {
    /**
     * MUST be emitted whenever a new account subscribes to
     * the recovery provider (e.g. in the `subscribe` function).
     * MUST 在新账户订阅恢复提供商时发出(例如,在 `subscribe` 函数中)。
     */
    event AccountSubscribed(address indexed account);

    /**
     * MUST be emitted whenever an account unsubscribes from
     * the recovery provider (e.g. in the `unsubscribe` function).
     * MUST 在账户取消订阅恢复提供商时发出(例如,在 `unsubscribe` 函数中)。
     */
    event AccountUnsubscribed(address indexed account);

    /**
     * @notice A function that "subscribes" a smart account (msg.sender) to a recovery provider.
     * @notice 一个将智能账户 (msg.sender)“订阅”到恢复提供商的函数。
     * SHOULD process and assign the `recoveryData` to the `msg.sender`.
     * SHOULD 处理并将 `recoveryData` 分配给 `msg.sender`。
     * 
     * @param recoveryData a recovery commitment (hash/ZKP public output) to be used 
     * @param recoveryData 用于在 `recover` 函数中使用的恢复承诺(哈希/ZKP 公共输出)
     * in the `recover` function to check a recovery proof validity.
     * 用于检查恢复证明的有效性。
     */
    function subscribe(bytes memory recoveryData) external;

    /**
     * @notice A function that revokes a smart account subscription.
     * @notice 一个撤销智能账户订阅的函数。
     * MUST delete all the recovery data associated with the `msg.sender`.
     * MUST 删除与 `msg.sender` 关联的所有恢复数据。
     */
    function unsubscribe() external;

    /**
     * @notice A function to get a recovery data (commitment) of an account.
     * @notice 用于获取账户的恢复数据(承诺)的函数。
     * 
     * @param account the account to get the recovery data of.
     * @param account 要获取恢复数据的账户。
     * @return the associated recovery data.
     * @return 关联的恢复数据。
     */
    function getRecoveryData(address account) external view returns (bytes memory);

    /**
     * @notice A function that checks if a recovery of a smart account (msg.sender)
     * @notice 一个检查智能账户 (msg.sender) 恢复到 `newOwner` 是否可能的函数。
     * to the `newOwner` is possible.
     * SHOULD use `msg.sender`'s `recoveryData` to check the `proof` validity.
     * SHOULD 使用 `msg.sender` 的 `recoveryData` 来检查 `proof` 的有效性。
     * MUST ensure that the `proof` can't be reused, e.g. update nonce.
     * MUST 确保 `proof` 不能被重用,例如,更新 nonce。
     * 
     * @param newOwner the new owner to recover the `msg.sender` ownership to.
     * @param newOwner 用于恢复 `msg.sender` 所有权的新所有者。
     * @param proof the recovery proof.
     * @param proof 恢复证明。
     */
    function recover(address newOwner, bytes memory proof) external;
}

理由

预计 AARI 将与任何账户抽象标准配合使用,以实现最大的账户恢复灵活性。无论是 EIP-4337 还是 EIP-7702,特定的智能账户提供商都可以通过简单地实现一个通用接口来支持账户恢复。

由于整个账户恢复过程只不过是证明了解某个替代密钥而不是私钥,因此账户能够“承诺”此密钥至关重要。恢复提供商接口中的 subscribe 函数允许精确地执行此操作。此外,如果在某个时间点用户想要“重新承诺”到新的密钥(由于安全原因),他们可以多重调用 unsubscribe + subscribe 函数来实现所需的结果。

向后兼容性

此 EIP 完全向后兼容。

安全考虑

有几个安全问题需要指出:

  • 由智能账户开发者来正确访问控制 addRecoveryProviderremoveRecoveryProvider 函数。
  • 智能账户用户可能会被“钓鱼”,从而向他们的账户添加恶意恢复提供商。在这种情况下,恢复提供商可以通过接受虚假的恢复证明来获得对账户的完全控制权。

版权

版权和相关权利通过 CC0 放弃。

Citation

Please cite this document as:

Artem Chystiakov (@arvolear) <artem@rarilabs.com>, "ERC-7947: 账户抽象恢复接口 [DRAFT]," Ethereum Improvement Proposals, no. 7947, May 2025. [Online serial]. Available: https://eips.ethereum.org/EIPS/eip-7947.