This ERC proposes a standard interface for social recovery of smart contract accounts. It separates identity and policy verification from the recovery process, allowing more ways to authenticate (known as Guardians) than just on-chain accounts. It also lets users customize recovery policies without changing the account’s smart contract.
Vitalik Buterin has long advocated for social recovery as an essential tool for user protection within the crypto space. He posits that the value of this system rests in its ability to offer users, especially those less acquainted with the technicalities of cryptography, a robust safety net when access credentials are lost. By entrusting account recovery to a network of selected individuals or entities, dubbed "Guardians," users gain a safeguard against the risk of losing access to their digital assets.
In essence, social recovery operates by verifying the identity of the user and the chosen Guardians, and then considering a set of their signatures. Should the validated signatures reach a specified threshold, account access is reestablished. This system is equipped to enforce complex policies, such as necessitating signatures from particular Guardians or reaching signature thresholds from different Guardian categories.
To overcome these limitations, this Ethereum Improvement Proposal (EIP) introduces a novel, customizable social recovery interface standard. This standard decouples identity and recovery policy verification from the recovery procedure itself, thereby enabling an independent, versatile definition and extension of both. This strategy accommodates a wider range of Guardian types and recovery policies, thereby offering users the following benefits:
This approach enables users to customize recovery policies without the need to change the smart contract of the account itself.
The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "NOT RECOMMENDED", "MAY", and "OPTIONAL" in this document are to be interpreted as described in RFC 2119 and RFC 8174.
This EIP consists of four key concepts:
TypesAndDecodersThis defines the necessary data types required by this interface standard.
The Identity structure represents various types of guardians. The process of identity verification is as follows:
signer value in the declared entity is empty, this implies that the Identity entity is of EOA/SCA account type. In this case, guardianVerifier address should be the address of EOA/SCA (the actual signer). For permission verification of this Identity entity, it is recommended to utilize a secure library or built-in function capable of validating both ECDSA and ERC-1271 signatures. This helps in preventing potential security vulnerabilities, such as signature malleability attacks.signer value in the declared entity is non-empty, this suggests that the Identity entity is of non-account type. In this case, permission verification can be accomplished by calling guardianVerifier address contract instance through IPermissionVerifier interface.IPermissionVerifierThe Guardian Permission Verification Interface. Implementations MUST conform to this interface to enable identity verification of non-account type guardians.
IRecoveryPolicyVerifierThe Recovery Policy Verification Interface. Implementations MAY conform to this interface to support verification of varying recovery policies. RecoveryPolicyVerifier is optional for SocialRecoveryInterface.
The verifyRecoveryPolicy() function is designed to validate whether the provided list of Permissions abides by the specified recovery properties (properties). This function has the following constraints and effects: For each matched guardian, calculations are made according to the corresponding property in the properties list (e.g., accumulating weight, distinguishing role while accumulating, etc.).
These constraints ensure that the provided guardians and properties comply with the requirements of the recovery policy, maintaining the security and integrity of the recovery process.
IRecoveryAccountThe Smart Contract Account MAY implement the IRecoveryAccount interface to support social recovery functionality, enabling users to customize configurations of different types of Guardians and recovery policies. In the contract design based on Module, the implementation of RecoveryModule is very similar to RecoveryAccount, except that different accounts need to be distinguished and isolated.
Guardian's signable message, it SHOULD employ EIP-712 type signature to ensure the content of the signature is readable and can be confirmed accurately during the Guardian signing process.getRecoveryNonce() SHOULD be separated from nonces associated with account asset operations, as social recovery is a function at the account layer.Note: This workflow is presented as an illustrative example to clarify the coordinated usage of the associated interface components. It does not imply a mandatory adherence to this exact process.
A user sets up a recoveryPolicyConfigA within his RecoveryAccount:
When GuardianA and GuardianB assist the user in performing account recovery, they are to confirm the EIP-712 structured data for signing, which might look like this:
In this step, the guardians need to confirm that the domain separator's verifyingContract is the correct RecoveryAccount address for the user, the contract name, version, and chainId are correct, and the policyVerifier and newOwners fields in the message part match the user's provided data.
The msgHash is then composed of:
msgHash = keccak256("\\x19\\x01" + domainSeparatorV4() + dataHash)Where,
dataHash = keccak256(EXECUTE_RECOVERY_TYPEHASH + configIndex + keccak256(bytes(newOwners)) + getRecoveryNonce())EXECUTE_RECOVERY_TYPEHASH = keccak256("StartRecovery(address configIndex, bytes newOwners, uint256 nonce)")The guardians sign this hash to obtain the signature:
signature = sign(msgHash)The permission is then constructed as:
permission = guardian + signatureOnce each Guardian has generated their unique permission, all these individual permissions are collected to form permissions:
permissions= [guardianA+signature, guardianB+signature, ...]
The permissions is an array that consists of all the permissions of the Guardians who are participating in the recovery process.
A bundler or another relayer service calls the RecoveryAccount.startRecovery(0xA, newOwners, permissions) function.
startRecovery() function's processing logic is as follows:
msgHash) from the input parameters 0xA, newOwners and internally generated EIP-712 signature parameters and RecoveryNonce.guardian and corresponding signature from the input parameters permissions and process them as follows:
guardianA.signer is non-empty (Identity A), call IPermissionVerifier(guardianVerifier1).isValidPermissions(signerA, msgHash, permissionA.signature) to validate the signature.guardianA.signer is empty (Identity B), call the internal function SignatureChecker.isValidSignatureNow(guardianVerifier2, msgHash, permissionB.signature) to validate the signature.After successful verification of all guardians signatures, fetch the associated config data for policyVerifier address 0xA and call IRecoveryPolicyVerifier(0xA).verifyRecoveryPolicy(permissions, properties). The function verifyRecoveryPolicy() performs the following checks:
Note that the guardians parameter in the function refers to the guardians whose signatures have been successfully verified.
guardians (Identity A and B) are present in config.guardianInfos list and are unique.property values of guardians (30 + 30 = 60).config.thresholdConfigs.threshold ,the result is more than the first element (threshold: 50, lockPeriod: 24 hours) but less than the second element (threshold: 100, lockPeriod: ""), the validation is successful, and the lock period of 24 hours is returned.The RecoveryAccount saves a temporary state {newOwners, block.timestamp + 24 hours} and increments RecoveryNonce. A RecoveryStarted event is emitted.
After the expiry time, anyone (usually a relayer) can call RecoveryAccount.executeRecovery() to replace newOwners, remove the temporary state, complete the recovery, and emit a RecoveryExecuteed event.
A primary design rationale for this proposal is to extend a greater diversity of Guardian types and more flexible, customizable recovery policies for a RecoveryAccount. This is achieved by separating the verification logic from the social recovery process, ensuring that the basic logic of the account contract remains unaltered.
The necessity of incorporating Verifiers from external contracts arises from the importance of maintaining the inherent recovery logic of the RecoveryAccount. The Verifiers's logic is designed to be simple and clear, and its fixed invocation format means that any security risks posed by integrating external contracts can be effectively managed.
The recoveryConfigs are critical to the RecoveryAccount and should be securely and effectively stored. The access and modification permissions associated with these configurations must be carefully managed and isolated to maintain security. The storage and quantity of recoveryConfigs are not limited to ensure the maximum flexibility of the RecoveryAccount's implementation.
The introduction of recoveryNonce into the RecoveryAccount serves to prevent potential replay attacks arising from the malicious use of Guardian's permissions. The recoveryNonce ensures each recovery process is unique, reducing the likelihood of past successful recovery attempts being maliciously reused.
No backward compatibility issues are introduced by this standard.
TBD.
Needs discussion.
Copyright and related rights waived via CC0.