# Recovery (/advanced/account-recovery/sdk-recovery)

> For the complete documentation index, see [llms.txt](/llms.txt)



With Kernel's [permissions system](/smart-accounts/permissions/intro), 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:

<Cards>
  <Card icon="key" title="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.
  </Card>

  <Card icon="vault" title="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.
  </Card>
</Cards>

There are two ways to use recovery: through a pre-built recovery flow or build a totally custom flow using the Kernel recovery plugin.

## Recovery Plugin [#recovery-plugin]

<Callout type="info">
  Impatient?  Check out [complete examples here](https://github.com/zerodevapp/zerodev-examples/tree/main/guardians/recovery.ts).
</Callout>

Here we go through the process of using the recovery plugin:

<div className="fd-steps">
  <div className="fd-step">
    ### Setting up the guardian validator [#setting-up-the-guardian-validator]

    Start by creating a permissions validator.  Let's say you want a single key to be your guardian:

    ```ts
    const guardianSigner = privateKeyToAccount(GUARDIAN_KEY)

    const guardianValidator = await signerToEcdsaValidator(publicClient, {
      signer: guardianSigner,
      entryPoint,
      kernelVersion
    })
    ```

    If you want multiple guardians, set up a [multisig validator](/advanced/multisig) instead.
  </div>

  <div className="fd-step">
    ### Setting up account with the recovery action [#setting-up-account-with-the-recovery-action]

    We have deployed a simple recovery executor that can recover any accounts using [the ECDSA validator](/smart-accounts/permissions/signers/ecdsa).  You can set it up with the following values:

    ```ts
    import { toFunctionSelector } from "viem"

    const recoveryExecutorAddress = '0xe884C2868CC82c16177eC73a93f7D9E6F3A5DC6E'
    const recoveryExecutorFunction = 'function doRecovery(address _validator, bytes calldata _data)'
    const recoveryExecutorSelector = toFunctionSelector(recoveryExecutorFunction)
    ```

    Then, set up the account with the executor:

    ```ts
    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.
  </div>

  <div className="fd-step">
    ### Executing recovery [#executing-recovery]

    After you [construct the account client from the account](/onboarding/create-a-smart-account#create-an-account-client), you can execute recovery as such:

    ```ts
    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],
        })
    })
    ```
  </div>

  <div className="fd-step">
    ### Using account with the new owner [#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](/onboarding/create-a-smart-account#create-a-kernel-account).  For example:

    ```ts
    const account = await createKernelAccount(publicClient, {
     address: "the smart account address",

      // ...other options
    })
    ```
  </div>
</div>
