Recovery
With Kernel's permissions system, it's possible to set up a guardian (or multiple guardians) for a smart account, so that if the owner loses their key, the guardian(s) can recover the key for the owner.
There are two typical types of recovery:
-
Self-recovery: your user can set up recovery for their account with another auth factor they own, such as a passkey or another wallet they own.
-
DApp-assisted recovery: your user might set you (the DApp) as their guardian. When they lose their account, they would contact you and you would recover the account for them.
There are two ways to use recovery: through a pre-built recovery flow or build a totally custom flow using the Kernel recovery plugin.
Pre-built Recovery Flow
Check out the recovery flow docs.
Recovery Plugin
Here we go through the process of using the recovery plugin:
Setting up the guardian validator
Start by creating a permissions validator. Let's say you want a single key to be your guardian:
const guardianSigner = privateKeyToAccount(GUARDIAN_KEY)
const guardianValidator = await signerToEcdsaValidator(publicClient, {
signer: guardianSigner,
entryPoint,
kernelVersion
})
If you want multiple guardians, set up a multisig validator instead.
Setting up account with the recovery action
We have deployed a simple recovery executor that can recover any accounts using the ECDSA validator. You can set it up with the following values:
import { toFunctionSelector } from "viem"
const recoveryExecutorAddress = '0x2f65dB8039fe5CAEE0a8680D2879deB800F31Ae1'
const recoveryExecutorFunction = 'function doRecovery(address _validator, bytes calldata _data)'
const recoveryExecutorSelector = toFunctionSelector(recoveryExecutorFunction)
Then, set up the account with the executor:
const account = await createKernelAccount(publicClient, {
entryPoint,
kernelVersion,
plugins: {
sudo: sudoValidator,
regular: guardianValidator,
action: {
address: recoveryExecutorAddress,
selector: recoveryExecutorSelector,
},
}
})
you only need to set the sudo validator if you are enabling the guardian validator, i.e. that it's the first time you are using the guardian.
Executing recovery
After you construct the account client from the account, you can execute recovery as such:
import { encodeFunctionData } from "viem"
import { ECDSA_VALIDATOR_ADDRESS } from "@zerodev/ecdsa-validator"
const userOpHash = await kernelClient.sendUserOperation({
callData: encodeFunctionData({
abi: parseAbi([recoveryExecutorFunction]),
functionName: 'doRecovery',
args: [ECDSA_VALIDATOR_ADDRESS, newSigner.address],
})
})
Using account with the new owner
After you update the account owner, the account address can no longer by computed from the new owner. Therefore, you should use the address
option to manually set the account address when you create the account object. For example:
const account = await createKernelAccount(publicClient, {
address: "the smart account address",
// ...other options
})