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

# Perform executions on a smart account's behalf

[Delegation](/smart-accounts-kit/1.0.0/concepts/delegation/overview/) is the ability for a [MetaMask smart account](/smart-accounts-kit/1.0.0/concepts/smart-accounts/) to grant permission to another account to perform executions on its behalf.

In this guide, you'll create a delegator account (Alice) and a delegate account (Bob), and grant Bob permission to perform executions on Alice's behalf. You'll complete the delegation lifecycle (create, sign, and redeem a delegation).

## Prerequisites[​](#prerequisites "Direct link to Prerequisites")

[Install and set up the Smart Accounts Kit.](/smart-accounts-kit/1.0.0/get-started/install/)

## Steps[​](#steps "Direct link to Steps")

### 1. Create a Public Client[​](#1-create-a-public-client "Direct link to 1. Create a Public Client")

Create a [Viem Public Client](https://viem.sh/docs/clients/public) using Viem's `createPublicClient` function. You will configure Alice's account (the delegator) and the Bundler Client with the Public Client, which you can use to query the signer's account state and interact with smart contracts.

```
import { createPublicClient, http } from 'viem'
import { sepolia as chain } from 'viem/chains'

const publicClient = createPublicClient({
  chain,
  transport: http(),
})

```

### 2. Create a Bundler Client[​](#2-create-a-bundler-client "Direct link to 2. Create a Bundler Client")

Create a [Viem Bundler Client](https://viem.sh/account-abstraction/clients/bundler) using Viem's `createBundlerClient` function. You can use the bundler service to estimate gas for user operations and submit transactions to the network.

```
import { createBundlerClient } from 'viem/account-abstraction'

const bundlerClient = createBundlerClient({
  client: publicClient,
  transport: http('https://your-bundler-rpc.com'),
})

```

### 3. Create a delegator account[​](#3-create-a-delegator-account "Direct link to 3. Create a delegator account")

Create an account to represent Alice, the delegator who will create a delegation. The delegator must be a MetaMask smart account; use the toolkit's [toMetaMaskSmartAccount](/smart-accounts-kit/1.0.0/reference/smart-account/#tometamasksmartaccount) method to create the delegator account.

A Hybrid smart account is a flexible smart account implementation that supports both an externally owned account (EOA) owner and any number of P256 (passkey) signers. This examples configures a [Hybrid smart account](/smart-accounts-kit/1.0.0/guides/smart-accounts/create-smart-account/#hybrid-smart-account) with an Account signer:

```
import { Implementation, toMetaMaskSmartAccount } from '@metamask/smart-accounts-kit'
import { privateKeyToAccount } from 'viem/accounts'

const delegatorAccount = privateKeyToAccount('0x...')

const delegatorSmartAccount = await toMetaMaskSmartAccount({
  client: publicClient,
  implementation: Implementation.Hybrid,
  deployParams: [delegatorAccount.address, [], [], []],
  deploySalt: '0x',
  signer: { account: delegatorAccount },
})

```

note

See [how to configure other smart account types](/smart-accounts-kit/1.0.0/guides/smart-accounts/create-smart-account/).

### 4. Create a delegate account[​](#4-create-a-delegate-account "Direct link to 4. Create a delegate account")

Create an account to represent Bob, the delegate who will receive the delegation. The delegate can be a smart account or an externally owned account (EOA):

- Smart account
- EOA

```
import { Implementation, toMetaMaskSmartAccount } from '@metamask/smart-accounts-kit'
import { privateKeyToAccount } from 'viem/accounts'

const delegateAccount = privateKeyToAccount('0x...')

const delegateSmartAccount = await toMetaMaskSmartAccount({
  client: publicClient,
  implementation: Implementation.Hybrid, // Hybrid smart account
  deployParams: [delegateAccount.address, [], [], []],
  deploySalt: '0x',
  signer: { account: delegateAccount },
})

```

```
import { privateKeyToAccount } from 'viem/accounts'
import { sepolia as chain } from 'viem/chains'
import { createWalletClient, http } from 'viem'

const delegateAccount = privateKeyToAccount('0x...')

export const delegateWalletClient = createWalletClient({
  account: delegateAccount,
  chain,
  transport: http(),
})

```

### 5. Create a delegation[​](#5-create-a-delegation "Direct link to 5. Create a delegation")

Create a [root delegation](/smart-accounts-kit/1.0.0/concepts/delegation/overview/#root-delegation) from Alice to Bob. With a root delegation, Alice is delegating her own authority away, as opposed to _redelegating_ permissions she received from a previous delegation.

Use the toolkit's [createDelegation](/smart-accounts-kit/1.0.0/reference/delegation/#createdelegation) method to create a root delegation. When creating delegation, you need to configure the scope of the delegation to define the initial authority.

This example uses the [erc20TransferAmount](/smart-accounts-kit/1.0.0/guides/delegation/use-delegation-scopes/spending-limit/#erc-20-transfer-scope) scope, allowing Alice to delegate to Bob the ability to spend her USDC, with a specified limit on the total amount.

Important

Before creating a delegation, ensure that the delegator account (in this example, Alice's account) has been deployed. If the account is not deployed, redeeming the delegation will fail.

```
import { createDelegation, ScopeType } from '@metamask/smart-accounts-kit'
import { parseUnits } from 'viem'

// USDC address on Ethereum Sepolia.
const tokenAddress = '0x1c7D4B196Cb0C7B01d743Fbc6116a902379C7238'

const delegation = createDelegation({
  to: delegateSmartAccount.address, // This example uses a delegate smart account
  from: delegatorSmartAccount.address,
  environment: delegatorSmartAccount.environment,
  scope: {
    type: ScopeType.Erc20TransferAmount,
    tokenAddress,
    // 10 USDC
    maxAmount: parseUnits('10', 6),
  },
})

```

### 6. Sign the delegation[​](#6-sign-the-delegation "Direct link to 6. Sign the delegation")

Sign the delegation with Alice's account, using the [signDelegation](/smart-accounts-kit/1.0.0/reference/smart-account/#signdelegation) method from `MetaMaskSmartAccount`. Alternatively, you can use the toolkit's [signDelegation](/smart-accounts-kit/1.0.0/reference/delegation/#signdelegation) utility method. Bob will later use the signed delegation to perform actions on Alice's behalf.

```
const signature = await delegatorSmartAccount.signDelegation({
  delegation,
})

const signedDelegation = {
  ...delegation,
  signature,
}

```

### 7. Redeem the delegation[​](#7-redeem-the-delegation "Direct link to 7. Redeem the delegation")

Bob can now redeem the delegation. The redeem transaction is sent to the `DelegationManager` contract, which validates the delegation and executes actions on Alice's behalf.

To prepare the calldata for the redeem transaction, use the [redeemDelegations](/smart-accounts-kit/1.0.0/reference/delegation/#redeemdelegations) method from `DelegationManager`. Since Bob is redeeming a single delegation chain, use the [SingleDefault](/smart-accounts-kit/1.0.0/concepts/delegation/delegation-manager/#execution-modes) execution mode.

Bob can redeem the delegation by submitting a user operation if his account is a smart account, or a regular transaction if his account is an EOA. In this example, Bob transfers 1 USDC from Alice’s account to his own.

- Redeem with a smart account
- Redeem with an EOA
- config.ts

```
import { createExecution, ExecutionMode } from '@metamask/smart-accounts-kit'
import { DelegationManager } from '@metamask/smart-accounts-kit/contracts'
import { zeroAddress } from 'viem'
import { callData } from './config.ts'

const delegations = [signedDelegation]

// USDC address on Ethereum Sepolia.
const tokenAddress = '0x1c7D4B196Cb0C7B01d743Fbc6116a902379C7238'

const executions = [createExecution({ target: tokenAddress, callData })]

const redeemDelegationCalldata = DelegationManager.encode.redeemDelegations({
  delegations: [delegations],
  modes: [ExecutionMode.SingleDefault],
  executions: [executions],
})

const userOperationHash = await bundlerClient.sendUserOperation({
  account: delegateSmartAccount,
  calls: [
    {
      to: delegateSmartAccount.address,
      data: redeemDelegationCalldata,
    },
  ],
  maxFeePerGas: 1n,
  maxPriorityFeePerGas: 1n,
})

```

```
import {
  createExecution,
  getSmartAccountsEnvironment,
  ExecutionMode,
} from '@metamask/smart-accounts-kit'
import { DelegationManager } from '@metamask/smart-accounts-kit/contracts'
import { zeroAddress } from 'viem'
import { callData } from './config.ts'

const delegations = [signedDelegation]

// USDC address on Ethereum Sepolia.
const tokenAddress = '0x1c7D4B196Cb0C7B01d743Fbc6116a902379C7238'

const executions = [createExecution({ target: tokenAddress, callData })]

const redeemDelegationCalldata = DelegationManager.encode.redeemDelegations({
  delegations: [delegations],
  modes: [ExecutionMode.SingleDefault],
  executions: [executions],
})

const transactionHash = await delegateWalletClient.sendTransaction({
  to: getSmartAccountsEnvironment(chain.id).DelegationManager,
  data: redeemDelegationCalldata,
  chain,
})

```

```
import { encodeFunctionData, erc20Abi, parseUnits } from 'viem'

// calldata to transfer 1 USDC to delegate address.
export const callData = encodeFunctionData({
  abi: erc20Abi,
  args: [delegateSmartAccount.address, parseUnits('1', 6)],
  functionName: 'transfer',
})

```

## Next steps[​](#next-steps "Direct link to Next steps")

- See [how to configure different scopes](/smart-accounts-kit/1.0.0/guides/delegation/use-delegation-scopes/) to define the initial authority of a delegation.
- See [how to further refine the authority of a delegation](/smart-accounts-kit/1.0.0/guides/delegation/use-delegation-scopes/constrain-scope/) using caveat enforcers.
- See [how to disable a delegation](/smart-accounts-kit/1.0.0/guides/delegation/disable-delegation/) to revoke permissions.
