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

# Perform executions on a smart account's behalf

[Delegation](/smart-accounts-kit/concepts/delegation/overview/) is the ability for a [MetaMask smart account](/smart-accounts-kit/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/get-started/install/)

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

### 1. Set up a Public Client[​](#1-set-up-a-public-client "Direct link to 1. Set up a Public Client")

Set up a Public Client using Viem's [createPublicClient](https://viem.sh/docs/clients/public) function. You will configure Alice's account (the [delegator](/smart-accounts-kit/development/reference/glossary#delegator-account)**Delegator account** The account that creates and signs a delegation to grant limited authority to another account.) 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. Set up a Bundler Client[​](#2-set-up-a-bundler-client "Direct link to 2. Set up a Bundler Client")

Set up a Bundler Client using Viem's [createBundlerClient](https://viem.sh/account-abstraction/clients/bundler) function. You can use the [bundler](/smart-accounts-kit/development/reference/glossary#bundler)**Bundler** An ERC-4337 component that manages the alternate mempool: it collects user operations from smart accounts, packages them, and submits them to the network. service to estimate gas for [user operations](/smart-accounts-kit/development/reference/glossary#user-operation)**User operation** A pseudo-transaction object defined by ERC-4337 that describes what a smart account should execute. User operations are submitted to the alternate mempool managed by bundlers. 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](/smart-accounts-kit/development/reference/glossary#delegator-account)**Delegator account** The account that creates and signs a delegation to grant limited authority to another account. who will create a delegation. The delegator must be a [MetaMask smart account](/smart-accounts-kit/development/reference/glossary#metamask-smart-account)**MetaMask smart account** A smart contract account created using the Smart Accounts Kit that supports programmable behavior, flexible signing options, and ERC-7710 delegations.; use the toolkit's [toMetaMaskSmartAccount](/smart-accounts-kit/reference/smart-account/#tometamasksmartaccount) method to create the delegator account.

This example configures a Hybrid smart account, which is a flexible smart account implementation that supports both an [EOA](/smart-accounts-kit/development/reference/glossary#externally-owned-account-eoa)**Externally owned account (EOA)** A private-key-controlled account with no built-in programmable execution logic. owner and any number of [passkey](/smart-accounts-kit/development/reference/glossary#passkey)**Passkey** A cryptographic key that can be used to sign transactions instead of a private key. (WebAuthn) signers:

```
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/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](/smart-accounts-kit/development/reference/glossary#delegate-account)**Delegate account** The account that receives delegated authority and can redeem a delegation under its constraints. who will receive the delegation. The delegate can be a [smart account](/smart-accounts-kit/development/reference/glossary#metamask-smart-account)**MetaMask smart account** A smart contract account created using the Smart Accounts Kit that supports programmable behavior, flexible signing options, and ERC-7710 delegations. or an [EOA](/smart-accounts-kit/development/reference/glossary#externally-owned-account-eoa)**Externally owned account (EOA)** A private-key-controlled account with no built-in programmable execution logic.:

- 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/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/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/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/reference/smart-account/#signdelegation) method from `MetaMaskSmartAccount`. Alternatively, you can use the toolkit's [signDelegation](/smart-accounts-kit/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/reference/delegation/#redeemdelegations) method from `DelegationManager`. Since Bob is redeeming a single delegation chain, use the [SingleDefault](/smart-accounts-kit/concepts/delegation/delegation-manager/#execution-modes) execution mode.

Bob can redeem the delegation by submitting a [user operation](/smart-accounts-kit/development/reference/glossary#user-operation)**User operation** A pseudo-transaction object defined by ERC-4337 that describes what a smart account should execute. User operations are submitted to the alternate mempool managed by bundlers. 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/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/guides/delegation/use-delegation-scopes/constrain-scope/) using caveat enforcers.
- See [how to disable a delegation](/smart-accounts-kit/guides/delegation/disable-delegation/) to revoke permissions.
