Skip to content

High-level navigation enhancements #2074

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Draft
wants to merge 35 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
35 commits
Select commit Hold shift + click to select a range
565d9e9
Migrate gator docs
alexandratran May 23, 2025
11523bd
fixes
alexandratran May 23, 2025
598c837
swizzle desktop sidebar
alexandratran May 23, 2025
ff8d86b
update codeowners
alexandratran May 23, 2025
87b1020
Add initial dropdown component.
bgravenorst May 26, 2025
cd23897
Add front page.
bgravenorst May 27, 2025
a12367a
Update SDK connect guides
alexandratran May 30, 2025
03a1139
Merge branch 'main' into migrate-gator
alexandratran Jun 2, 2025
5f3a239
Fix category sections.
bgravenorst Jun 2, 2025
f341ae4
Inital dropdown style changes.
bgravenorst Jun 3, 2025
7a1c453
Update dropdown behaviour.
bgravenorst Jun 4, 2025
bf1448e
Add link to Embedded wallets (#2069)
bgravenorst Jun 2, 2025
000cf1e
Minor update. (#2070)
bgravenorst Jun 2, 2025
7ad0f3a
Update react-native.md (#2068)
RobItu Jun 3, 2025
e342ba9
chore(deps): bump tar-fs from 1.16.4 to 1.16.5 in the npm_and_yarn gr…
dependabot[bot] Jun 3, 2025
00f115a
fixes
alexandratran May 23, 2025
0d88cff
Add front page.
bgravenorst May 27, 2025
e9f6fed
Remove dup.
bgravenorst Jun 4, 2025
5c1df47
High-level navigation changes
alexandratran Jun 4, 2025
088d266
add get started button
alexandratran Jun 4, 2025
558a954
Merge branch 'main' into sdk-connect
alexandratran Jun 4, 2025
c31ebea
updates to sdk intro + redirects
alexandratran Jun 4, 2025
1feffcb
Merge branch 'main' into migrate-gator
alexandratran Jun 4, 2025
5c0dd5e
add api reference docs and fix links
alexandratran Jun 4, 2025
4e9c9b8
Merge branch 'migrate-gator' into nav-enhancements
alexandratran Jun 4, 2025
7415a8d
minor adjustments
alexandratran Jun 5, 2025
3fdde08
address feedback
alexandratran Jun 5, 2025
0873bb4
move llm prompt and update copy
alexandratran Jun 5, 2025
f72b52e
Merge branch 'main' into migrate-gator
alexandratran Jun 6, 2025
9c54eab
change file names (delegation-toolkit) and fix links
alexandratran Jun 6, 2025
1c8e299
fix lint error
alexandratran Jun 6, 2025
d03d348
Merge branch 'main' into sdk-connect
alexandratran Jun 6, 2025
c57df56
Merge branch 'migrate-gator' into nav-enhancements
alexandratran Jun 6, 2025
b352c5a
Merge branch 'sdk-connect' into nav-enhancements
alexandratran Jun 6, 2025
5370a11
Add product banner
alexandratran Jun 7, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .github/CODEOWNERS
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,9 @@
# Snaps documentation
/snaps/ @MetaMask/tech-writers @MetaMask/snaps

# Delegation Toolkit documentation
/delegation-toolkit/ @MetaMask/tech-writers @MetaMask/delegation @MetaMask/delegation-devrel

# SDK documentation
/sdk/ @MetaMask/tech-writers @MetaMask/sdk-devs @MetaMask/sdk-devrel

Expand Down
9 changes: 9 additions & 0 deletions delegation-toolkit/concepts/_category_.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
{
"label": "Concepts",
"position": 3,
"link": {
"type": "generated-index",
"slug": "/concepts",
"title": "Delegation Toolkit concepts"
}
}
185 changes: 185 additions & 0 deletions delegation-toolkit/concepts/caveat-enforcers.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,185 @@
---
description: Learn about caveat enforcers and how they restrict delegations.
sidebar_position: 4
---

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

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.

:::warning Important
- Without caveat enforcers, a delegation has infinite and unbounded authority to make any execution the original account can make.
We strongly recommend using caveat enforcers.
- Caveat enforcers safeguard the execution process but do not guarantee a final state post-redemption.
Always consider the full impact of combined caveat enforcers.
:::

## Smart contract interface

Caveat enforcers are Solidity contracts that implement the [`ICaveatEnforcer`](https://github.com/MetaMask/delegation-framework/blob/main/src/interfaces/ICaveatEnforcer.sol) interface:

```solidity
// SPDX-License-Identifier: MIT AND Apache-2.0
pragma solidity 0.8.23;

import { ModeCode } from "../utils/Types.sol";

/**
* This is an abstract contract that exposes pre and post Execution hooks during delegation redemption.
*/
interface ICaveatEnforcer {
/**
* Enforces conditions before any actions in a batch redemption process begin.
*/
function beforeAllHook(
bytes calldata _terms, // The terms to enforce set by the delegator.
bytes calldata _args, // An optional input parameter set by the redeemer at time of invocation.
ModeCode _mode, // The mode of execution for the executionCalldata.
bytes calldata _executionCalldata, // The data representing the execution.
bytes32 _delegationHash, // The hash of the delegation.
address _delegator, // The address of the delegator.
address _redeemer // The address that is redeeming the delegation.
)
external;

/**
* Enforces conditions before the execution tied to a specific delegation in the redemption process.
*/
function beforeHook(
bytes calldata _terms,
bytes calldata _args,
ModeCode _mode,
bytes calldata _executionCalldata,
bytes32 _delegationHash,
address _delegator,
address _redeemer
)
external;

/**
* Enforces conditions after the execution tied to a specific delegation in the redemption process.
*/
function afterHook(
bytes calldata _terms,
bytes calldata _args,
ModeCode _mode,
bytes calldata _executionCalldata,
bytes32 _delegationHash,
address _delegator,
address _redeemer
)
external;

/**
* Enforces conditions after all actions in a batch redemption process have been executed.
*/
function afterAllHook(
bytes calldata _terms,
bytes calldata _args,
ModeCode _mode,
bytes calldata _executionCalldata,
bytes32 _delegationHash,
address _delegator,
address _redeemer
)
external;
}
```

The interface consists of four key hook functions that are called at different stages of the delegation redemption process:

1. **`beforeAllHook`**: Called before any actions in a batch redemption process begin. This can be used to verify conditions that must be true for the entire batch execution.

2. **`beforeHook`**: Called before the execution tied to a specific delegation. This allows for pre-execution validation of conditions specific to that delegation.

3. **`afterHook`**: Called after the execution tied to a specific delegation completes. This can verify post-execution state changes or effects specific to that delegation.

4. **`afterAllHook`**: Called after all actions in a batch redemption process have completed. This enables verification of final conditions after the entire batch has executed.

Each of these hooks receives comprehensive information about the execution context, including:
- The caveat terms specified by the delegator.
- Optional arguments provided by the redeemer.
- The execution mode and calldata.
- The delegation hash.
- The delegator and redeemer addresses.

### Caveat enforcer rejection

The most important safety feature of these hooks is their ability to block executions:

- If any hook determines its conditions aren't met, it will **revert** (throw an exception).
- When a reversion occurs, the entire delegation redemption process is canceled.
- This prevents partial or invalid executions from occurring.
- No state changes from the attempted execution will be committed to the blockchain.

This "all-or-nothing" approach ensures that delegations only execute exactly as intended by their caveats.

## Caveat builder

While caveat enforcers operate at the smart contract level, most developers interact with them through the [`CaveatBuilder`](../how-to/create-delegation/restrict-delegation.md) interface in the MetaMask Delegation Toolkit.

The `CaveatBuilder` provides a developer-friendly TypeScript API that:

- Abstracts away the complexity of correctly formatting and encoding caveat terms.
- 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`
corresponds to a specific caveat enforcer contract. For example, when you use:

```typescript
caveatBuilder.addCaveat("allowedTargets", ["0xc11F3a8E5C7D16b75c9E2F60d26f5321C6Af5E92"]);
```

The builder is creating a caveat that references the
[`AllowedTargetsEnforcer`](../reference/caveats.md#allowedtargets) contract address and
properly encodes the provided addresses as terms for that enforcer.

## Caveat enforcer best practices

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.

- **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)
for common restriction patterns, including:

- Limiting target addresses and methods.
- Setting time or block number constraints.
- Restricting token transfers and approvals.
- Limiting execution frequency.

For more complex scenarios, you can also [create custom caveat enforcers](../how-to/create-delegation/create-custom-caveat-enforcer.md) by implementing the `ICaveatEnforcer` interface.

## Attenuating authority with redelegations

When [creating chains of delegations](../how-to/create-delegation/index.md#create-a-redelegation), 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:

- Each delegation in the chain inherits all restrictions from its parent delegation.
- New caveats can add further restrictions, but can't remove existing ones.

This means that a delegate can only redelegate with equal or lesser authority than they received.

### Example: Narrowing permissions

Imagine a simple financial delegation scenario:

1. **Alice delegates to Bob**, allowing him to withdraw up to 100 USDC on her behalf.
2. **Bob re-delegates to Carol**, but limits the permission to:
- Only 50 USDC (reducing the amount).
- Only before the end of the week (adding a time constraint).

Carol now has a more restricted version of Alice's original delegation. Bob couldn't give Carol more authority than he had (such as allowing her to withdraw 200 USDC), but he could narrow the permission.
140 changes: 140 additions & 0 deletions delegation-toolkit/concepts/delegation.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,140 @@
---
description: Learn about delegation, the delegation lifecycle, and the Delegation Framework.
sidebar_position: 2
---

# Delegation

*Delegation* is the ability for a [smart account](smart-accounts.md) to grant permission to another smart account
or externally owned account (EOA) to perform specific executions on their 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](../how-to/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
```
Loading
Loading