diff --git a/delegation-toolkit/concepts/delegation.md b/delegation-toolkit/concepts/delegation.md
deleted file mode 100644
index 003a68ccd17..00000000000
--- a/delegation-toolkit/concepts/delegation.md
+++ /dev/null
@@ -1,140 +0,0 @@
----
-description: Learn about delegation, the delegation lifecycle, and the Delegation Framework.
-sidebar_position: 2
----
-
-# Delegation
-
-*Delegation* is the ability for a [MetaMask smart account](smart-accounts.md) to grant permission to another smart account
-or externally owned account (EOA) to perform specific executions on its behalf, under defined rules and restrictions.
-The account that grants the permission is called the *delegator account*, while the account that receives the permission
-is called the *delegate account*.
-
-The MetaMask Delegation Toolkit includes the following delegation features:
-
-- **Caveats** - Users can use [caveat enforcers](caveat-enforcers.md) to apply rules and restrictions to delegations.
- For example: Alice delegates the ability to spend her USDC to Bob, limiting the amount to 100 USDC.
-
-- **Chain of delegations** - Users can redelegate permissions that have been delegated to them, creating a chain of delegations across trusted parties.
-
-Delegations are created using the `Delegation` type, which is specified as follows:
-
-```typescript
-export type Delegation = {
- delegate: Hex; // The address to which the delegation is being granted.
- delegator: Hex; // The address that is granting the delegation.
- authority: Hex; // Hash of the parent delegation, or the constant ROOT_AUTHORITY.
- caveats: Caveat[]; // Caveats that restrict the authority being granted.
- salt: Hex; // Used to avoid hash collisions between identical delegations.
- signature: Hex; // Signature from the delegator account.
-};
-```
-
-## Delegation lifecycle
-
-The delegation lifecycle is as follows:
-
-1. **Delegation creation** - A delegation is initialized, and the delegator account signs it.
-
-2. **Caveat enforcement** - The caveats applied to the delegation specify conditions under which
- the delegation can be redeemed.
-
-3. **Delegation storage** - The delegation can be stored, enabling retrieval for future redemption.
-
- :::note
- [Storing and retrieving delegations](../experimental/store-retrieve-delegations.md) using the toolkit's
- `DelegationStorageClient` is an experimental feature.
- :::
-
-4. **Delegation redemption** - The delegate (the account being granted the permission) redeems the
- delegation through an [ERC-4337 user operation](smart-accounts.md#account-abstraction-erc-4337),
- which verifies that the delegated authority is valid in order to perform the execution.
-
-See [how to create a delegation](../guides/create-delegation/index.md) to get started with the
-delegation lifecycle.
-
-## Delegation Framework
-
-The MetaMask Delegation Toolkit includes the Delegation Framework, which is a
-[set of comprehensively audited smart contracts](https://github.com/MetaMask/delegation-framework) that
-collectively handle delegator account creation, the delegation lifecycle,
-and caveat enforcement.
-It consists of the following components:
-
-- **Delegator Core** - Delegator Core contains the logic for the ERC-4337 compliant delegator accounts.
- It defines the interface needed for the Delegation Manager to invoke executions on behalf of the accounts.
-
-- **Delegator account implementations** - There are [multiple delegator account implementations](smart-accounts.md#smart-account-implementation-types),
- with the main difference being the signature scheme used to manage the underlying account.
-
-- **Delegation Manager** - The Delegation Manager validates delegations and triggers executions
- on behalf of the delegator, ensuring tasks are executed accurately and securely.
-
- When a delegation is redeemed, the Delegation Manager performs the following steps.
- It processes a single step for all redemptions before proceeding to the next one:
-
- 1. Validates the input data by ensuring the lengths of `permissionContexts`, `modes`, and
- `executionCallDatas` match, or throws `BatchDataLengthMismatch`.
- 2. Decodes and validates the delegation, checking that the caller (`msg.sender`) is the delegate
- and that there are no empty signatures, or throws `InvalidDelegate`.
- 3. Verifies delegation signatures, ensuring validity using `ECDSA` (for EOAs) or
- `isValidSignature` (for contracts), or throws `InvalidSignature`.
- 4. Validates the delegation chain's authority and ensures delegations are not disabled.
- 5. Executes the `beforeHook` for each `caveat` in the delegation, passing relevant data (`terms`,
- `arguments`, `mode`, `execution` `calldata`, and `delegationHash`) to the caveat enforcer.
- 6. Calls `executeFromExecutor` to perform the delegation's execution, either by the delegator or
- the caller for self-authorized executions.
- 7. Executes the `afterHook` for each `caveat`, similar to the `beforeHook`, passing required data
- to enforce post-execution conditions.
- 8. Emits `RedeemedDelegation` events for each delegation that was successfully redeemed.
-
-- **Caveat enforcers** - [Caveat enforcers](caveat-enforcers.md) manage rules and restrictions for delegations,
- providing fine-tuned control over delegated executions.
-
-## Delegation redemption flow
-
-This diagram illustrates how a delegation is created and subsequently redeemed on the Delegation Manager.
-The Delegation Manager is responsible for validating the signature of the delegation and the caveat enforcers.
-If everything is correct, it allows a delegate to execute an action on behalf of the delegator.
-
-Learn more about the caveat enforcer hooks in the [Caveat enforcers](caveat-enforcers.md) section.
-
-```mermaid
-%%{
- init: {
- 'sequence': {
- 'actorMargin': 25,
- 'width': 200
- }
- }
-}%%
-
-sequenceDiagram
- participant Delegator
- participant Delegate
- participant Manager as Delegation Manager
- participant Enforcer as Caveat enforcer
-
- Delegator->>Delegator: Create delegation with caveat enforcers
- Delegator->>Delegator: Sign delegation
- Delegator->>Delegate: Send signed delegation
- Note right of Delegate: Hold delegation until redemption
-
- Delegate->>Manager: redeemDelegations() with delegation & execution details
- Manager->>Delegator: isValidSignature()
- Delegator-->>Manager: Confirm valid (or not)
-
- Manager->>Enforcer: beforeAllHook()
- Note right of Manager: Expect no error
- Manager->>Enforcer: beforeHook()
- Note right of Manager: Expect no error
-
- Manager->>Delegator: executeFromExecutor() with execution details
- Delegator->>Delegator: Perform execution
- Note right of Manager: Expect no error
-
- Manager->>Enforcer: afterHook()
- Note right of Manager: Expect no error
- Manager->>Enforcer: afterAllHook()
- Note right of Manager: Expect no error
-```
diff --git a/delegation-toolkit/concepts/caveat-enforcers.md b/delegation-toolkit/concepts/delegation/caveat-enforcers.md
similarity index 89%
rename from delegation-toolkit/concepts/caveat-enforcers.md
rename to delegation-toolkit/concepts/delegation/caveat-enforcers.md
index f8dc236e715..dcefa1dc49f 100644
--- a/delegation-toolkit/concepts/caveat-enforcers.md
+++ b/delegation-toolkit/concepts/delegation/caveat-enforcers.md
@@ -1,12 +1,12 @@
---
description: Learn about caveat enforcers and how they restrict delegations.
-sidebar_position: 4
+sidebar_position: 2
---
# Caveat enforcers
The MetaMask Delegation Toolkit provides *caveat enforcers*, which are smart contracts that implement rules and restrictions (*caveats*) on delegations.
-They serve as the underlying mechanism that enables conditional execution within the [Delegation Framework](delegation.md#delegation-framework).
+They serve as the underlying mechanism that enables conditional execution within the [Delegation Framework](index.md#delegation-framework).
A caveat enforcer acts as a gate that validates whether a delegation can be used for a particular execution. When a delegate attempts to execute an action on behalf of a delegator, each caveat enforcer specified in the delegation evaluates whether the execution meets its defined criteria.
@@ -119,7 +119,7 @@ This "all-or-nothing" approach ensures that delegations only execute exactly as
## Caveat builder
-While caveat enforcers operate at the smart contract level, most developers interact with them through the [`CaveatBuilder`](../guides/create-delegation/restrict-delegation.md) interface in the MetaMask Delegation Toolkit.
+While caveat enforcers operate at the smart contract level, most developers interact with them through the [`CaveatBuilder`](../../guides/delegation/restrict-delegation.md) interface in the MetaMask Delegation Toolkit.
The `CaveatBuilder` provides a developer-friendly TypeScript API that:
@@ -127,7 +127,7 @@ The `CaveatBuilder` provides a developer-friendly TypeScript API that:
- Provides type-checking and validation for caveat parameters.
- Handles the creation of the `caveats` array needed when creating a delegation.
-Each [caveat type](../reference/caveats.md) in the `CaveatBuilder`
+Each [caveat type](../../reference/caveats.md) in the `CaveatBuilder`
corresponds to a specific caveat enforcer contract. For example, when you use:
```typescript
@@ -135,7 +135,7 @@ caveatBuilder.addCaveat("allowedTargets", ["0xc11F3a8E5C7D16b75c9E2F60d26f5321C6
```
The builder is creating a caveat that references the
-[`AllowedTargetsEnforcer`](../reference/caveats.md#allowedtargets) contract address and
+[`AllowedTargetsEnforcer`](../../reference/caveats.md#allowedtargets) contract address and
properly encodes the provided addresses as terms for that enforcer.
## Caveat enforcer best practices
@@ -145,14 +145,14 @@ When designing delegations with caveats, consider these best practices:
- **Combine caveat enforcers appropriately** - Use multiple caveat enforcers to create comprehensive restrictions.
- **Consider caveat enforcer order** - When using caveat enforcers that modify external contract states, the order matters.
- For example, using [`NativeTokenPaymentEnforcer`](../reference/caveats.md#nativetokenpayment) before
- [`NativeBalanceChangeEnforcer`](../reference/caveats.md#nativebalancechange) might cause validation failures.
+ For example, using [`NativeTokenPaymentEnforcer`](../../reference/caveats.md#nativetokenpayment) before
+ [`NativeBalanceChangeEnforcer`](../../reference/caveats.md#nativebalancechange) might cause validation failures.
- **Be careful with unbounded delegations** - Always include appropriate caveat enforcers to limit what a delegate can do.
## Available caveat enforcers
-The Delegation Toolkit provides [many out-of-the-box caveat enforcers](../reference/caveats.md)
+The Delegation Toolkit provides [many out-of-the-box caveat enforcers](../../reference/caveats.md)
for common restriction patterns, including:
- Limiting target addresses and methods.
@@ -160,11 +160,11 @@ for common restriction patterns, including:
- Restricting token transfers and approvals.
- Limiting execution frequency.
-For more complex scenarios, you can also [create custom caveat enforcers](../guides/create-delegation/create-custom-caveat-enforcer.md) by implementing the `ICaveatEnforcer` interface.
+For more complex scenarios, you can also [create custom caveat enforcers](../../guides/delegation/create-custom-caveat-enforcer.md) by implementing the `ICaveatEnforcer` interface.
## Attenuating authority with redelegations
-When [creating chains of delegations](../guides/create-delegation/index.md#create-a-redelegation), it's important to understand how authority flows and can be restricted.
+When creating chains of delegations via [redelegations](index.md#delegation-types), it's important to understand how authority flows and can be restricted.
Caveats applied to a chain of delegations are *accumulative*—they stack on top of each other:
diff --git a/delegation-toolkit/concepts/delegation/index.md b/delegation-toolkit/concepts/delegation/index.md
new file mode 100644
index 00000000000..9f4ee8e4fdb
--- /dev/null
+++ b/delegation-toolkit/concepts/delegation/index.md
@@ -0,0 +1,180 @@
+---
+description: Learn about delegation, the delegation lifecycle, and the Delegation Framework.
+sidebar_position: 2
+toc_max_heading_level: 2
+---
+
+import Tabs from "@theme/Tabs";
+import TabItem from "@theme/TabItem";
+
+# Delegation
+
+*Delegation* is the ability for a [MetaMask smart account](../smart-accounts.md) to grant permission to another smart account
+or externally owned account (EOA) to perform specific executions on its behalf.
+The account that grants the permission is called the *delegator account*, while the account that receives the permission
+is called the *delegate account*.
+
+The MetaMask Delegation Toolkit follows the [ERC-7710](https://eips.ethereum.org/EIPS/eip-7710) standard for smart contract delegation.
+In addition, users can use [caveat enforcers](caveat-enforcers.md) to apply rules and restrictions to delegations.
+For example: Alice delegates the ability to spend her USDC to Bob, limiting the amount to 100 USDC.
+
+## Delegation lifecycle
+
+The delegation lifecycle is as follows:
+
+1. **Create a delegation** - The delegator account creates a delegation, applying *caveats* which specify conditions under which the delegation can be redeemed.
+ The delegator signs the delegation.
+
+3. **Store the delegation** - A dapp can store the delegation, enabling retrieval for future redemption.
+
+4. **Redeem the delegation** - The delegate (the account being granted the permission) redeems the delegation via the Delegation Manager,
+ which verifies that the delegated authority is valid in order to perform the execution.
+
+See [how to perform executions on a smart account's behalf](../../guides/delegation/execute-on-smart-accounts-behalf.md) to get started with the delegation lifecycle.
+
+## Delegation types
+
+You can create the following delegation types:
+
+- **Root delegation** - A root delegation is when a delegator delegates their own authority away, as opposed to *redelegating* permissions they received from a previous delegation.
+ In a chain of delegations, the first delegation is the root delegation.
+ For example, Alice delegates the ability to spend her USDC to Bob, limiting the amount to 100 USDC.
+
+ Use [`createDelegation`](../../reference/api/delegation.md#createdelegation) to create a root delegation.
+
+- **Open root delegation** - An open root delegation is a root delegation that doesn't specify a delegate.
+ This means that any account can redeem the delegation.
+ For example, Alice delegates the ability to spend 100 of her USDC to anyone.
+
+ You must create open root delegations carefully, to ensure that they are not misused.
+ Use [`createOpenDelegation`](../../reference/api/delegation.md#createopendelegation) to create an open root delegation.
+
+- **Redelegation** - A delegate can redelegate permissions that have been granted to them, creating a chain of delegations across trusted parties.
+ For example, Alice delegates the ability to spend 100 of her USDC to Bob.
+ Bob redelegates the ability to spend 50 of Alice's 100 USDC to Carol.
+
+ Use [`createDelegation`](../../reference/api/delegation.md#createdelegation) to create a redelegation.
+
+- **Open redelegation** - An open redelegation is a redelegation that doesn't specify a delegate.
+ This means that any account can redeem the redelegation.
+ For example, Alice delegates the ability to spend 100 of her USDC to Bob.
+ Bob redelegates the ability to spend 50 of Alice's 100 USDC to anyone.
+
+ As with open root delegations, you must create open redelegations carefully, to ensure that they are not misused.
+ Use [`createOpenDelegation`](../../reference/api/delegation.md#createopendelegation) to create an open redelegation.
+
+## Delegation Framework
+
+The MetaMask Delegation Toolkit includes the Delegation Framework, which is a
+[set of comprehensively audited smart contracts](https://github.com/MetaMask/delegation-framework) that
+collectively handle delegator account creation, the delegation lifecycle,
+and caveat enforcement.
+It consists of the following components:
+
+- **Delegator Core** - Delegator Core contains the logic for the ERC-4337 compliant delegator accounts.
+ It defines the interface needed for the Delegation Manager to invoke executions on behalf of the accounts.
+
+- **Delegator account implementations** - Delegator accounts are smart accounts, and there are [multiple smart account implementations](../smart-accounts.md#smart-account-implementation-types),
+ with differing signature schemes used to manage the underlying account.
+
+- **Delegation Manager** - The Delegation Manager validates delegations and triggers executions
+ on behalf of the delegator, ensuring tasks are executed accurately and securely.
+
+ When you redeem a delegation using [`redeemDelegations`](../../reference/api/delegation.md#redeemdelegations), the Delegation Manager performs the following steps.
+ It processes a single step for all redemptions before proceeding to the next one:
+
+ 1. Validates the input data by ensuring the lengths of `delegations`, `modes`, and
+ `executions` match.
+ 2. Decodes and validates the delegation, checking that the caller is the delegate
+ and that there are no empty signatures.
+ 3. Verifies delegation signatures, ensuring validity using ECDSA (for EOAs) or
+ `isValidSignature` (for contracts).
+ 4. Validates the delegation chain's authority and ensures delegations are not disabled.
+ 5. Executes the `beforeHook` for each [caveat](caveat-enforcers.md) in the delegation, passing relevant data (`terms`,
+ `arguments`, `mode`, `execution` `calldata`, and `delegationHash`) to the caveat enforcer.
+ 6. Calls `executeFromExecutor` to perform the delegation's execution, either by the delegator or
+ the caller for self-authorized executions.
+ 7. Executes the `afterHook` for each caveat, similar to the `beforeHook`, passing required data
+ to enforce post-execution conditions.
+ 8. Emits `RedeemedDelegation` events for each delegation that was successfully redeemed.
+
+- **Caveat enforcers** - [Caveat enforcers](caveat-enforcers.md) manage rules and restrictions for delegations,
+ providing fine-tuned control over delegated executions.
+
+## Delegation flow
+
+This diagram shows how a delegation is created and redeemed with the Delegation Manager.
+The Delegation Manager is responsible for validating the signature of the delegation and the caveat enforcers.
+If everything is correct, it allows a delegate to execute an action on behalf of the delegator.
+
+Learn more about the caveat enforcer hooks in the [Caveat enforcers](caveat-enforcers.md) section.
+
+```mermaid
+%%{
+ init: {
+ 'sequence': {
+ 'actorMargin': 30,
+ 'width': 250
+ }
+ }
+}%%
+
+sequenceDiagram
+ participant Delegator
+ participant Delegate
+ participant Manager as Delegation Manager
+ participant Enforcer as Caveat enforcer
+
+ Delegator->>Delegator: Create delegation with caveat enforcers
+ Delegator->>Delegator: Sign delegation
+ Delegator->>Delegate: Send signed delegation
+ Note right of Delegate: Hold delegation until redemption
+
+ Delegate->>Manager: redeemDelegations() with delegation & execution details
+ Manager->>Delegator: isValidSignature()
+ Delegator-->>Manager: Confirm valid (or not)
+
+ Manager->>Enforcer: beforeAllHook()
+ Note right of Manager: Expect no error
+ Manager->>Enforcer: beforeHook()
+ Note right of Manager: Expect no error
+
+ Manager->>Delegator: executeFromExecutor() with execution details
+ Delegator->>Delegator: Perform execution
+ Note right of Manager: Expect no error
+
+ Manager->>Enforcer: afterHook()
+ Note right of Manager: Expect no error
+ Manager->>Enforcer: afterAllHook()
+ Note right of Manager: Expect no error
+```
+
+## Execution modes
+
+When redeeming a delegation using [`redeemDelegations`](../../reference/api/delegation.md#redeemdelegations), you must pass an execution mode for each delegation chain you pass to the method.
+The Delegation Toolkit supports the following execution modes, based on [ERC-7579](https://erc7579.com/):
+
+| Execution mode | Number of delegation chains passed to `redeemDelegations` | Processing method | Does user operation continue execution if redemption reverts? |
+|--|--|--|--|
+| `SINGLE_DEFAULT_MODE` | One | Sequential | No |
+| `SINGLE_TRY_MODE` | One | Sequential | Yes |
+| `BATCH_DEFAULT_MODE` | Multiple | Interleaved | No |
+| `BATCH_TRY_MODE` | Multiple | Interleaved | Yes |
+
+### Sequential processing
+
+In `SINGLE` modes, processing is sequential:
+
+1. For each delegation in the chain, all caveats' `before` hooks are called.
+2. The single redeemed action is executed.
+3. For each delegation in the chain, all caveats' `after` hooks are called.
+
+### Interleaved processing
+
+In `BATCH` modes, processing is interleaved:
+
+1. For each chain in the batch, and each delegation in the chain, all caveats' `before` hooks are called.
+2. Each redeemed action is executed.
+3. For each chain in the batch, and each delegation in the chain, all caveats' `after` hooks are called.
+
+`BATCH` mode allows for powerful use cases, but the Delegation Framework currently does not include any `BATCH` compatible caveat enforcers.
diff --git a/delegation-toolkit/concepts/environment.md b/delegation-toolkit/concepts/environment.md
index 986c7a16a4a..fe4c046db78 100644
--- a/delegation-toolkit/concepts/environment.md
+++ b/delegation-toolkit/concepts/environment.md
@@ -8,7 +8,7 @@ import TabItem from "@theme/TabItem";
# Delegator environment
-The `DeleGatorEnvironment` object is a component of the MetaMask Delegation Toolkit that defines the contract addresses necessary for interacting with the [Delegation Framework](delegation.md#delegation-framework) on a specific network.
+The `DeleGatorEnvironment` object is a component of the MetaMask Delegation Toolkit that defines the contract addresses necessary for interacting with the [Delegation Framework](delegation/index.md#delegation-framework) on a specific network.
The delegator environment serves several key purposes:
@@ -71,7 +71,7 @@ See the changelog of the toolkit version you are using (in the left sidebar) for
Alternatively, you can use the [`getDelegatorEnvironment`](../reference/api/delegation.md#getdelegatorenvironment) function to resolve the environment.
This function is especially useful if your delegator is not a smart account when
-[creating a redelegation](../guides/create-delegation/index.md#create-a-redelegation).
+creating a [redelegation](delegation/index.md#delegation-types).
```typescript
import {
diff --git a/delegation-toolkit/concepts/smart-accounts.md b/delegation-toolkit/concepts/smart-accounts.md
index ab153d1fa57..a57bf44e3d3 100644
--- a/delegation-toolkit/concepts/smart-accounts.md
+++ b/delegation-toolkit/concepts/smart-accounts.md
@@ -92,4 +92,4 @@ The MetaMask Smart Accounts flow is as follows:
Delegator accounts are a type of MetaMask smart account that allows users to grant permission to other smart accounts or EOAs
to perform specific executions on their behalf, under defined rules and restrictions.
-Learn more about [delegation](delegation.md).
+Learn more about [delegation](delegation/index.md).
diff --git a/delegation-toolkit/experimental/store-retrieve-delegations.md b/delegation-toolkit/experimental/store-retrieve-delegations.md
index ff22fe8a5be..56f56315d9e 100644
--- a/delegation-toolkit/experimental/store-retrieve-delegations.md
+++ b/delegation-toolkit/experimental/store-retrieve-delegations.md
@@ -15,7 +15,7 @@ This is an experimental feature and may change in future releases.
:::
You can use methods provided by the `DelegationStorageClient` of the MetaMask Delegation Toolkit to store and retrieve
-[delegations](../concepts/delegation.md).
+[delegations](../concepts/delegation/index.md).
## Prerequisites
diff --git a/delegation-toolkit/get-started/erc7715-quickstart.md b/delegation-toolkit/get-started/erc7715-quickstart.md
index fc608e0e57b..8907abdeac2 100644
--- a/delegation-toolkit/get-started/erc7715-quickstart.md
+++ b/delegation-toolkit/get-started/erc7715-quickstart.md
@@ -130,7 +130,7 @@ const bundlerClient = createBundlerClient({
### 6. Redeem ERC-7715 permissions
-The session account can now [redeem the delegation](../guides/redeem-delegation.md). The redeem transaction is sent to the `DelegationManager` contract, which validates the delegation and executes actions on the user's behalf.
+The session account can now [redeem the delegation](../experimental/erc-7710-redeem-delegations.md). The redeem transaction is sent to the `DelegationManager` contract, which validates the delegation and executes actions on the user's behalf.
To redeem the permissions, you can use the `sendUserOperationWithDelegation` bundler client action.
diff --git a/delegation-toolkit/get-started/install.md b/delegation-toolkit/get-started/install.md
index 0b3dceeea31..7709ad6b0c3 100644
--- a/delegation-toolkit/get-started/install.md
+++ b/delegation-toolkit/get-started/install.md
@@ -17,7 +17,7 @@ This page provides instructions to install and set up the MetaMask Delegation To
- Install [Yarn](https://yarnpkg.com/),
[npm](https://docs.npmjs.com/downloading-and-installing-node-js-and-npm), or another package manager.
- If you plan to use any smart contracts (for example, to
- [create a custom caveat enforcer](../guides/create-delegation/create-custom-caveat-enforcer.md)),
+ [create a custom caveat enforcer](../guides/delegation/create-custom-caveat-enforcer.md)),
install [Foundry](https://book.getfoundry.sh/getting-started/installation).
## Steps
@@ -33,7 +33,7 @@ npm install @metamask/delegation-toolkit
### 2. (Optional) Install the contracts
If you plan to extend the Delegation Framework smart contracts (for example, to
-[create a custom caveat enforcer](../guides/create-delegation/create-custom-caveat-enforcer.md)), install
+[create a custom caveat enforcer](../guides/delegation/create-custom-caveat-enforcer.md)), install
the contract package using Foundry's command-line tool, Forge:
```bash
diff --git a/delegation-toolkit/get-started/smart-account-quickstart/eip7702.md b/delegation-toolkit/get-started/smart-account-quickstart/eip7702.md
index 493c17982d0..41a90b2f518 100644
--- a/delegation-toolkit/get-started/smart-account-quickstart/eip7702.md
+++ b/delegation-toolkit/get-started/smart-account-quickstart/eip7702.md
@@ -8,7 +8,7 @@ sidebar_label: EIP-7702 quickstart
This quickstart demonstrates how to upgrade your externally owned account (EOA) to support MetaMask Smart Accounts
functionality using an [EIP-7702](https://eips.ethereum.org/EIPS/eip-7702) transaction. This enables your EOA to leverage the benefits of account
-abstraction, such as batch transactions, gas sponsorship, and [ERC-7710 delegation capabilities](../../concepts/delegation.md).
+abstraction, such as batch transactions, gas sponsorship, and [delegation capabilities](../../concepts/delegation/index.md).
## Prerequisites
@@ -156,6 +156,6 @@ const userOperationHash = await bundlerClient.sendUserOperation({
## Next steps
-- To grant specific permissions to other accounts from your smart account, [create a delegation](../../how-to/create-delegation/index.md).
+- To grant specific permissions to other accounts from your smart account, [create a delegation](../../guides/delegation/execute-on-smart-accounts-behalf.md).
- To quickly bootstrap a MetaMask Smart Accounts project, [use the CLI](../use-the-cli.md).
- You can also [use MetaMask SDK to upgrade a MetaMask account to a smart account](/sdk/tutorials/upgrade-eoa-to-smart-account).
diff --git a/delegation-toolkit/get-started/smart-account-quickstart/index.md b/delegation-toolkit/get-started/smart-account-quickstart/index.md
index 2d65660cf80..3cab237b061 100644
--- a/delegation-toolkit/get-started/smart-account-quickstart/index.md
+++ b/delegation-toolkit/get-started/smart-account-quickstart/index.md
@@ -94,8 +94,8 @@ const userOperationHash = await bundlerClient.sendUserOperation({
## Next steps
-- To grant specific permissions to other accounts from your smart account, [create a delegation](../../guides/create-delegation/index.md).
+- To grant specific permissions to other accounts from your smart account, [create a delegation](../../guides/delegation/execute-on-smart-accounts-behalf.md).
- This quickstart example uses a Hybrid smart account.
You can also [configure other smart account types](../../guides/smart-accounts/create-smart-account.md).
-- To upgrade an EOA to a smart account, see the [EIP-7702 quickstart](eip7702-quickstart.md).
+- To upgrade an EOA to a smart account, see the [EIP-7702 quickstart](eip7702.md).
- To quickly bootstrap a MetaMask Smart Accounts project, [use the CLI](../use-the-cli.md).
diff --git a/delegation-toolkit/guides/configure.md b/delegation-toolkit/guides/configure.md
index c518247b3cd..b12e70d6851 100644
--- a/delegation-toolkit/guides/configure.md
+++ b/delegation-toolkit/guides/configure.md
@@ -17,9 +17,7 @@ The MetaMask Delegation Toolkit provides custom middleware for [Pimlico's](https
## Prerequisites
-- [Install and set up the Delegation Toolkit](../get-started/install.md).
-- Optionally, complete the [smart account quickstart](../get-started/quickstart.md) or [delegation quickstart](../get-started/delegation-quickstart.md) to
- familiarize yourself with the toolkit's capabilities.
+[Install and set up the Delegation Toolkit.](../get-started/install.md)
## Viem's Account Abstraction API
diff --git a/delegation-toolkit/guides/create-delegation/index.md b/delegation-toolkit/guides/create-delegation/index.md
deleted file mode 100644
index df9c3da9607..00000000000
--- a/delegation-toolkit/guides/create-delegation/index.md
+++ /dev/null
@@ -1,349 +0,0 @@
----
-description: Learn how to create different types of delegations, and how to sign a delegation.
-sidebar_position: 6
----
-
-import Tabs from "@theme/Tabs";
-import TabItem from "@theme/TabItem";
-
-# Create a delegation
-
-The MetaMask Delegation Toolkit enables you to create [delegations](../../concepts/delegation.md)
-from a delegator account to a delegate account.
-
-:::note
-Delegations are compatible with [ERC-7710](https://eip.tools/eip/7710) and [ERC-7715](https://ethereum-magicians.org/t/erc-7715-grant-permissions-from-wallets/20100), to support a standardized minimal interface.
-[Requesting ERC-7715 permissions](../../experimental/erc-7715-request-permissions.md) and [redeeming ERC-7710 delegations](../../experimental/erc-7710-redeem-delegations.md)
-are experimental features.
-:::
-
-:::warning
-The examples on this page demonstrate delegations without any restrictions.
-Unrestricted delegations grant complete control over the account to the delegate, which can pose significant security risks.
-It is crucial to add caveats to limit the delegated authority.
-Learn how to [restrict a delegation](./restrict-delegation.md) using caveat enforcers.
-:::
-
-## Prerequisites
-
-- [Install and set up the Delegation Toolkit.](../../get-started/install.md)
-- [Configure the Delegation Toolkit.](../configure.md)
-- [Create a MetaMask smart account.](../smart-accounts/create-smart-account.md)
-
-## Create a root delegation
-
-A *root delegation* is a delegation that doesn't derive its authority from another delegation.
-It is when a delegator delegates its own authority away, as opposed to a [redelegation](#create-a-redelegation).
-Create a root delegation as follows:
-
-
-
-
-```typescript
-import { createDelegation } from "@metamask/delegation-toolkit";
-import { delegatorSmartAccount } from "./config.ts";
-
-// The address to which the delegation is granted. It can be an EOA address, or
-// smart account address.
-const delegate = "0x2FcB88EC2359fA635566E66415D31dD381CF5585";
-
-const delegation = createDelegation({
- to: delegate,
- from: delegatorSmartAccount.address,
- caveats: [] // Empty caveats array - we recommend adding appropriate restrictions.
-});
-```
-
-
-
-
-
-```typescript
-import { createPublicClient, http } from "viem";
-import { sepolia as chain } from "viem/chains";
-import {
- Implementation,
- toMetaMaskSmartAccount,
-} from "@metamask/delegation-toolkit";
-
-const publicClient = createPublicClient({
- chain,
- transport: http()
-});
-
-const privateKey = generatePrivateKey();
-const account = privateKeyToAccount(privateKey);
-
-export const delegatorSmartAccount = await toMetaMaskSmartAccount({
- client: publicClient,
- implementation: Implementation.Hybrid,
- deployParams: [account.address, [], [], []],
- deploySalt: "0x",
- signatory: { account },
-});
-```
-
-
-
-
-## Create an open root delegation
-
-An *open root delegation* is a root delegation that doesn't specify a delegate.
-This means that any account can redeem the delegation.
-You must create open root delegations carefully, to ensure that they are not misused.
-Create an open root delegation by setting the delegate property to the special address
-`0x0000000000000000000000000000000000000a11` (available via the constant `ANY_BENEFICIARY`).
-
-
-
-
-```typescript
-import { createOpenDelegation } from "@metamask/delegation-toolkit";
-import { delegatorSmartAccount } from "./config.ts";
-
-const openRootDelegation = createOpenDelegation({
- from: delegatorSmartAccount.address,
- caveats: [] // Empty caveats array - we recommend adding appropriate restrictions.
-});
-```
-
-
-
-
-
-```typescript
-import { createPublicClient, http } from "viem";
-import { sepolia as chain } from "viem/chains";
-import {
- Implementation,
- toMetaMaskSmartAccount,
-} from "@metamask/delegation-toolkit";
-
-const publicClient = createPublicClient({
- chain,
- transport: http()
-});
-
-const privateKey = generatePrivateKey();
-const account = privateKeyToAccount(privateKey);
-
-export const delegatorSmartAccount = await toMetaMaskSmartAccount({
- client: publicClient,
- implementation: Implementation.Hybrid,
- deployParams: [account.address, [], [], []],
- deploySalt: "0x",
- signatory: { account },
-});
-```
-
-
-
-
-## Create a redelegation
-
-A recipient of a delegation (the delegate), can *redelegate* that authority to a third party, potentially applying additional [restrictions](restrict-delegation.md).
-Create a redelegation as follows:
-
-
-
-
-```typescript
-import {
- createDelegation,
- getDelegationHashOffchain
- } from "@metamask/delegation-toolkit";
-import { delegatorSmartAccount } from "./config.ts";
-
-// The address is used as the root delegator. While creating the redelegation,
-// the root delegate address will be the delegator address.
-const delegate = "0x2FcB88EC2359fA635566E66415D31dD381CF5585";
-
-const delegation = createDelegation({
- to: delegate,
- from: delegatorSmartAccount.address,
- caveats: [] // Empty caveats array - we recommend adding appropriate restrictions.
-});
-
-// The authority is the (typed data) hash of the delegation from which the authority is derived.
-const parentDelegationHash = getDelegationHashOffchain(delegation);
-
-// The address is used as the delegate address while creating the redelegation.
-const leafDelegate = "0xb4821Ab7d5942Bd2533387592068a12608B4a52C"
-
-const leafDelegation = createDelegation({
- to: leafDelegate,
- from: delegate,
- // You can also choose to pass the parent delegation object, and let function
- // handle the rest.
- parentDelegation: parentDelegationHash,
- caveats: [] // Empty caveats array - we recommend adding appropriate restrictions.
-});
-```
-
-
-
-
-
-```typescript
-import { createPublicClient, http } from "viem";
-import { sepolia as chain } from "viem/chains";
-import {
- Implementation,
- toMetaMaskSmartAccount,
-} from "@metamask/delegation-toolkit";
-
-const publicClient = createPublicClient({
- chain,
- transport: http()
-});
-
-const privateKey = generatePrivateKey();
-const account = privateKeyToAccount(privateKey);
-
-export const delegatorSmartAccount = await toMetaMaskSmartAccount({
- client: publicClient,
- implementation: Implementation.Hybrid,
- deployParams: [account.address, [], [], []],
- deploySalt: "0x",
- signatory: { account },
-});
-```
-
-
-
-
-## Create an open redelegation
-
-An *open redelegation* is a [redelegation](#create-a-redelegation) that doesn't specify a delegate.
-This means that any account can redeem the redelegation.
-As with [open root delegations](#create-an-open-root-delegation), you must create open redelegations carefully,
-to ensure that they are not misused.
-Create an open redelegation as follows:
-
-
-
-
-```typescript
-import {
- createDelegation,
- createOpenDelegation,
- getDelegationHashOffchain
- } from "@metamask/delegation-toolkit";
-import { delegatorSmartAccount } from "./config.ts";
-
-// The address is used as the root delegator. While creating the redelegation,
-// the root delegate address will be the delegator address.
-const delegate = "0x2FcB88EC2359fA635566E66415D31dD381CF5585";
-
-const delegation = createDelegation({
- to: delegate,
- from: delegatorSmartAccount.address,
- caveats: [] // Empty caveats array - we recommend adding appropriate restrictions.
-});
-
-// The authority is the (typed data) hash of the delegation from which the authority is derived.
-const parentDelegationHash = getDelegationHashOffchain(delegation);
-
-const leafDelegation = createOpenDelegation({
- from: delegate,
- // You can also choose to pass the parent delegation object, and let the function
- // handle the rest.
- parentDelegation: parentDelegationHash,
- caveats: [] // Empty caveats array - we recommend adding appropriate restrictions.
-});
-```
-
-
-
-
-
-```typescript
-import { createPublicClient, http } from "viem";
-import { sepolia as chain } from "viem/chains";
-import {
- Implementation,
- toMetaMaskSmartAccount,
-} from "@metamask/delegation-toolkit";
-
-const publicClient = createPublicClient({
- chain,
- transport: http()
-});
-
-const privateKey = generatePrivateKey();
-const account = privateKeyToAccount(privateKey);
-
-export const delegatorSmartAccount = await toMetaMaskSmartAccount({
- client: publicClient,
- implementation: Implementation.Hybrid,
- deployParams: [account.address, [], [], []],
- deploySalt: "0x",
- signatory: { account },
-});
-```
-
-
-
-
-## Sign a delegation
-
-A delegation must be signed by the delegator to be valid for redemption. The `MetaMaskSmartAccount` supports signing the delegation using [EIP-712 Typed Data](https://eips.ethereum.org/EIPS/eip-712) via the `signDelegation` method.
-Sign a delegation as follows:
-
-
-
-
-```typescript
-import { createDelegation } from "@metamask/delegation-toolkit";
-import { delegatorSmartAccount } from "./config.ts";
-
-// The address to which the delegation is granted. It can be an EOA address, or
-// smart account address.
-const delegate = "0x2FcB88EC2359fA635566E66415D31dD381CF5585";
-
-const delegation = createDelegation({
- to: delegate,
- from: delegatorSmartAccount.address,
- caveats: [] // Empty caveats array - we recommend adding appropriate restrictions.
-});
-
-const signature = await delegatorSmartAccount.signDelegation({ delegation });
-
-const signedDelegation = {
- ...delegation,
- signature
-};
-```
-
-
-
-
-
-```typescript
-import { createPublicClient, http } from "viem";
-import { sepolia as chain } from "viem/chains";
-import {
- Implementation,
- toMetaMaskSmartAccount,
-} from "@metamask/delegation-toolkit";
-
-const publicClient = createPublicClient({
- chain,
- transport: http()
-});
-
-const privateKey = generatePrivateKey();
-const account = privateKeyToAccount(privateKey);
-
-export const delegatorSmartAccount = await toMetaMaskSmartAccount({
- client: publicClient,
- implementation: Implementation.Hybrid,
- deployParams: [account.address, [], [], []],
- deploySalt: "0x",
- signatory: { account },
-});
-
-```
-
-
-
\ No newline at end of file
diff --git a/delegation-toolkit/guides/delegation/_category_.json b/delegation-toolkit/guides/delegation/_category_.json
new file mode 100644
index 00000000000..b304d543be5
--- /dev/null
+++ b/delegation-toolkit/guides/delegation/_category_.json
@@ -0,0 +1,4 @@
+{
+ "label": "Delegation",
+ "position": 3
+}
\ No newline at end of file
diff --git a/delegation-toolkit/guides/create-delegation/create-custom-caveat-enforcer.md b/delegation-toolkit/guides/delegation/create-custom-caveat-enforcer.md
similarity index 99%
rename from delegation-toolkit/guides/create-delegation/create-custom-caveat-enforcer.md
rename to delegation-toolkit/guides/delegation/create-custom-caveat-enforcer.md
index 4dcefc0711b..46346d337a7 100644
--- a/delegation-toolkit/guides/create-delegation/create-custom-caveat-enforcer.md
+++ b/delegation-toolkit/guides/delegation/create-custom-caveat-enforcer.md
@@ -1,6 +1,6 @@
---
description: Learn how to create, deploy, and apply a custom caveat enforcer
-sidebar_position: 2
+sidebar_position: 3
---
import Tabs from "@theme/Tabs";
diff --git a/delegation-toolkit/guides/delegation/execute-on-smart-accounts-behalf.md b/delegation-toolkit/guides/delegation/execute-on-smart-accounts-behalf.md
new file mode 100644
index 00000000000..39666994b62
--- /dev/null
+++ b/delegation-toolkit/guides/delegation/execute-on-smart-accounts-behalf.md
@@ -0,0 +1,229 @@
+---
+description: Use delegations to perform executions on a smart account's behalf.
+sidebar_position: 1
+sidebar_label: Execute on a smart account's behalf
+---
+
+import Tabs from "@theme/Tabs";
+import TabItem from "@theme/TabItem";
+
+# Perform executions on a smart account's behalf
+
+[Delegation](../../concepts/delegation/index.md) is the ability for a [MetaMask smart account](../../concepts/smart-accounts.md) 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 Delegation Toolkit.](../../get-started/install.md)
+
+## Steps
+
+### 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.
+
+```typescript
+import { createPublicClient, http } from "viem"
+import { sepolia as chain } from "viem/chains"
+
+const publicClient = createPublicClient({
+ chain,
+ transport: http(),
+})
+```
+
+### 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.
+
+```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 who will create a delegation.
+The delegator must be a MetaMask smart account; use the toolkit's [`toMetaMaskSmartAccount`](../../reference/api/smart-account.md#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 with an Account signatory](../smart-accounts/create-smart-account.md#create-a-hybrid-smart-account-with-an-account-signatory):
+
+```typescript
+import { Implementation, toMetaMaskSmartAccount } from "@metamask/delegation-toolkit"
+import { privateKeyToAccount } from "viem/accounts"
+
+const delegatorAccount = privateKeyToAccount("0x...")
+
+const delegatorSmartAccount = await toMetaMaskSmartAccount({
+ client: publicClient,
+ implementation: Implementation.Hybrid,
+ deployParams: [delegatorAccount.address, [], [], []],
+ deploySalt: "0x",
+ signatory: { account: delegatorAccount },
+})
+```
+
+:::note
+See [how to configure other smart account types](../smart-accounts/create-smart-account.md).
+:::
+
+### 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):
+
+
+
+
+```typescript
+import { Implementation, toMetaMaskSmartAccount } from "@metamask/delegation-toolkit"
+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",
+ signatory: { account: delegateAccount },
+})
+```
+
+
+
+
+```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](../../concepts/delegation/index.md#delegation-types) 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`](../../reference/api/delegation.md#createdelegation) method to create a root delegation.
+This example passes an empty `caveats` array, which means Bob can perform any action on Alice's behalf. We recommend [restricting the delegation](restrict-delegation.md) by adding caveat enforcers.
+For example, Alice can delegate the ability to spend her USDC to Bob, limiting the amount to 100 USDC.
+
+:::warning 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 } from "@metamask/delegation-toolkit"
+
+const delegation = createDelegation({
+ to: delegateSmartAccount.address, // This example uses a delegate smart account
+ from: delegatorSmartAccount.address,
+ caveats: [], // Empty caveats array - we recommend adding appropriate restrictions.
+})
+```
+
+### 6. Sign the delegation
+
+Sign the delegation with Alice's account, using the [`signDelegation`](../../reference/api/smart-account.md#signdelegation) method from `MetaMaskSmartAccount`. Alternatively, you can use the toolkit's [`signDelegation`](../../reference/api/delegation.md#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`](../../reference/api/delegation.md#redeemdelegations) method from `DelegationManager`.
+Since Bob is redeeming a single delegation chain, use the [`SINGLE_DEFAULT_MODE`](../../concepts/delegation/index.md#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:
+
+
+
+
+```typescript
+import { createExecution } from "@metamask/delegation-toolkit"
+import { DelegationManager } from "@metamask/delegation-toolkit/contracts"
+import { SINGLE_DEFAULT_MODE } from "@metamask/delegation-toolkit/utils"
+import { zeroAddress } from "viem"
+
+const delegations = [signedDelegation]
+
+const executions = createExecution({ target: zeroAddress })
+
+const redeemDelegationCalldata = DelegationManager.encode.redeemDelegations({
+ delegations: [delegations],
+ modes: [SINGLE_DEFAULT_MODE],
+ executions: [executions],
+})
+
+const userOperationHash = await bundlerClient.sendUserOperation({
+ account: delegateSmartAccount,
+ calls: [
+ {
+ to: delegateSmartAccount.address,
+ data: redeemDelegationCalldata,
+ },
+ ],
+ maxFeePerGas: 1n,
+ maxPriorityFeePerGas: 1n,
+})
+```
+
+
+
+
+```typescript
+import { createExecution, getDeleGatorEnvironment } from "@metamask/delegation-toolkit"
+import { DelegationManager } from "@metamask/delegation-toolkit/contracts"
+import { SINGLE_DEFAULT_MODE } from "@metamask/delegation-toolkit/utils"
+import { zeroAddress } from "viem"
+
+const delegations = [signedDelegation]
+
+const executions = createExecution({ target: zeroAddress })
+
+const redeemDelegationCalldata = DelegationManager.encode.redeemDelegations({
+ delegations: [delegations],
+ modes: [SINGLE_DEFAULT_MODE],
+ executions: [executions]
+});
+
+const transactionHash = await delegateWalletClient.sendTransaction({
+ to: getDeleGatorEnvironment(chain.id).DelegationManager,
+ data: redeemDelegationCalldata,
+ chain,
+})
+```
+
+
+
diff --git a/delegation-toolkit/guides/create-delegation/restrict-delegation.md b/delegation-toolkit/guides/delegation/restrict-delegation.md
similarity index 97%
rename from delegation-toolkit/guides/create-delegation/restrict-delegation.md
rename to delegation-toolkit/guides/delegation/restrict-delegation.md
index ba82bb6d119..fe6c5838b01 100644
--- a/delegation-toolkit/guides/create-delegation/restrict-delegation.md
+++ b/delegation-toolkit/guides/delegation/restrict-delegation.md
@@ -1,6 +1,6 @@
---
description: Learn how to restrict a delegation using caveat enforcers, and the available caveat types.
-sidebar_position: 1
+sidebar_position: 2
toc_max_heading_level: 3
---
@@ -9,7 +9,7 @@ import TabItem from "@theme/TabItem";
# Restrict a delegation
-Use [caveat enforcers](../../concepts/caveat-enforcers.md) to apply specific rules and restrictions
+Use [caveat enforcers](../../concepts/delegation/caveat-enforcers.md) to apply specific rules and restrictions
to a delegation, ensuring that delegated executions are only performed under predefined circumstances.
A delegation has a `caveats` property, which is an array of `Caveat` objects.
diff --git a/delegation-toolkit/guides/redeem-delegation.md b/delegation-toolkit/guides/redeem-delegation.md
deleted file mode 100644
index 58f6a81e1f0..00000000000
--- a/delegation-toolkit/guides/redeem-delegation.md
+++ /dev/null
@@ -1,352 +0,0 @@
----
-description: Learn how to redeem a delegation with a smart contract account (SCA) or an externally owned account (EOA).
-sidebar_position: 7
-toc_max_heading_level: 3
----
-
-import Tabs from "@theme/Tabs";
-import TabItem from "@theme/TabItem";
-
-# Redeem a delegation
-
-A delegate can redeem a delegation by submitting either a user operation or a regular transaction,
-depending on whether the delegate is a MetaMask smart account or an externally owned account (EOA).
-
-The redeem transaction is sent to the `DelegationManager` contract, which validates the delegation and executes actions on the delegator's behalf.
-To prepare the calldata for the redeem transaction, use the [`redeemDelegation`](../reference/api/delegation.md#redeemdelegation) utility function.
-The function supports batch redemption, allowing multiple delegations to be processed within a single transaction.
-
-## Prerequisites
-
-- [Install and set up the Delegation Toolkit.](../get-started/install.md)
-- [Configure the Delegation Toolkit.](configure.md)
-- [Create a delegator smart account.](smart-accounts/create-smart-account.md)
-- [Create a delegation.](create-delegation/index.md)
-
-## Redeem a delegation
-
-Redeem a delegation with a [MetaMask smart account](#redeem-with-a-metamask-smart-account) or an [externally owned account (EOA)](#redeem-with-an-eoa).
-
-### Redeem with a MetaMask smart account
-
-The following example demonstrates how to submit a user operation to redeem a delegation.
-It assumes you have a delegation signed by the delegator, and that the delegate is a MetaMask smart account.
-
-
-
-
-```typescript
-import { ExecutionStruct } from "@metamask/delegation-toolkit";
-import { DelegationManager } from "@metamask/delegation-toolkit/contracts";
-import { SINGLE_DEFAULT_MODE } from "@metamask/delegation-toolkit/utils";
-import { bundlerClient, pimlicoClient } from "./client.ts";
-import { delegateSmartAccount } from "./account.ts";
-
-const delegations: Delegation[] = [ signedDelegation ];
-
-// SINGLE_DEFAULT_MODE is the default execution mode.
-const mode: ExecutionMode = SINGLE_DEFAULT_MODE;
-
-// For SINGLE execution modes, the executions array must be length 1.
-const executions: ExecutionStruct[] = [{
- target: zeroAddress,
- value: 0n,
- callData: "0x"
-}];
-
-const redeemDelegationCalldata = DelegationManager.encode.redeemDelegations({
- delegations: [ delegations ],
- modes: [ mode ],
- executions: [ executions ]
-});
-
-const { fast: fee } = await pimlicoClient.getUserOperationGasPrice();
-
-const userOperationHash = await bundlerClient.sendUserOperation({
- account: delegateSmartAccount,
- calls: [
- {
- to: delegateSmartAccount.address,
- data: redeemDelegationCalldata
- }
- ],
- ...fee
-});
-```
-
-
-
-
-
-```typescript
-import {
- Implementation,
- toMetaMaskSmartAccount,
-} from "@metamask/delegation-toolkit";
-import { privateKeyToAccount } from "viem/accounts";
-import { publicClient } from "./client.ts"
-
-const delegateAccount = privateKeyToAccount("0x...");
-
-export const delegateSmartAccount = await toMetaMaskSmartAccount({
- client: publicClient,
- implementation: Implementation.Hybrid,
- deployParams: [delegateAccount.address, [], [], []],
- deploySalt: "0x",
- signatory: { account: delegateAccount },
-});
-```
-
-
-
-
-
-```typescript
-import { createPublicClient, http } from "viem";
-import { sepolia as chain } from "viem/chains";
-import { createBundlerClient } from "viem/account-abstraction";
-import { createPimlicoClient } from "permissionless/clients/pimlico";
-
-// You can get the API Key from the Pimlico dashboard.
-const pimlicoUrl = "https://api.pimlico.io/v2/11155111/rpc";
-
-export const publicClient = createPublicClient({
- chain,
- transport: http(),
-});
-
-export const bundlerClient = createBundlerClient({
- client: publicClient,
- transport: http(pimlicoUrl),
-});
-
-export const pimlicoClient = createPimlicoClient({
- transport: http(pimlicoUrl),
-});
-```
-
-
-
-
-### Redeem with an EOA
-
-The following example demonstrates how to submit a transaction to redeem a delegation. It assumes you have a delegation signed by the delegator, and that the delegate is an EOA.
-
-
-
-
-```typescript
-import {
- ExecutionStruct,
- ExecutionMode
- Delegation,
- getDeleGatorEnvironment,
-} from "@metamask/delegation-toolkit";
-import { DelegationManager } from "@metamask/delegation-toolkit/contracts";
-import { SINGLE_DEFAULT_MODE } from "@metamask/delegation-toolkit/utils";
-import { sepolia as chain } from "viem/chains";
-import { delegateWalletClient } from "./account.ts";
-
-const delegations: Delegation[] = [ signedDelegation ];
-
-// SINGLE_DEFAULT_MODE is the default execution mode.
-const mode: ExecutionMode = SINGLE_DEFAULT_MODE;
-
-// For SINGLE execution modes, the executions array must be length 1.
-// Modify the executions to fit your use case.
-const executions: ExecutionStruct[] = [{
- target: zeroAddress,
- value: 0n,
- callData: "0x"
-}];
-
-const redeemDelegationCalldata = DelegationManager.encode.redeemDelegations({
- delegations: [ delegations ],
- modes: [ mode ],
- executions: [ executions ]
-});
-
-const transactionHash = await walletClient.sendTransaction({
- to: getDeleGatorEnvironment(chain.id).DelegationManager,
- data: redeemDelegationCalldata,
- chain,
-});
-```
-
-
-
-
-
-```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(),
-})
-```
-
-
-
-
-## Redeem multiple delegations
-
-You can redeem multiple delegations in a single user operation, each delegation independent of the others.
-Each element in the `delegationsArray` must have a corresponding element in the `executionsArray` and `modes`.
-
-The following example assumes you already have multiple signed delegations and that the delegate is a MetaMask smart account.
-The preparation of the calldata is the same when [using an EOA as the delegate](#redeem-with-an-eoa);
-the primary difference is that an EOA submits a regular transaction instead of a user operation.
-
-
-
-
-```typescript
-import {
- ExecutionStruct,
- Delegation,
- ExecutionMode,
-} from "@metamask/delegation-toolkit";
-import { DelegationManager } from "@metamask/delegation-toolkit/contracts";
-import { SINGLE_DEFAULT_MODE } from "@metamask/delegation-toolkit/utils";
-import { bundlerClient, pimlicoClient } from "./client.ts";
-import { delegateSmartAccount } from "./account.ts";
-
-const delegationsArray: Delegation[][] = [
- [ signedDelegation1 ]
- [ signedDelegation2 ]
- [ signedDelegation3 ]
-];
-
-const modes: ExecutionMode = [
- SINGLE_DEFAULT_MODE,
- SINGLE_DEFAULT_MODE,
- SINGLE_DEFAULT_MODE
-];
-
-const execution: ExecutionStruct[] = [{
- target: zeroAddress,
- value: 0n,
- callData: "0x"
-}];
-
-// Modify the executions to fit your use case. For simplicity, we've
-// included a basic example. The execution array can contain
-// multiple different executions.
-const executionsArray: ExecutionStruct:[][] = [
- execution,
- execution,
- execution
-];
-
-const redeemDelegationCalldata = DelegationManager.encode.redeemDelegations({
- delegations: [ delegations ],
- modes: [ mode ],
- executions: [ executions ]
-});
-
-const { fast: fee } = await pimlicoClient.getUserOperationGasPrice();
-
-const userOperationHash = await bundlerClient.sendUserOperation({
- account: delegateSmartAccount,
- calls: [
- {
- to: delegateSmartAccount.address,
- data: redeemDelegationCalldata
- }
- ],
- ...fee
-});
-```
-
-
-
-
-
-```typescript
-import {
- Implementation,
- toMetaMaskSmartAccount,
-} from "@metamask/delegation-toolkit";
-import { privateKeyToAccount } from "viem/accounts";
-import { publicClient } from "./client.ts";
-
-const delegateAccount = privateKeyToAccount("0x...");
-
-export const delegateSmartAccount = await toMetaMaskSmartAccount({
- client: publicClient,
- implementation: Implementation.Hybrid,
- deployParams: [delegateAccount.address, [], [], []],
- deploySalt: "0x",
- signatory: { account: delegateAccount },
-});
-```
-
-
-
-
-
-```typescript
-import { createPublicClient, http } from "viem";
-import { sepolia as chain } from "viem/chains";
-import { createBundlerClient } from "viem/account-abstraction";
-import { createPimlicoClient } from "permissionless/clients/pimlico";
-
-// You can get the API Key from the Pimlico dashboard.
-const pimlicoUrl = "https://api.pimlico.io/v2/11155111/rpc";
-
-export const publicClient = createPublicClient({
- chain,
- transport: http(),
-});
-
-export const bundlerClient = createBundlerClient({
- client: publicClient,
- transport: http(pimlicoUrl),
-});
-
-export const pimlicoClient = createPimlicoClient({
- transport: http(pimlicoUrl),
-});
-```
-
-
-
-
-## Execution modes
-
-The Delegation Toolkit supports several execution modes based on [ERC-7579](https://erc7579.com/).
-See the [ERC implementation](https://github.com/erc7579/erc7579-implementation/blob/main/src/lib/ModeLib.sol) for more details about the execution modes.
-
-The supported execution modes are `SINGLE_DEFAULT_MODE`, `SINGLE_TRY_MODE`, `BATCH_DEFAULT_MODE`, and `BATCH_TRY_MODE`.
-
-### `SINGLE` execution modes
-
-In `SINGLE` execution modes, only a single delegation chain and a single execution can be provided. This mode processes delegations sequentially:
-
-1. For each delegation in the chain, all caveats' `before` hooks are called.
-2. The single redeemed action is executed.
-3. For each delegation in the chain, all caveats' `after` hooks are called.
-
-### `BATCH` execution modes
-
-In `BATCH` execution modes, multiple delegation chains and multiple executions can be provided. This mode executes delegations in an interleaved way:
-
-1. For each chain in the batch, and each delegation in the chain, all caveats' `before` hooks are called.
-2. Each redeemed action is executed.
-3. For each chain in the batch, and each delegation in the chain, all caveats' `after` hooks are called.
-
-`BATCH` mode allows for powerful use cases, but the Delegation Framework currently does not include any `BATCH` compatible caveat enforcers.
-
-### `DEFAULT` modes
-
-In `DEFAULT` modes, if a revert occurs during redemption, the entire user operation reverts at that point.
-
-### `TRY` modes
-
-In `TRY` modes, if a revert occurs during redemption, execution of the user operation continues.
diff --git a/delegation-toolkit/guides/smart-accounts/create-smart-account.md b/delegation-toolkit/guides/smart-accounts/create-smart-account.md
index 3989a08155f..db5573d4880 100644
--- a/delegation-toolkit/guides/smart-accounts/create-smart-account.md
+++ b/delegation-toolkit/guides/smart-accounts/create-smart-account.md
@@ -24,7 +24,7 @@ You can create a Hybrid smart account with the following types of signatories.
### Create a Hybrid smart account with an Account signatory
-Use [`toMetaMaskSmartAccount`](../../reference/api/smart-account.md#tometamasksmartaccount) and Viem's [`privateKeyToAccount`](https://viem.sh/docs/accounts/local/privateKeyToAccount) to create a Hybrid smart account with a signatory from a private key:
+Use [`toMetaMaskSmartAccount`](../../reference/api/smart-account.md#tometamasksmartaccount), and Viem's [`privateKeyToAccount` and `generatePrivateKey`](https://viem.sh/docs/accounts/local/privateKeyToAccount), to create a Hybrid smart account with a signatory from a randomly generated private key:
@@ -290,7 +290,7 @@ A [Stateless 7702 smart account](../../concepts/smart-accounts.md#stateless-7702
functionality as defined by [EIP-7702](https://eips.ethereum.org/EIPS/eip-7702).
:::note
-This implementation does not handle the upgrade process; see the [EIP-7702 quickstart](../../get-started/eip7702-quickstart.md) to learn how to upgrade.
+This implementation does not handle the upgrade process; see the [EIP-7702 quickstart](../../get-started/smart-account-quickstart/eip7702.md) to learn how to upgrade.
:::
You can create a Stateless 7702 smart account with the following types of signatories.
@@ -416,5 +416,5 @@ With a MetaMask smart account, you can perform the following functions:
- In conjunction with [Viem Account Abstraction clients](../configure.md), deploy the smart account
and [send user operations](send-user-operation.md).
-- [Create delegations](../create-delegation/index.md) that can be used to grant specific rights and permissions to other accounts.
+- [Create delegations](../delegation/execute-on-smart-accounts-behalf.md) that can be used to grant specific rights and permissions to other accounts.
Smart accounts that create delegations are called *delegator accounts*.
diff --git a/delegation-toolkit/index.md b/delegation-toolkit/index.md
index 943740f8b11..fbd2bc0c874 100644
--- a/delegation-toolkit/index.md
+++ b/delegation-toolkit/index.md
@@ -12,8 +12,8 @@ import CardList from "@site/src/components/CardList"
The MetaMask Delegation Toolkit is a [Viem](https://viem.sh/)-based collection of tools for embedding [MetaMask Smart Accounts](concepts/smart-accounts.md) into dapps.
Smart accounts support programmable account behavior and advanced features like delegated permissions, multi-signature approvals, and gas abstraction.
-[Delegations](concepts/delegation.md) are a core feature of MetaMask Smart Accounts, enabling secure, rule-based permission sharing.
-These delegations are powered by the toolkit's Delegation Framework, which defines how
+[Delegation](concepts/delegation/index.md) is a core feature of MetaMask Smart Accounts, enabling secure, rule-based permission sharing.
+Delegation is powered by the toolkit's Delegation Framework, which defines how
permissions are created, shared, and enforced.
## Why use the toolkit?
diff --git a/delegation-toolkit/reference/api/delegation.md b/delegation-toolkit/reference/api/delegation.md
index 1cff1034af8..705a97afb8c 100644
--- a/delegation-toolkit/reference/api/delegation.md
+++ b/delegation-toolkit/reference/api/delegation.md
@@ -10,7 +10,7 @@ import TabItem from "@theme/TabItem";
# Delegation API reference
-The following API methods are related to creating and managing [delegations](../../concepts/delegation.md).
+The following API methods are related to creating and managing [delegations](../../concepts/delegation/index.md).
## `createCaveatBuilder`
@@ -358,16 +358,17 @@ export const environment: DeleGatorEnvironment = {
-## `redeemDelegation`
+## `redeemDelegations`
Encodes calldata for redeeming delegations.
+This method supports batch redemption, allowing multiple delegations to be processed within a single transaction.
### Parameters
| Name | Type | Required | Description |
| --- | --- | --- | --- |
| `delegations` | `Delegation[][]` | Yes | A nested collection representing chains of delegations. Each inner collection contains a chain of delegations to be redeemed. |
-| `modes` | `ExecutionMode[]` | Yes | A collection specifying the execution mode for each corresponding delegation chain. |
+| `modes` | `ExecutionMode[]` | Yes | A collection specifying the [execution mode](../../concepts/delegation/index.md#execution-modes) for each corresponding delegation chain. Supported execution modes are `SINGLE_DEFAULT_MODE`, `SINGLE_TRY_MODE`, `BATCH_DEFAULT_MODE`, and `BATCH_TRY_MODE`. |
| `executions` | `ExecutionStruct[][]` | Yes | A nested collection where each inner collection contains a list of `ExecutionStruct` objects associated with a specific delegation chain. |
### Example
diff --git a/delegation-toolkit/reference/caveats.md b/delegation-toolkit/reference/caveats.md
index c1eef812e94..6e2c63d8805 100644
--- a/delegation-toolkit/reference/caveats.md
+++ b/delegation-toolkit/reference/caveats.md
@@ -6,7 +6,7 @@ toc_max_heading_level: 2
# Caveats
-When [restricting a delegation](../guides/create-delegation/restrict-delegation.md), you can specify the following caveat types in the `CaveatBuilder`.
+When [restricting a delegation](../guides/delegation/restrict-delegation.md), you can specify the following caveat types in the `CaveatBuilder`.
## `allowedCalldata`
diff --git a/vercel.json b/vercel.json
index 62e57d0b0a5..04e124f10ab 100644
--- a/vercel.json
+++ b/vercel.json
@@ -732,15 +732,15 @@
},
{
"source": "/delegation-toolkit/development/how-to/create-delegation/",
- "destination": "/delegation-toolkit/development/guides/create-delegation/"
+ "destination": "/delegation-toolkit/development/guides/delegation/execute-on-smart-accounts-behalf/"
},
{
"source": "/delegation-toolkit/development/how-to/create-delegation/:path*/",
- "destination": "/delegation-toolkit/development/guides/create-delegation/:path*/"
+ "destination": "/delegation-toolkit/development/guides/delegation/:path*/"
},
{
"source": "/delegation-toolkit/development/how-to/redeem-delegation/",
- "destination": "/delegation-toolkit/development/guides/redeem-delegation/"
+ "destination": "/delegation-toolkit/development/guides/delegation/execute-on-smart-accounts-behalf/"
},
{
"source": "/delegation-toolkit/development/get-started/quickstart/",
@@ -754,6 +754,10 @@
"source": "/delegation-toolkit/development/get-started/cli-quickstart/",
"destination": "/delegation-toolkit/development/get-started/use-the-cli/"
},
+ {
+ "source": "/delegation-toolkit/development/concepts/caveat-enforcers/",
+ "destination": "/delegation-toolkit/development/concepts/delegation/caveat-enforcers/"
+ },
{
"source": "/developer-tools/faucet/sepolia/",
"destination": "/developer-tools/faucet/"