From 3975e1e37ee0b52fcb491a01958982732cecb80e Mon Sep 17 00:00:00 2001 From: Alexandra Tran Date: Tue, 26 Aug 2025 12:43:34 -0700 Subject: [PATCH 1/4] Add custom caveat enforcer tutorial --- delegation-toolkit/tutorials/_category_.json | 4 ++ .../create-custom-caveat-enforcer.md | 58 ++++++++++++------- vercel.json | 4 ++ 3 files changed, 45 insertions(+), 21 deletions(-) create mode 100644 delegation-toolkit/tutorials/_category_.json rename delegation-toolkit/{guides/create-delegation => tutorials}/create-custom-caveat-enforcer.md (54%) diff --git a/delegation-toolkit/tutorials/_category_.json b/delegation-toolkit/tutorials/_category_.json new file mode 100644 index 00000000000..03bb310eef8 --- /dev/null +++ b/delegation-toolkit/tutorials/_category_.json @@ -0,0 +1,4 @@ +{ + "label": "Tutorials", + "position": 5 +} \ No newline at end of file diff --git a/delegation-toolkit/guides/create-delegation/create-custom-caveat-enforcer.md b/delegation-toolkit/tutorials/create-custom-caveat-enforcer.md similarity index 54% rename from delegation-toolkit/guides/create-delegation/create-custom-caveat-enforcer.md rename to delegation-toolkit/tutorials/create-custom-caveat-enforcer.md index 4dcefc0711b..24fc5e9f6f0 100644 --- a/delegation-toolkit/guides/create-delegation/create-custom-caveat-enforcer.md +++ b/delegation-toolkit/tutorials/create-custom-caveat-enforcer.md @@ -1,5 +1,5 @@ --- -description: Learn how to create, deploy, and apply a custom caveat enforcer +description: Follow this tutorial to create a custom caveat enforcer for a delegation. sidebar_position: 2 --- @@ -8,24 +8,31 @@ import TabItem from "@theme/TabItem"; # Create a custom caveat enforcer -When [restricting a delegation](restrict-delegation.md), the MetaMask Delegation Toolkit provides some [out-of-the-box caveat enforcers](../../reference/caveats.md) -that cover common use cases. -For more granular or custom control, you can follow the instructions on this page to create custom caveat enforcers from scratch. +This tutorial walks you through creating a custom [caveat enforcer](../concepts/caveat-enforcers.md) and applying it to a [delegation](../concepts/delegation.md). + +The MetaMask Delegation Toolkit provides some [out-of-the-box caveat enforcers](../reference/caveats.md) that define rules and restrictions for common use cases. +For more granular or custom control, you can create custom caveat enforcers from scratch. +This tutorial walks you through creating and applying a caveat enforcer that only allows a delegation to be redeemed after a specific timestamp. ## Prerequisites -- [Install and set up the Delegation Toolkit.](../../get-started/install.md) +- [Install and set up the Delegation Toolkit](../../get-started/install.md) in your project. - [Configure the Delegation Toolkit.](../configure.md) +- [Install Foundry and Forge.](https://getfoundry.sh/introduction/installation) +- Get an [Infura API key](/developer-tools/dashboard/get-started/create-api) from the MetaMask Developer dashboard. +- Have a MetaMask account with some Sepolia ETH to deploy your contract. + :::note + You can use the [MetaMask faucet](/developer-tools/faucet) to get Sepolia ETH. + ::: ## Steps ### 1. Create the caveat enforcer -Create a contract that extends the +In your project's `src` directory, create a contract that extends the [`ICaveatEnforcer.sol`](https://github.com/MetaMask/delegation-framework/blob/main/src/interfaces/ICaveatEnforcer.sol) interface. - -For example, the following is a simple caveat enforcer that only allows a delegation to be redeemed after a specific timestamp. +The following `AfterTimestampEnforcer.sol` caveat enforcer only allows a delegation to be redeemed after a specific timestamp: ```solidity title="AfterTimestampEnforcer.sol" // SPDX-License-Identifier: MIT @@ -66,23 +73,28 @@ contract AfterTimestampEnforcer is CaveatEnforcer { ### 2. Deploy the caveat enforcer -Deploy your custom caveat enforcer to obtain its contract address. -For example, you can [deploy your smart contract using Forge](https://book.getfoundry.sh/forge/deploying). +Deploy your custom caveat enforcer using [Forge](https://book.getfoundry.sh/forge/deploying) to obtain its contract address. +Replace `` with your Infura API key, and `` with the private key of your MetaMask account: -### 3. Apply the caveat enforcer +```bash +forge create src/AfterTimestampEnforcer.sol:AfterTimestampEnforcer \ + --rpc-url https://sepolia.infura.io/v3/ \ + --private-key \ + --broadcast +``` -When creating a delegation, add the `Caveat` for the custom caveat to the `CaveatBuilder`. -Learn more about [applying caveats to a delegation](restrict-delegation.md). +The Forge CLI will display the address of the deployed caveat enforcer. -The following example uses the custom `AfterTimestampEnforcer.sol` caveat enforcer to create a delegation granting -an allowance of 1,000,000 wei that can only be spent after one hour from when the delegation is created. +### 3. Apply the caveat enforcer -:::warning Important -Depending on the use case, it may be necessary to add additional caveats to restrict the delegation further. -::: +Specify the address where your `AfterTimestampEnforcer.sol` contract is deployed, add it to the caveat builder, and create a delegation. +Learn more about [applying caveats to a delegation](../guides/create-delegation/restrict-delegation.md). + +The following code snippet uses the custom caveat enforcer to create a delegation granting +an allowance of 1,000,000 wei that can only be spent after one hour from when the delegation is created: - + ```typescript import { @@ -94,7 +106,7 @@ import { delegatorSmartAccount } from "./config.ts"; const environment = delegatorSmartAccount.environment; -// Replace this with the address where the AfterTimestampEnforcer.sol contract is deployed. +// Replace this with the address where your AfterTimestampEnforcer.sol contract is deployed. const afterTimestampEnforcer = "0x22Ae4c4919C3aB4B5FC309713Bf707569B74876F"; const caveatBuilder = createCaveatBuilder(environment); @@ -115,7 +127,6 @@ const delegation = createDelegation({ }); ``` - @@ -147,3 +158,8 @@ export const delegatorSmartAccount = await toMetaMaskSmartAccount({ + +You've successfully created, deployed, and applied a custom caveat enforcer! + +For production use cases, you might need to add additional caveats to restrict the delegation further. +Learn more about [caveat enforcers](../concepts/caveat-enforcers.md). diff --git a/vercel.json b/vercel.json index 62e57d0b0a5..770bf5e5ee9 100644 --- a/vercel.json +++ b/vercel.json @@ -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/guides/create-delegation/create-custom-caveat-enforcer/", + "destination": "/delegation-toolkit/development/tutorials/create-custom-caveat-enforcer/" + }, { "source": "/developer-tools/faucet/sepolia/", "destination": "/developer-tools/faucet/" From ace53974597141b035187fee713dc20a00a4eca4 Mon Sep 17 00:00:00 2001 From: Alexandra Tran Date: Wed, 27 Aug 2025 16:25:00 -0700 Subject: [PATCH 2/4] address reviewer comments --- delegation-toolkit/concepts/caveat-enforcers.md | 4 ++-- .../guides/create-delegation/restrict-delegation.md | 2 +- .../tutorials/create-custom-caveat-enforcer.md | 12 ++++++------ 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/delegation-toolkit/concepts/caveat-enforcers.md b/delegation-toolkit/concepts/caveat-enforcers.md index f8dc236e715..e061fa2e778 100644 --- a/delegation-toolkit/concepts/caveat-enforcers.md +++ b/delegation-toolkit/concepts/caveat-enforcers.md @@ -152,7 +152,7 @@ When designing delegations with caveats, consider these best practices: ## Available caveat enforcers -The Delegation Toolkit provides [many out-of-the-box caveat enforcers](../reference/caveats.md) +The Delegation Toolkit provides [out-of-the-box caveat enforcers](../reference/caveats.md) for common restriction patterns, including: - Limiting target addresses and methods. @@ -160,7 +160,7 @@ 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 other restriction patterns, you can also [create custom caveat enforcers](../tutorials/create-custom-caveat-enforcer.md) by implementing the `ICaveatEnforcer` interface. ## Attenuating authority with redelegations diff --git a/delegation-toolkit/guides/create-delegation/restrict-delegation.md b/delegation-toolkit/guides/create-delegation/restrict-delegation.md index ba82bb6d119..c53416de583 100644 --- a/delegation-toolkit/guides/create-delegation/restrict-delegation.md +++ b/delegation-toolkit/guides/create-delegation/restrict-delegation.md @@ -105,5 +105,5 @@ const delegation = createDelegation({ }); ``` -For more granular or custom control, you can also [create custom caveat enforcers](create-custom-caveat-enforcer.md) +For more specific or custom control, you can also [create custom caveat enforcers](../../tutorials/create-custom-caveat-enforcer.md) and add them to the caveat builder. diff --git a/delegation-toolkit/tutorials/create-custom-caveat-enforcer.md b/delegation-toolkit/tutorials/create-custom-caveat-enforcer.md index 24fc5e9f6f0..da010218351 100644 --- a/delegation-toolkit/tutorials/create-custom-caveat-enforcer.md +++ b/delegation-toolkit/tutorials/create-custom-caveat-enforcer.md @@ -10,9 +10,9 @@ import TabItem from "@theme/TabItem"; This tutorial walks you through creating a custom [caveat enforcer](../concepts/caveat-enforcers.md) and applying it to a [delegation](../concepts/delegation.md). -The MetaMask Delegation Toolkit provides some [out-of-the-box caveat enforcers](../reference/caveats.md) that define rules and restrictions for common use cases. -For more granular or custom control, you can create custom caveat enforcers from scratch. -This tutorial walks you through creating and applying a caveat enforcer that only allows a delegation to be redeemed after a specific timestamp. +The MetaMask Delegation Toolkit includes [out-of-the-box caveat enforcers](../reference/caveats.md) that define rules and restrictions for common use cases. +For more specific control or other use cases, you can create custom caveat enforcers. +In this tutorial, you'll create and apply a caveat enforcer that only allows a delegation to be redeemed after a specific timestamp. ## Prerequisites @@ -87,11 +87,11 @@ The Forge CLI will display the address of the deployed caveat enforcer. ### 3. Apply the caveat enforcer -Specify the address where your `AfterTimestampEnforcer.sol` contract is deployed, add it to the caveat builder, and create a delegation. +Specify the address of the deployed `AfterTimestampEnforcer.sol` contract, add it to the caveat builder, and create a delegation. Learn more about [applying caveats to a delegation](../guides/create-delegation/restrict-delegation.md). The following code snippet uses the custom caveat enforcer to create a delegation granting -an allowance of 1,000,000 wei that can only be spent after one hour from when the delegation is created: +a 1,000,000 wei allowance that becomes spendable one hour after it is created: @@ -106,7 +106,7 @@ import { delegatorSmartAccount } from "./config.ts"; const environment = delegatorSmartAccount.environment; -// Replace this with the address where your AfterTimestampEnforcer.sol contract is deployed. +// Replace this with the address of the deployed AfterTimestampEnforcer.sol contract. const afterTimestampEnforcer = "0x22Ae4c4919C3aB4B5FC309713Bf707569B74876F"; const caveatBuilder = createCaveatBuilder(environment); From 9fd77a44c00f826b24a9bd4b52c62c3337b913b0 Mon Sep 17 00:00:00 2001 From: Alexandra Tran Date: Wed, 27 Aug 2025 17:23:38 -0700 Subject: [PATCH 3/4] fix links --- delegation-toolkit/get-started/install.md | 4 ++-- .../tutorials/create-custom-caveat-enforcer.md | 10 +++++----- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/delegation-toolkit/get-started/install.md b/delegation-toolkit/get-started/install.md index 7709ad6b0c3..509d7e4fdfa 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/delegation/create-custom-caveat-enforcer.md)), + [create a custom caveat enforcer](../tutorials/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/delegation/create-custom-caveat-enforcer.md)), install +[create a custom caveat enforcer](../tutorials/create-custom-caveat-enforcer.md)), install the contract package using Foundry's command-line tool, Forge: ```bash diff --git a/delegation-toolkit/tutorials/create-custom-caveat-enforcer.md b/delegation-toolkit/tutorials/create-custom-caveat-enforcer.md index da010218351..a2aa3901650 100644 --- a/delegation-toolkit/tutorials/create-custom-caveat-enforcer.md +++ b/delegation-toolkit/tutorials/create-custom-caveat-enforcer.md @@ -8,7 +8,7 @@ import TabItem from "@theme/TabItem"; # Create a custom caveat enforcer -This tutorial walks you through creating a custom [caveat enforcer](../concepts/caveat-enforcers.md) and applying it to a [delegation](../concepts/delegation.md). +This tutorial walks you through creating a custom [caveat enforcer](../concepts/delegation/caveat-enforcers.md) and applying it to a [delegation](../concepts/delegation/index.md). The MetaMask Delegation Toolkit includes [out-of-the-box caveat enforcers](../reference/caveats.md) that define rules and restrictions for common use cases. For more specific control or other use cases, you can create custom caveat enforcers. @@ -16,8 +16,8 @@ In this tutorial, you'll create and apply a caveat enforcer that only allows a d ## Prerequisites -- [Install and set up the Delegation Toolkit](../../get-started/install.md) in your project. -- [Configure the Delegation Toolkit.](../configure.md) +- [Install and set up the Delegation Toolkit](../get-started/install.md) in your project. +- [Configure the Delegation Toolkit.](../guides/configure.md) - [Install Foundry and Forge.](https://getfoundry.sh/introduction/installation) - Get an [Infura API key](/developer-tools/dashboard/get-started/create-api) from the MetaMask Developer dashboard. - Have a MetaMask account with some Sepolia ETH to deploy your contract. @@ -88,7 +88,7 @@ The Forge CLI will display the address of the deployed caveat enforcer. ### 3. Apply the caveat enforcer Specify the address of the deployed `AfterTimestampEnforcer.sol` contract, add it to the caveat builder, and create a delegation. -Learn more about [applying caveats to a delegation](../guides/create-delegation/restrict-delegation.md). +Learn more about [applying caveats to a delegation](../guides/delegation/restrict-delegation.md). The following code snippet uses the custom caveat enforcer to create a delegation granting a 1,000,000 wei allowance that becomes spendable one hour after it is created: @@ -162,4 +162,4 @@ export const delegatorSmartAccount = await toMetaMaskSmartAccount({ You've successfully created, deployed, and applied a custom caveat enforcer! For production use cases, you might need to add additional caveats to restrict the delegation further. -Learn more about [caveat enforcers](../concepts/caveat-enforcers.md). +Learn more about [caveat enforcers](../concepts/delegation/caveat-enforcers.md). From 9d0c2093a406c907916d484fceba9feece291637 Mon Sep 17 00:00:00 2001 From: Alexandra Tran Date: Thu, 28 Aug 2025 16:59:15 -0700 Subject: [PATCH 4/4] address reviewer comments --- .../tutorials/create-custom-caveat-enforcer.md | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/delegation-toolkit/tutorials/create-custom-caveat-enforcer.md b/delegation-toolkit/tutorials/create-custom-caveat-enforcer.md index a2aa3901650..ab8d24a0774 100644 --- a/delegation-toolkit/tutorials/create-custom-caveat-enforcer.md +++ b/delegation-toolkit/tutorials/create-custom-caveat-enforcer.md @@ -1,5 +1,5 @@ --- -description: Follow this tutorial to create a custom caveat enforcer for a delegation. +description: Follow this tutorial to create, deploy, and apply a custom caveat enforcer for a delegation. sidebar_position: 2 --- @@ -29,10 +29,12 @@ In this tutorial, you'll create and apply a caveat enforcer that only allows a d ### 1. Create the caveat enforcer -In your project's `src` directory, create a contract that extends the +At the root of your project, create a `contracts` directory. +In that directory, create a new contract named `AfterTimestampEnforcer.sol`. + +Add the following code to `AfterTimestampEnforcer.sol`, which creates a caveat enforcer that extends the [`ICaveatEnforcer.sol`](https://github.com/MetaMask/delegation-framework/blob/main/src/interfaces/ICaveatEnforcer.sol) -interface. -The following `AfterTimestampEnforcer.sol` caveat enforcer only allows a delegation to be redeemed after a specific timestamp: +interface and only allows a delegation to be redeemed after a specific timestamp: ```solidity title="AfterTimestampEnforcer.sol" // SPDX-License-Identifier: MIT