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

# Perform executions on a smart account's behalf

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

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

## Steps

### 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.

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

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

```

### 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.

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

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

```

### 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/development/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:

```typescript
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/development/guides/smart-accounts/create-smart-account/).

### 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**

```typescript
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 },
})

```

**EOA**

```typescript
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

Create a [root delegation](/smart-accounts-kit/development/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/development/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/development/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.

```typescript
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

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

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

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

```

### 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/development/reference/delegation/#redeemdelegations) method from `DelegationManager`. Since Bob is redeeming a single delegation chain, use the [SingleDefault](/smart-accounts-kit/development/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**

```typescript
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,
})

```

**Redeem with an EOA**

```typescript
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,
})

```

**config.ts**

```typescript
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

- See [how to configure different scopes](/smart-accounts-kit/development/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/development/guides/delegation/use-delegation-scopes/constrain-scope/) using caveat enforcers.
- See [how to disable a delegation](/smart-accounts-kit/development/guides/delegation/disable-delegation/) to revoke permissions.
