Skip to content

Latest commit

 

History

History
178 lines (135 loc) · 6.29 KB

File metadata and controls

178 lines (135 loc) · 6.29 KB
description Learn how to create a redelegation.
sidebar_label Create a redelegation
toc_max_heading_level 3
keywords
delegation
state
caveat enforcer
delegation scope
redelegation

import Tabs from "@theme/Tabs"; import TabItem from "@theme/TabItem"; import GlossaryTerm from '@theme/GlossaryTerm';

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 re-shared 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, ScopeType } from '@metamask/smart-accounts-kit'
import { parseUnits } from 'viem'

const delegation = createDelegation({
  scope: {
    type: ScopeType.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 })
import { Implementation, toMetaMaskSmartAccount } from '@metamask/smart-accounts-kit'
import { privateKeyToAccount } from 'viem/accounts'
import { createPublicClient, http } from 'viem'
import { sepolia as chain } from 'viem/chains'

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

const aliceAccount = privateKeyToAccount('0x...')
const bobAccount = privateKeyToAccount('0x...')

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

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

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, ScopeType } from '@metamask/smart-accounts-kit'
import { parseUnits } from 'viem'

const redelegation = createDelegation({
  scope: {
    type: ScopeType.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 })
// Update the existing config to create a smart account for Carol.

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

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

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 hashDelegation 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 { CaveatType } from '@metamask/smart-accounts-kit'
import { createCaveatBuilder, hashDelegation } from '@metamask/smart-accounts-kit/utils'

const caveatBuilder = createCaveatBuilder(bobSmartAccount.environment)

const caveats = caveatBuilder.addCaveat(CaveatType.LimitedCalls, { limit: 1 })

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

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

Next steps

See how to disable a delegation to revoke permissions.