Skip to main content

Create a redelegation

Redelegation is a core feature that sets delegations apart from other permission sharing frameworks. It allows a delegate to create a delegation chain, passing on the same or reduced level of authority from the root delegator.

For example, if Alice grants Bob permission to spend 10 USDC on her behalf, Bob can further grant Carol permission to spend up to 5 USDC on Alice's behalf-that is, Bob can redelegate. This creates a delegation chain where the root permissions are reshared with additional parties.

Prerequisites

Create a delegation

Create a root delegation from Alice to Bob.

This example uses the erc20TransferAmount scope, allowing Alice to delegate to Bob the ability to spend 10 USDC on her behalf.

import { aliceSmartAccount, bobSmartAccount } from "./config.ts";
import { createDelegation } from '@metamask/smart-accounts-kit'
import { parseUnits } from 'viem'

const delegation = createDelegation({
scope: {
type: "erc20TransferAmount",
tokenAddress: "0xc11F3a8E5C7D16b75c9E2F60d26f5321C6Af5E92",
// USDC has 6 decimal places.
maxAmount: parseUnits("10", 6),
},
to: bobSmartAccount.address,
from: aliceSmartAccount.address,
environment: aliceSmartAccount.environment,
})

const signedDelegation = aliceSmartAccount.signDelegation({ delegation })

Create a redelegation

Create a redelegation from Bob to Carol. When creating a redelegation, you can only narrow the scope of the original authority, not expand it.

To create a redelegation, provide the signed delegation as the parentDelegation argument when calling createDelegation. This example uses the erc20TransferAmount scope, allowing Bob to delegate to Carol the ability to spend 5 USDC on Alice's behalf.

import { bobSmartAccount, carolSmartAccount } from "./config.ts"
import { createDelegation } from '@metamask/smart-accounts-kit'
import { parseUnits } from 'viem'

const redelegation = createDelegation({
scope: {
type: "erc20TransferAmount",
tokenAddress: "0xc11F3a8E5C7D16b75c9E2F60d26f5321C6Af5E92",
// USDC has 6 decimal places.
maxAmount: parseUnits("5", 6),
},
to: carolSmartAccount.address,
from: bobSmartAccount.address,
// Signed root delegation from previous step.
parentDelegation: signedDelegation,
environment: bobSmartAccount.environment,
})

const signedRedelegation = bobSmartAccount.signDelegation({ delegation: redelegation })

Limit redelegation using caveats

When you create a redelegation, apply the toolkit's caveats to narrow the Carol's authority. For example, you can limit the authority so Carol can use the delegation only once.

To apply caveats, create the Delegation object and use createCaveatBuilder. Use getDelegationHashOffchain to get the delegation hash, then provide it as the authority field.

This example uses the limitedCalls caveat with a limit of 1.

// Use the config from previous step.
import { bobSmartAccount, carolSmartAccount } from "./config.ts"
import { createCaveatBuilder, getDelegationHashOffchain } from '@metamask/smart-accounts-kit/utils'

const caveatBuilder = createCaveatBuilder(bobSmartAccount.environment)

const caveats = caveatBuilder.addCaveat('limitedCalls', { limit: 1 })

const redelegation: Delegation = {
delegate: bobSmartAccount.address,
delegator: carolSmartAccount.address,
authority: getDelegationHashOffchain(rootDelegation),
caveats: caveats.build(),
salt: '0x',
};

const signedRedelegation = await bobSmartAccount.signDelegation({ delegation: redelegation })

Next steps