Skip to content

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
})