# https://docs.gator.metamask.io/development llms-full.txt ## MetaMask Delegation Toolkit [Skip to main content](https://docs.gator.metamask.io/development#__docusaurus_skipToContent_fallback) This is a public beta release of the MetaMask Delegation Toolkit. This is the development version of the documentation and some features may not yet be available in the latest release. You can switch to the [latest version](https://docs.gator.metamask.io/) (0.10.2). On this page # MetaMask Delegation Toolkit documentation ## Why use the toolkit? [​](https://docs.gator.metamask.io/development\#why-use-the-toolkit "Direct link to Why use the toolkit?") The MetaMask Delegation Toolkit enables developers to create frictionless new experiences based on granular permission sharing and trust. The toolkit offers a suite of contracts, libraries, and services designed for maximum composability, allowing developers to build and extend their dapps with ease. The toolkit enables: - **Instant user onboarding.** Provide frictionless onboarding with no browser extension, mobile app, or seed phrase required. - **New web3 experiences.** Unlock new experiences such as peer-to-peer social coordination using incentive trees, or recurring subscription payments that don't require users to connect to the dapp. - **Uninterrupted user experiences.** Keep users immersed in the dapp by embedding the wallet experience and reassigning gas costs to where they make sense. The toolkit includes the [Delegation Framework](https://docs.gator.metamask.io/development/concepts/delegation#delegation-framework) – a pioneering set of open-source, customizable smart contracts, allowing dapps and protocols to implement custom permission control. Developers can use the Delegation Framework to prepare their dapps for [delegations](https://docs.gator.metamask.io/development/concepts/delegation) created from [delegator accounts](https://docs.gator.metamask.io/development/concepts/delegator-accounts). ## Where do I start? [​](https://docs.gator.metamask.io/development\#where-do-i-start "Direct link to Where do I start?") Check out the following sections to get started with the MetaMask Delegation Toolkit: [**🏁 Get started** \\ If you're ready to get started building, install the Toolkit and follow a quickstart.](https://docs.gator.metamask.io/get-started)[**πŸ› οΈ How-to guides** \\ To complete specific tasks with the Delegation Toolkit, follow the how-to guides.](https://docs.gator.metamask.io/how-to)[**πŸ’­ Concepts** \\ If you're new to the Delegation Toolkit, learn about some key concepts.](https://docs.gator.metamask.io/concepts) ## Questions? [​](https://docs.gator.metamask.io/development\#questions "Direct link to Questions?") If you have questions, email [hellogators@consensys.net](mailto:hellogators@consensys.net). - [Why use the toolkit?](https://docs.gator.metamask.io/development#why-use-the-toolkit) - [Where do I start?](https://docs.gator.metamask.io/development#where-do-i-start) - [Questions?](https://docs.gator.metamask.io/development#questions) ## MetaMask Chatbot [Skip to main content](https://docs.gator.metamask.io/development/chatbot#__docusaurus_skipToContent_fallback) This is a public beta release of the MetaMask Delegation Toolkit. This is the development version of the documentation and some features may not yet be available in the latest release. You can switch to the [latest version](https://docs.gator.metamask.io/chatbot) (0.10.2). # Chatbot Consensys Docsbot ### Consensys Documentation Chatbot * * * Hello I am an AI chatbot! My features are still experimental and I can provide assistance with questions about MetaMask Delegation Toolkit, its features or usage instructions. Be sure to check the source documentation links that I provide for full details. Please help me enhance my AI's effectiveness by clicking πŸ‘ for helpful responses and πŸ‘Ž for inaccurate ones. Please do not input any of your own or another's personal information. If you need support and do not want to engage with me, please reach out to us via [Discord](https://discord.com/invite/bZwrf3x4Vs). I am powered by Microsoft and any information that you provide is not used for training my AI systems. For details on our data handling practices, see our [Privacy Policy](https://consensys.io/privacy-policy) By proceeding you acknowledge the above. Proceed Not sure what to ask? Try the following: - How can I get started with the MetaMask Delegation Toolkit? ## MetaMask Delegation Toolkit [Skip to main content](https://docs.gator.metamask.io/development/concepts#__docusaurus_skipToContent_fallback) This is a public beta release of the MetaMask Delegation Toolkit. This is the development version of the documentation and some features may not yet be available in the latest release. You can switch to the [latest version](https://docs.gator.metamask.io/concepts) (0.10.2). [**πŸ“„οΈDelegator accounts** \\ Learn about account abstraction, the delegator account flow, and account types.](https://docs.gator.metamask.io/development/concepts/delegator-accounts)[**πŸ“„οΈDelegation** \\ Learn about delegation, the delegation lifecycle, and the Delegation Framework.](https://docs.gator.metamask.io/development/concepts/delegation)[**πŸ“„οΈDelegator environment** \\ Learn about the delegator environment object \`DeleGatorEnvironment\` and how to use it.](https://docs.gator.metamask.io/development/concepts/environment)[**πŸ“„οΈCaveat enforcers** \\ Learn about caveat enforcers and how they restrict delegations.](https://docs.gator.metamask.io/development/concepts/caveat-enforcers) ## Caveat Enforcers Overview [Skip to main content](https://docs.gator.metamask.io/development/concepts/caveat-enforcers#__docusaurus_skipToContent_fallback) This is a public beta release of the MetaMask Delegation Toolkit. This is the development version of the documentation and some features may not yet be available in the latest release. You can switch to the [latest version](https://docs.gator.metamask.io/concepts/caveat-enforcers) (0.10.2). On this page # 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](https://docs.gator.metamask.io/development/concepts/delegation#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. 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 [​](https://docs.gator.metamask.io/development/concepts/caveat-enforcers\#smart-contract-interface "Direct link to 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: ```codeBlockLines_e6Vv // 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 [​](https://docs.gator.metamask.io/development/concepts/caveat-enforcers\#caveat-enforcer-rejection "Direct link to 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 [​](https://docs.gator.metamask.io/development/concepts/caveat-enforcers\#caveat-builder "Direct link to Caveat builder") While caveat enforcers operate at the smart contract level, most developers interact with them through the [`CaveatBuilder`](https://docs.gator.metamask.io/development/how-to/create-delegation/restrict-delegation) 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](https://docs.gator.metamask.io/development/how-to/create-delegation/restrict-delegation#caveat-types) in the `CaveatBuilder` corresponds to a specific caveat enforcer contract. For example, when you use: ```codeBlockLines_e6Vv caveatBuilder.addCaveat("allowedTargets", ["0xc11F3a8E5C7D16b75c9E2F60d26f5321C6Af5E92"]); ``` The builder is creating a caveat that references the [`AllowedTargetsEnforcer`](https://docs.gator.metamask.io/development/how-to/create-delegation/restrict-delegation#allowedtargets) contract address and properly encodes the provided addresses as terms for that enforcer. ## Caveat enforcer best practices [​](https://docs.gator.metamask.io/development/concepts/caveat-enforcers\#caveat-enforcer-best-practices "Direct link to 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`](https://docs.gator.metamask.io/development/how-to/create-delegation/restrict-delegation#nativetokenpayment) before [`NativeBalanceGteEnforcer`](https://docs.gator.metamask.io/development/how-to/create-delegation/restrict-delegation#nativebalancegte) might cause validation failures. - **Be careful with unbounded delegations** \- Always include appropriate caveat enforcers to limit what a delegate can do. ## Available caveat enforcers [​](https://docs.gator.metamask.io/development/concepts/caveat-enforcers\#available-caveat-enforcers "Direct link to Available caveat enforcers") The Delegation Toolkit provides [many out-of-the-box caveat enforcers](https://docs.gator.metamask.io/development/how-to/create-delegation/restrict-delegation#caveat-types) 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](https://docs.gator.metamask.io/development/how-to/create-delegation/create-custom-caveat-enforcer) by implementing the `ICaveatEnforcer` interface. ## Attenuating authority with redelegations [​](https://docs.gator.metamask.io/development/concepts/caveat-enforcers\#attenuating-authority-with-redelegations "Direct link to Attenuating authority with redelegations") When [creating chains of delegations](https://docs.gator.metamask.io/development/how-to/create-delegation#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 [​](https://docs.gator.metamask.io/development/concepts/caveat-enforcers\#example-narrowing-permissions "Direct link to 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. - [Smart contract interface](https://docs.gator.metamask.io/development/concepts/caveat-enforcers#smart-contract-interface) - [Caveat enforcer rejection](https://docs.gator.metamask.io/development/concepts/caveat-enforcers#caveat-enforcer-rejection) - [Caveat builder](https://docs.gator.metamask.io/development/concepts/caveat-enforcers#caveat-builder) - [Caveat enforcer best practices](https://docs.gator.metamask.io/development/concepts/caveat-enforcers#caveat-enforcer-best-practices) - [Available caveat enforcers](https://docs.gator.metamask.io/development/concepts/caveat-enforcers#available-caveat-enforcers) - [Attenuating authority with redelegations](https://docs.gator.metamask.io/development/concepts/caveat-enforcers#attenuating-authority-with-redelegations) - [Example: Narrowing permissions](https://docs.gator.metamask.io/development/concepts/caveat-enforcers#example-narrowing-permissions) ## MetaMask Delegation Toolkit [Skip to main content](https://docs.gator.metamask.io/development/concepts/delegation#__docusaurus_skipToContent_fallback) This is a public beta release of the MetaMask Delegation Toolkit. This is the development version of the documentation and some features may not yet be available in the latest release. You can switch to the [latest version](https://docs.gator.metamask.io/concepts/delegation) (0.10.2). On this page # Delegation _Delegation_ is the ability for a [delegator account](https://docs.gator.metamask.io/development/concepts/delegator-accounts) to grant permission to another smart contract account (SCA) or externally owned account (EOA) to perform specific executions on the delegator's behalf, under defined rules and restrictions. The MetaMask Delegation Toolkit includes the following delegation features: - **Caveats** \- Users can use [caveat enforcers](https://docs.gator.metamask.io/development/concepts/caveat-enforcers) 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: ```codeBlockLines_e6Vv 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 [​](https://docs.gator.metamask.io/development/concepts/delegation\#delegation-lifecycle "Direct link to 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](https://docs.gator.metamask.io/development/experimental/store-retrieve-delegations) 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](https://docs.gator.metamask.io/development/concepts/delegator-accounts#account-abstraction-erc-4337), which verifies that the delegated authority is valid in order to perform the execution. See [how to create a delegation](https://docs.gator.metamask.io/development/how-to/create-delegation) to get started with the delegation lifecycle. ## Delegation Framework [​](https://docs.gator.metamask.io/development/concepts/delegation\#delegation-framework "Direct link to 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](https://docs.gator.metamask.io/development/concepts/delegator-accounts#account-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](https://docs.gator.metamask.io/development/concepts/caveat-enforcers) manage rules and restrictions for delegations, providing fine-tuned control over delegated executions. - [Delegation lifecycle](https://docs.gator.metamask.io/development/concepts/delegation#delegation-lifecycle) - [Delegation Framework](https://docs.gator.metamask.io/development/concepts/delegation#delegation-framework) ## MetaMask Delegation Toolkit [Skip to main content](https://docs.gator.metamask.io/development/concepts/delegator-accounts#__docusaurus_skipToContent_fallback) This is a public beta release of the MetaMask Delegation Toolkit. This is the development version of the documentation and some features may not yet be available in the latest release. You can switch to the [latest version](https://docs.gator.metamask.io/concepts/delegator-accounts) (0.10.2). On this page # Delegator accounts The MetaMask Delegation Toolkit enables you to create and manage _delegator accounts_. Delegator accounts are [ERC-4337](https://eips.ethereum.org/EIPS/eip-4337) smart contract accounts (SCAs) that support programmable account behavior and advanced features such as multi-signature approvals, automated transaction batching, and custom security policies. Unlike traditional wallets, which rely on private keys for every transaction, MetaMask delegator accounts use smart contracts to govern account logic. ## Account abstraction (ERC-4337) [​](https://docs.gator.metamask.io/development/concepts/delegator-accounts\#account-abstraction-erc-4337 "Direct link to Account abstraction (ERC-4337)") Account abstraction, specified by [ERC-4337](https://eips.ethereum.org/EIPS/eip-4337), is a mechanism that enables users to manage SCAs containing arbitrary verification logic. ERC-4337 enables SCAs to be used as primary accounts in place of traditional private key-based accounts, or externally owned accounts (EOAs). ERC-4337 introduces the following concepts: - **User operation** \- A package of instructions signed by a user, specifying executions for the SCA to perform. User operations are collected and submitted to the network by bundlers. - **Bundler** \- A service that collects multiple user operations, packages them into a single transaction, and submits them to the network, optimizing gas costs and transaction efficiency. - **Entry point contract** \- A contract that validates and processes bundled user operations, ensuring they adhere to the required rules and security checks. - **Paymasters** \- Entities that handle the payment of gas fees on behalf of users, often integrated into SCAs to facilitate gas abstraction. ## Delegator account flow [​](https://docs.gator.metamask.io/development/concepts/delegator-accounts\#delegator-account-flow "Direct link to Delegator account flow") The MetaMask delegator account flow is as follows: 1. **Account setup** \- A user creates an SCA by deploying a smart contract, and initializing it with ownership and security settings. The user can customize the SCA in the following ways: - **Account logic** \- They can configure custom logic for actions such as multi-signature approvals, spending limits, and automated transaction batching. - **Security and recovery** \- They can configure advanced security features such as two-factor authentication and mechanisms for account recovery involving trusted parties. - **Gas management** \- They can configure flexible gas payment options, including alternative tokens or third-party sponsorship. 2. **User operation creation** \- For actions such as sending transactions, a user operation is created with necessary details and signed by the configured signatory. 3. **Bundlers and mempool** \- The signed user operation is submitted to a special mempool, where bundlers collect and package multiple user operations into a single transaction to save on gas costs. 4. **Validation and execution** \- The bundled transaction goes to an entry point contract, which validates each user operation and executes them if they meet the smart contract's rules. ## Delegator account types [​](https://docs.gator.metamask.io/development/concepts/delegator-accounts\#delegator-account-types "Direct link to Delegator account types") The MetaMask Delegation Toolkit supports two types of delegator accounts, each offering unique features and use cases. See [Configure accounts and signers](https://docs.gator.metamask.io/development/how-to/configure-delegator-accounts-signers) to learn how to use these different account types. ### Hybrid Delegator [​](https://docs.gator.metamask.io/development/concepts/delegator-accounts\#hybrid-delegator "Direct link to Hybrid Delegator") The Hybrid Delegator is a flexible implementation that supports both an externally owned account (EOA) "owner" and any number of P256 (passkey) signers. You can configure any of these signers as the signatory, and use them to sign on behalf of the delegator. This type is referenced in the toolkit as `Implementation.Hybrid`. ### Multisig Delegator [​](https://docs.gator.metamask.io/development/concepts/delegator-accounts\#multisig-delegator "Direct link to Multisig Delegator") The Multisig Delegator is an implementation that supports multiple signers with a configurable threshold for valid signatures, allowing for enhanced security and flexibility in account management. The signatory must have at least as many signers include as the threshold is configured for the account. This type is referenced in the Toolkit as `Implementation.Multisig`. - [Account abstraction (ERC-4337)](https://docs.gator.metamask.io/development/concepts/delegator-accounts#account-abstraction-erc-4337) - [Delegator account flow](https://docs.gator.metamask.io/development/concepts/delegator-accounts#delegator-account-flow) - [Delegator account types](https://docs.gator.metamask.io/development/concepts/delegator-accounts#delegator-account-types) - [Hybrid Delegator](https://docs.gator.metamask.io/development/concepts/delegator-accounts#hybrid-delegator) - [Multisig Delegator](https://docs.gator.metamask.io/development/concepts/delegator-accounts#multisig-delegator) ## MetaMask Delegation Toolkit [Skip to main content](https://docs.gator.metamask.io/development/concepts/environment#__docusaurus_skipToContent_fallback) This is a public beta release of the MetaMask Delegation Toolkit. This is the development version of the documentation and some features may not yet be available in the latest release. You can switch to the [latest version](https://docs.gator.metamask.io/concepts/environment) (0.10.2). On this page # 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](https://docs.gator.metamask.io/development/concepts/delegation#delegation-framework) on a specific network. The delegator environment serves several key purposes: - It provides a centralized configuration for all the contract addresses required by the Delegation Framework. - It enables easy switching between different networks (for example, Mainnet and testnet) or custom deployments. - It ensures consistency across different parts of the application that interact with the Delegation Framework. ## Resolve the delegator environment [​](https://docs.gator.metamask.io/development/concepts/environment\#resolve-the-delegator-environment "Direct link to Resolve the delegator environment") When you create a [`MetaMaskSmartAccount`](https://docs.gator.metamask.io/development/how-to/create-delegator-account) instance, the Delegation Toolkit automatically resolves the environment based on the version it requires and the chain configured. If no environment is found for the specified chain, it throws an error. - example.ts - config.ts ```codeBlockLines_e6Vv import { DeleGatorEnvironment } from "@metamask/delegation-toolkit"; import { delegatorSmartAccount } from "./config.ts"; const environment: DeleGatorEnvironment = delegatorSmartAccount.environment; ``` ```codeBlockLines_e6Vv import { Implementation, toMetaMaskSmartAccount, } from "@metamask/delegation-toolkit"; import { privateKeyToAccount } from "viem/accounts"; import { createPublicClient, http } from "viem"; import { lineaSepolia as chain } from "viem/chains"; const publicClient = createPublicClient({ chain, transport: http(), }); const delegatorAccount = privateKeyToAccount("0x..."); const delegatorSmartAccount = await toMetaMaskSmartAccount({ client: publicClient, implementation: Implementation.Hybrid, deployParams: [delegatorAccount.address, [], [], []], deploySalt: "0x", signatory: { account: delegatorAccount }, }); export delegatorSmartAccount; ``` note See the [changelog](https://docs.gator.metamask.io/0.9.0/changelog/0.9.0) of the toolkit version you are using for supported chains. Alternatively, you can use the `getDelegatorEnvironment` function to resolve the environment. This function is especially useful if your delegator is not a smart contract account when [creating a redelegation](https://docs.gator.metamask.io/development/how-to/create-delegation#create-a-redelegation). ```codeBlockLines_e6Vv import { getDeleGatorEnvironment, DeleGatorEnvironment, } from "@metamask/delegation-toolkit"; // Resolves the DeleGatorEnvironment for Linea Sepolia const environment: DeleGatorEnvironment = getDelegatorEnvironment(59141); ``` ## Deploy custom delegator environment [​](https://docs.gator.metamask.io/development/concepts/environment\#deploy-custom-delegator-environment "Direct link to Deploy custom delegator environment") You can deploy the contracts using any method, but the toolkit provides a convenient `deployDelegatorEnvironment` function. This function simplifies deploying the Delegation Framework contracts to your desired EVM chain. This function requires a Viem [Public Client](https://viem.sh/docs/clients/public.html), [Wallet Client](https://viem.sh/docs/clients/wallet.html), and [Chain](https://viem.sh/docs/glossary/types#chain) to deploy the contracts and resolve the `DeleGatorEnvironment`. Your wallet must have sufficient native token balance to deploy the contracts. - example.ts - config.ts ```codeBlockLines_e6Vv import { walletClient, publicClient } from "./config.ts"; import { lineaSepolia as chain } from "viem/chains"; const environment = await deployDeleGatorEnvironment( walletClient, publicClient, chain ); ``` ```codeBlockLines_e6Vv import { privateKeyToAccount } from "viem/accounts"; import { lineaSepolia as chain } from "viem/chains"; import { http, createWalletClient, createPublicClient } from "viem"; // Your deployer wallet private key. const privateKey = "0x123.."; const account = privateKeyToAccount(privateKey); export const walletClient = createWalletClient({ account, chain, transport: http() }); export const publicClient = createPublicClient({ transport: http(), chain, }); ``` You can also override specific contracts when calling `deployDelegatorEnvironment`. For example, if you've already deployed the `EntryPoint` contract on the target chain, you can pass the contract address to the function. ```codeBlockLines_e6Vv // The config.ts is the same as in the previous example. import { walletClient, publicClient } from "./config.ts"; import { lineaSepolia as chain } from "viem/chains"; const environment = await deployDeleGatorEnvironment( walletClient, publicClient, chain, + { + EntryPoint: "0x0000000071727De22E5E9d8BAf0edAc6f37da032" + } ); ``` Once the contracts are deployed, you can use them to override the delegator environment. ## Override delegator environment [​](https://docs.gator.metamask.io/development/concepts/environment\#override-delegator-environment "Direct link to Override delegator environment") To override the delegator environment, the toolkit provides a `overrideDeployedEnvironment` function to resolve `DeleGatorEnvironment` with specified contracts for the given chain and contract version. ```codeBlockLines_e6Vv // The config.ts is the same as in the previous example. import { walletClient, publicClient } from "./config.ts"; import { lineaSepolia as chain } from "viem/chains"; import { DeleGatorEnvironment, overrideDeployedEnvironment, deployDeleGatorEnvironment } from "@metamask/delegation-toolkit"; const environment: DeleGatorEnvironment = await deployDeleGatorEnvironment( walletClient, publicClient, chain ); const delegatorEnvironment: DeleGatorEnvironment = overrideDeployedEnvironment( chainId, "1.3.0", environment, ); ``` If you've already deployed the contracts using a different method, you can create a `DelegatorEnvironment` instance with the required contract addresses, and pass it to the function. ```codeBlockLines_e6Vv - import { walletClient, publicClient } from "./config.ts"; - import { lineaSepolia as chain } from "viem/chains"; import { DeleGatorEnvironment, overrideDeployedEnvironment, - deployDeleGatorEnvironment } from "@metamask/delegation-toolkit"; - const environment: DeleGatorEnvironment = await deployDeleGatorEnvironment( - walletClient, - publicClient, - chain - ); + const evniroment: DeleGatorEnvironment = { + SimpleFactory: "0x124..", + // ... + implementations: { + // ... + }, + }; const delegatorEnvironment: DeleGatorEnvironment = overrideDeployedEnvironment( chainId, "1.3.0", environment ); ``` note Make sure to specify the Delegation Framework version required by the toolkit. See the [changelog](https://docs.gator.metamask.io/0.9.0/changelog/0.9.0) of the toolkit version you are using for its required Framework version. - [Resolve the delegator environment](https://docs.gator.metamask.io/development/concepts/environment#resolve-the-delegator-environment) - [Deploy custom delegator environment](https://docs.gator.metamask.io/development/concepts/environment#deploy-custom-delegator-environment) - [Override delegator environment](https://docs.gator.metamask.io/development/concepts/environment#override-delegator-environment) ## MetaMask Delegation Toolkit [Skip to main content](https://docs.gator.metamask.io/development/experimental#__docusaurus_skipToContent_fallback) This is a public beta release of the MetaMask Delegation Toolkit. This is the development version of the documentation and some features may not yet be available in the latest release. You can switch to the [latest version](https://docs.gator.metamask.io/experimental) (0.10.2). [**πŸ“„οΈStore and retrieve delegations** \\ Store and retrieve delegations using the \`DelegationStorageClient\`.](https://docs.gator.metamask.io/development/experimental/store-retrieve-delegations)[**πŸ“„οΈERC-7715: Request permissions** \\ Learn how to request ERC-7715 permissions.](https://docs.gator.metamask.io/development/experimental/erc-7715-request-permissions)[**πŸ“„οΈERC-7710: Redeem delegations** \\ Learn how to redeem ERC-7710 delegations with a smart contract account or an externally owned account (EOA).](https://docs.gator.metamask.io/development/experimental/erc-7710-redeem-delegations) ## MetaMask ERC-7710 Delegations [Skip to main content](https://docs.gator.metamask.io/development/experimental/erc-7710-redeem-delegations#__docusaurus_skipToContent_fallback) This is a public beta release of the MetaMask Delegation Toolkit. This is the development version of the documentation and some features may not yet be available in the latest release. You can switch to the [latest version](https://docs.gator.metamask.io/experimental/erc-7710-redeem-delegations) (0.10.2). On this page # ERC-7710: Redeem delegations Experimental This is an experimental feature and may change in future releases. [ERC-7710](https://eip.tools/eip/7710) introduces a standard way for smart contract accounts (SCAs) to delegate capabilities to other SCAs or externally owned accounts (EOAs). The MetaMask Delegation Toolkit provides two experimental functions, `erc7710BundlerActions()` and `erc7710WalletActions()`, that let a caller redeem delegations granted by MetaMask's permissions system. ## Extract relevant data [​](https://docs.gator.metamask.io/development/experimental/erc-7710-redeem-delegations\#extract-relevant-data "Direct link to Extract relevant data") Refer to [ERC-7715: Request permissions](https://docs.gator.metamask.io/development/experimental/erc-7715-request-permissions) for information on how to request user permissions. Once the permission has been granted, extract the relevant data from the response. For example: ```codeBlockLines_e6Vv // Response received from the ERC-7715 wallet_grantPermissions request. const permissionsResponse = [{\ chainId: "0xe715",\ account: "0xD6f56C2B10b1e02D841E4a97c60Afe914E884DBd",\ expiry: 1234567890,\ permission: {\ type: "native-token-stream",\ data: {\ amountPerSecond: "0x1",\ maxAmount: "0x2",\ initialAmount: undefined,\ startTime: 2,\ },\ },\ context: "0x1a2b3c4d5e6f7a8b9c0d1e2f3a4b5c6d7e8f9a0b1c2d3e4f5a6b7c8d9e0f1a2b3c4d5e6f7a8b9c0d1e2f3a4b5c6d7e8f9a0b1c2d3e4f5a6b7c8d9e0f1a2b3c4d5e6f7a8b9c0d1e2f3a4b5c6d7e8f9a0b1c2d3e4f5a6b7c8d9e0f1a2b3c4d"\ signer: {\ type: "account",\ data: {\ account: "0x07bfc7230D5BD2544059816D88A895BB000Abe00"\ }\ },\ signerMeta: {\ delegationManager: "0xDC7e12b41E5e61BfCc7F56AAFB7B93288F61e841"\ },\ accountMetadata: [{\ factory: "0x65E726b404149fE37F4b291c81Dc6eddd44763A7",\ factoryData: "0x1a2b3c4d5e6f7a8b9c0d1e2f3a4b5c6d7e8f9a0b1c2d3e4f5a6b7c8d9e0f1a2b3c4d5e6f7a8b9c0d1e2f3a4b5c6d7e8f9a0b1c2d3e4f5a6b7c8d9e0f1a2b3c4d5e6f7a8b9c0d1e2f3a4b5c6d7e8f9a0b1c2d3e4f5a6b7c8d9e0f1a2b"\ }]\ }]; const permissionsContext = permissionsResponse[0].context; const delegationManager = permissionsResponse[0].signerMeta.delegationManager; // accountMeta is only present when the smart contract account is not deployed. const accountMetadata = permissionsResponse[0].accountMeta; ``` This data encodes the authority that lets the delegate redeem the permission. ### Security considerations for `accountMeta` [​](https://docs.gator.metamask.io/development/experimental/erc-7710-redeem-delegations\#security-considerations-for-accountmeta "Direct link to security-considerations-for-accountmeta") When a user grants a permission, they can provide `accountMeta` which is an array of `factory` and `factoryData` values. These calls must be executed before redeeming the permission (this is handled for you in `sendUserOperationWithDelegation`). Because each `accountMeta` is an arbitrary call specified by the granter, it is important that these are executed carefully. We recommend taking the following precautions: - **Only grant permissions to session accounts** \- When requesting permissions, use an account that is only used for that single purpose, and does not contain tokens. This way, any `accountMeta` executed can't perform any damaging actions. - **Only execute `accountMeta` against trusted factory addresses** \- Ensure that only `accountMeta` targeting a known factory address is executed. The bundler action `sendUserOperationWithDelegation` only executes `accountMeta` that targets the `SimpleFactory` address for the current Delegation Framework. If you redeem delegations in any other way, it is your responsibility to validate trusted factory addresses. ## Redeem the permission [​](https://docs.gator.metamask.io/development/experimental/erc-7710-redeem-delegations\#redeem-the-permission "Direct link to Redeem the permission") Redeem a delegation using one of two methods. Choose the method based on your account type: - If redeeming with an SCA, call `sendUserOperationWithDelegation`. - If redeeming with an EOA, call `sendTransactionWithDelegation`. ### Redeem with an SCA [​](https://docs.gator.metamask.io/development/experimental/erc-7710-redeem-delegations\#redeem-with-an-sca "Direct link to Redeem with an SCA") To redeem a delegation with a smart contract account, create a [`MetaMaskSmartAccount`](https://docs.gator.metamask.io/how-to/create-delegator-account#create-a-metamasksmartaccount) and a [Viem Bundler Client](https://viem.sh/account-abstraction/clients/bundler). After setting up your Bundler Client, you can extend its functionality with `erc7710BundlerActions` actions to support ERC-7710. Once extended, use `sendUserOperationWithDelegation` to redeem the permission. - example.ts - config.ts ```codeBlockLines_e6Vv import { sessionAccount, bundlerClient, publicClient } from "./config.ts"; // These properties must be extracted from the permission response. const permissionsContext = permissionsResponse[0].context; const delegationManager = permissionsResponse[0].signerMeta.delegationManager; const accountMetadata = permissionsResponse[0].accountMeta; // Calls without permissionsContext and delegationManager will be executed // as a normal user operation. const userOperationHash = await bundlerClient.sendUserOperationWithDelegation({ publicClient, account: sessionAccount, calls: [\ {\ to: sessionAccount.address,\ data: "0x",\ value: 1n,\ permissionsContext,\ delegationManager,\ },\ ], // Appropriate values must be used for fee-per-gas. maxFeePerGas: 1n, maxPriorityFeePerGas: 1n accountMetadata, }); ``` ```codeBlockLines_e6Vv import { createPublicClient, http, createBundlerClient } from "viem"; import { generatePrivateKey, privateKeyToAccount } from "viem/accounts"; import { sepolia as chain } from "viem/chains"; import { createBundlerClient } from "viem/account-abstraction"; import { erc7710BundlerActions } from "@metamask/delegation-toolkit/experimental"; import { toMetaMaskSmartAccount, Implementation } from "@metamask/delegation-toolkit"; export const publicClient = createPublicClient({ chain: chain, transport: http(), }); // Your session account for requesting and redeeming should be same. const privateKey = "0x..."; const account = privateKeyToAccount(privateKey); export const sessionAccount = await toMetaMaskSmartAccount({ client: publicClient, implementation: Implementation.Hybrid, deployParams: [account.address, [], [], []], deploySalt: "0x", signatory: { account }, }); export const bundlerClient = createBundlerClient({ transport: http( `https://your-bundler-url` ), // Allows you to use the same Bundler Client as paymaster. paymaster: true }).extend(erc7710BundlerActions()); ``` note `sendUserOperationWithDelegation` is similar to the `sendUserOperation` function, but does not accept `callData` directly. ### Redeem with an EOA [​](https://docs.gator.metamask.io/development/experimental/erc-7710-redeem-delegations\#redeem-with-an-eoa "Direct link to Redeem with an EOA") To redeem a delegation with an EOA, create a [Viem Wallet Client](https://viem.sh/docs/clients/wallet). After creating your Wallet Client, you can extend its functionality with `erc7710WalletActions` actions to support ERC-7710. Once extended, use `sendTransactionWithDelegation` to redeem the permission. - example.ts - config.ts ```codeBlockLines_e6Vv import { walletClient, publicClient } from "./config.ts"; // These properties must be extracted from the permission response. const permissionsContext = permissionsResponse[0].context; const delegationManager = permissionsResponse[0].signerMeta.delegationManager; const accountMetadata = permissionsResponse[0].accountMeta; if (accountMetadata?.length !== 0) { // If the granted permission contains accountMetadata, this must be executed before attempting to // redeem the delegation. // This transaction will deploy the delegator account. const hash = walletClient.sendTransaction({ to: accountMetadata.factory, data: accountMetadata.factoryData, }); // You should wait for transaction to be successfully executed. // You can use the TransactionReceipt.status to verify the state. await publicClient.waitForTransactionReceipt( { hash }); } const hash = walletClient.sendTransactionWithDelegation({ chain, to: "0x70997970c51812dc3a010c7d01b50e0d17dc79c8", value: 1n, permissionsContext, delegationManager }); ``` ```codeBlockLines_e6Vv import { http, createPublicClient } from "viem"; import { generatePrivateKey, privateKeyToAccount } from "viem/accounts"; import { sepolia as chain } from "viem/chains"; import { erc7710WalletActions } from "@metamask/delegation-toolkit/experimental"; export const publicClient = createPublicClient({ chain, transport: http() }); // Your session account for requesting and redeeming should be same. const privateKey = "0x..."; const account = privateKeyToAccount(privateKey); const walletClient = createWalletClient({ account, transport: http(), chain, }).extend(erc7710WalletActions()); ``` - [Extract relevant data](https://docs.gator.metamask.io/development/experimental/erc-7710-redeem-delegations#extract-relevant-data) - [Security considerations for `accountMeta`](https://docs.gator.metamask.io/development/experimental/erc-7710-redeem-delegations#security-considerations-for-accountmeta) - [Redeem the permission](https://docs.gator.metamask.io/development/experimental/erc-7710-redeem-delegations#redeem-the-permission) - [Redeem with an SCA](https://docs.gator.metamask.io/development/experimental/erc-7710-redeem-delegations#redeem-with-an-sca) - [Redeem with an EOA](https://docs.gator.metamask.io/development/experimental/erc-7710-redeem-delegations#redeem-with-an-eoa) ## ERC-7715 Wallet Permissions [Skip to main content](https://docs.gator.metamask.io/development/experimental/erc-7715-request-permissions#__docusaurus_skipToContent_fallback) This is a public beta release of the MetaMask Delegation Toolkit. This is the development version of the documentation and some features may not yet be available in the latest release. You can switch to the [latest version](https://docs.gator.metamask.io/experimental/erc-7715-request-permissions) (0.10.2). On this page # ERC-7715: Request permissions Experimental This is an experimental feature. It requires MetaMask Flask 12.14.2 or later, and may change in future releases. [ERC-7715](https://eip.tools/eip/7715) introduces a standard way for dapps to request permissions from a wallet to execute transactions on a user's behalf. The MetaMask Delegation Toolkit provides the experimental actions for ERC-7715 that lets a caller request permissions from MetaMask's permissions system. ## Request permissions [​](https://docs.gator.metamask.io/development/experimental/erc-7715-request-permissions\#request-permissions "Direct link to Request permissions") To request permissions, extend your [Viem Wallet Client](https://viem.sh/docs/clients/wallet) with `erc7715ProviderActions` actions. You'll need a session account to request the permission, which can be either an externally owned account (EOA) or a smart contract account (SCA). This example uses an SCA: - example.ts - config.ts ```codeBlockLines_e6Vv import { sepolia as chain } from "viem/chains"; import { sessionAccount, walletClient } from "./config.ts"; const expiry = Math.floor(Date.now() / 1000 + 604_800); // 1 week from now. const currentTime = Math.floor(Date.now() / 1000); // now const grantedPermissions = await walletClient.grantPermissions([{\ chainId: chain.id,\ expiry,\ signer: {\ type: "account",\ data: {\ address: sessionAccount.address,\ },\ },\ permission: {\ type: "native-token-stream",\ data: {\ initialAmount: 1n, // 1 wei\ amountPerSecond: 1n, // 1 wei per second\ maxAmount: 10n, // 10 wei\ startTime: currentTime,\ justification: "Payment for a week long subscription",\ },\ },\ }]); ``` ```codeBlockLines_e6Vv import { createWalletClient, custom, createPublicClient, http } from "viem"; import { generatePrivateKey, privateKeyToAccount } from "viem/accounts"; import { sepolia as chain } from "viem/chains"; import { erc7715ProviderActions } from "@metamask/delegation-toolkit/experimental"; import { toMetaMaskSmartAccount, Implementation } from "@metamask/delegation-toolkit"; const publicClient = createPublicClient({ chain: chain, transport: http(), }); // The private key of the session owner. const privateKey = "0x..."; const account = privateKeyToAccount(privateKey); export const sessionAccount = await toMetaMaskSmartAccount({ client: publicClient, implementation: Implementation.Hybrid, deployParams: [account.address, [], [], []], deploySalt: "0x", signatory: { account }, }); export const walletClient = createWalletClient({ transport: custom(window.ethereum), }).extend(erc7715ProviderActions()); ``` ERC-7715 request permission sample Here's what your ERC-7715 native token streaming allowance request looks like: ```codeBlockLines_e6Vv [{\ chainId: "0xaa36a7",\ expiry: 1745041429,\ permission: {\ type: "native-token-stream",\ data: {\ amountPerSecond: "0x1",\ maxAmount: "0x1",\ initialAmount: "0xa",\ startTime: 1744955029,\ justification: "Payment for a week long subscription",\ },\ },\ signer: {\ type: "account",\ data: {\ address: "0x1234...",\ },\ },\ }] ``` Learn more about the [ERC-7715 permission schema](https://eip.tools/eip/7715). Additionally, you can allow users to modify the requested permission by setting the `isAdjustmentAllowed` parameter to `true` in the request. ```codeBlockLines_e6Vv import { sepolia as chain } from "viem/chains"; // The config.ts is the same as in the previous example. import { sessionAccount, walletClient } from "./config.ts"; const expiry = Math.floor(Date.now() / 1000 + 604_800); // 1 week from now. const currentTime = Math.floor(Date.now() / 1000); // now const grantedPermissions = await walletClient.grantPermissions([{\ chainId: chain.id,\ expiry,\ signer: {\ type: "account",\ data: {\ address: sessionAccount.address,\ },\ },\ permission: {\ type: "native-token-stream",\ + isAdjustmentAllowed: true,\ data: {\ initialAmount: 1n, // 1 wei\ amountPerSecond: 1n, // 1 wei per second\ maxAmount: 10n, // 10 wei\ startTime: currentTime,\ justification: "Payment for a week long subscription",\ },\ },\ }]); ``` note Users have full control over the permissions they grantβ€”depending on the permission you request, they may choose to grant more limited permissions than requested. You should always verify the granted permissions and adjust your dapp's behavior accordingly. ## Security considerations for `accountMeta` [​](https://docs.gator.metamask.io/development/experimental/erc-7715-request-permissions\#security-considerations-for-accountmeta "Direct link to security-considerations-for-accountmeta") When a user grants a permission, they can provide [`accountMeta`](https://docs.gator.metamask.io/development/experimental/erc-7710-redeem-delegations#extract-relevant-data) which is an array of `factory` and `factoryData` values. These calls must be executed before redeeming the permission (this is handled for you in `sendUserOperationWithDelegation`). Because each `accountMeta` is an arbitrary call specified by the granter, it is important that these are executed carefully. We recommend taking the following precautions: - **Only grant permissions to session accounts** \- When requesting permissions, use an account that is only used for that single purpose, and does not contain tokens. This way, any `accountMeta` executed can't perform any damaging actions. - **Only execute `accountMeta` against trusted factory addresses** \- Ensure that only `accountMeta` targeting a known factory address is executed. The bundler action `sendUserOperationWithDelegation` only executes `accountMeta` that targets the `SimpleFactory` address for the current Delegation Framework. If you redeem delegations in any other way, it is your responsibility to validate trusted factory addresses. ## Next steps [​](https://docs.gator.metamask.io/development/experimental/erc-7715-request-permissions\#next-steps "Direct link to Next steps") You can redeem the granted permission using the experimental [ERC-7710 `erc7710WalletActions()`](https://docs.gator.metamask.io/development/experimental/erc-7710-redeem-delegations). - [Request permissions](https://docs.gator.metamask.io/development/experimental/erc-7715-request-permissions#request-permissions) - [Security considerations for `accountMeta`](https://docs.gator.metamask.io/development/experimental/erc-7715-request-permissions#security-considerations-for-accountmeta) - [Next steps](https://docs.gator.metamask.io/development/experimental/erc-7715-request-permissions#next-steps) ## MetaMask Delegation Toolkit [Skip to main content](https://docs.gator.metamask.io/development/experimental/store-retrieve-delegations#__docusaurus_skipToContent_fallback) This is a public beta release of the MetaMask Delegation Toolkit. This is the development version of the documentation and some features may not yet be available in the latest release. You can switch to the [latest version](https://docs.gator.metamask.io/experimental/store-retrieve-delegations) (0.10.2). On this page # Store and retrieve delegations Experimental 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](https://docs.gator.metamask.io/concepts/delegation). ## Prerequisites [​](https://docs.gator.metamask.io/development/experimental/store-retrieve-delegations\#prerequisites "Direct link to Prerequisites") - [Install and set up the Delegation Toolkit.](https://docs.gator.metamask.io/development/get-started/install-delegation-toolkit) - [Configure the Delegation Toolkit.](https://docs.gator.metamask.io/development/how-to/configure-delegation-toolkit) - Ensure you have an API key and API key ID to interact with the `DelegationStorageClient`. If you need to gain access, email [hellogators@consensys.net](mailto:hellogators@consensys.net). ## Configure the storage client [​](https://docs.gator.metamask.io/development/experimental/store-retrieve-delegations\#configure-the-storage-client "Direct link to Configure the storage client") Create the `DelegationStorageClient` instance, and configure it using your API key and API key ID. ```codeBlockLines_e6Vv import { DelegationStorageClient, DelegationStorageEnvironment } from "@metamask/delegation-toolkit/experimental"; const delegationStorageClient = new DelegationStorageClient({ apiKey: "", apiKeyId: "", environment: DelegationStorageEnvironment.prod }); ``` ## Store a delegation [​](https://docs.gator.metamask.io/development/experimental/store-retrieve-delegations\#store-a-delegation "Direct link to Store a delegation") To store a delegation, use the `storeDelegation` method of the `DelegationStorageClient`. This method takes one parameter: 1. `delegation` \- A `Delegation` object representing the delegation to be stored. ### Example [​](https://docs.gator.metamask.io/development/experimental/store-retrieve-delegations\#example "Direct link to Example") - example.ts - config.ts ```codeBlockLines_e6Vv import { delegationStorageClient } from "./config.ts"; const delegationHash = await delegationStorageClient.storeDelegation(delegation); ``` ```codeBlockLines_e6Vv import { DelegationStorageClient, DelegationStorageEnvironment } from "@metamask/delegation-toolkit/experimental"; export const delegationStorageClient = new DelegationStorageClient({ apiKey: "", apiKeyId: "", environment: DelegationStorageEnvironment.prod }); ``` ## Retrieve a delegation chain [​](https://docs.gator.metamask.io/development/experimental/store-retrieve-delegations\#retrieve-a-delegation-chain "Direct link to Retrieve a delegation chain") To retrieve a delegation chain, use the `getDelegationChain` method of the `DelegationStorageClient`. This method takes one parameter: 1. `leafDelegationOrDelegationHash` \- Either a `Delegation` object or the delegation hash as a hex string. note A delegation can be a root delegation, where its `authority` is `0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff`. It can also be a child of another delegation, where its `authority` is the hash of its parent delegation. This method returns the delegation referenced by `leafDelegationOrDelegationHash` and any ancestors. ### Example [​](https://docs.gator.metamask.io/development/experimental/store-retrieve-delegations\#example-1 "Direct link to Example") - example.ts - config.ts ```codeBlockLines_e6Vv import { delegationStorageClient } from "./config.ts"; import { getDelegationHashOffchain } from "@metamask/delegation-toolkit"; // Assuming you have the leaf delegation const delegationHash = getDelegationHashOffchain(leafDelegation); const delegationChain: Delegation[] = await delegationStorageClient.getDelegationChain( delegationHash ); ``` ```codeBlockLines_e6Vv import { DelegationStorageClient, DelegationStorageEnvironment } from "@metamask/delegation-toolkit/experimental"; export const delegationStorageClient = new DelegationStorageClient({ apiKey: "", apiKeyId: "", environment: DelegationStorageEnvironment.prod }); ``` ## Retrieve delegations for a specific account [​](https://docs.gator.metamask.io/development/experimental/store-retrieve-delegations\#retrieve-delegations-for-a-specific-account "Direct link to Retrieve delegations for a specific account") To retrieve delegations stored for a specific account, use the `fetchDelegations` method of the `DelegationStorageClient`. This method allows you to fetch delegations where the specified account is either the delegator or the delegate. It takes two parameters: 1. `account` \- The address of the account for which you want to retrieve delegations. 2. `filter` \- The nature of the delegations. Possible values are: - `DelegationStoreFilter.Given` \- For delegations where the specified `account` is the `delegator`. - `DelegationStoreFilter.Received` \- For delegations where the specified `account` is the `delegate`. ### Example [​](https://docs.gator.metamask.io/development/experimental/store-retrieve-delegations\#example-2 "Direct link to Example") - example.ts - config.ts ```codeBlockLines_e6Vv import { delegationStorageClient } from "./config.ts"; const address = "0x027aeAFF3E5C33c4018FDD302c20a1B83aDCD96C" // Fetch the delegations given by address. const grantedDelegations = await delegationStorageClient.fetchDelegations( address, DelegationStoreFilter.Given, ); // Fetch the delegations received by the address. const receivedDelegations = await delegationStore.fetchDelegations( address, DelegationStoreFilter.Received, ); ``` ```codeBlockLines_e6Vv import { DelegationStorageClient, DelegationStorageEnvironment } from "@metamask/delegation-toolkit/experimental"; export const delegationStorageClient = new DelegationStorageClient({ apiKey: "", apiKeyId: "", environment: DelegationStorageEnvironment.prod }); ``` - [Prerequisites](https://docs.gator.metamask.io/development/experimental/store-retrieve-delegations#prerequisites) - [Configure the storage client](https://docs.gator.metamask.io/development/experimental/store-retrieve-delegations#configure-the-storage-client) - [Store a delegation](https://docs.gator.metamask.io/development/experimental/store-retrieve-delegations#store-a-delegation) - [Retrieve a delegation chain](https://docs.gator.metamask.io/development/experimental/store-retrieve-delegations#retrieve-a-delegation-chain) - [Retrieve delegations for a specific account](https://docs.gator.metamask.io/development/experimental/store-retrieve-delegations#retrieve-delegations-for-a-specific-account) ## MetaMask Toolkit Guide [Skip to main content](https://docs.gator.metamask.io/development/get-started#__docusaurus_skipToContent_fallback) This is a public beta release of the MetaMask Delegation Toolkit. This is the development version of the documentation and some features may not yet be available in the latest release. You can switch to the [latest version](https://docs.gator.metamask.io/get-started) (0.10.2). [**πŸ“„οΈInstall and set up** \\ Learn how to install and set up the MetaMask Delegation Toolkit.](https://docs.gator.metamask.io/development/get-started/install-delegation-toolkit)[**πŸ“„οΈQuickstart** \\ Get started quickly with the MetaMask Delegation Toolkit.](https://docs.gator.metamask.io/development/get-started/delegation-toolkit-quickstart)[**πŸ“„οΈCLI quickstart** \\ Get started with the MetaMask Delegation Toolkit using the \`create-gator-app\` CLI.](https://docs.gator.metamask.io/development/get-started/delegation-toolkit-cli-quickstart)[**πŸ“„οΈLLM context** \\ Context about the MetaMask Delegation Toolkit that can be provided to an LLM.](https://docs.gator.metamask.io/development/get-started/delegation-toolkit-llm-context) ## MetaMask Delegation Toolkit [Skip to main content](https://docs.gator.metamask.io/development/get-started/delegation-toolkit-cli-quickstart#__docusaurus_skipToContent_fallback) This is a public beta release of the MetaMask Delegation Toolkit. This is the development version of the documentation and some features may not yet be available in the latest release. You can switch to the [latest version](https://docs.gator.metamask.io/) (0.10.2). On this page # Delegation Toolkit CLI quickstart Use the `create-gator-app` interactive CLI to bootstrap a project with the MetaMask Delegation Toolkit in under two minutes. The CLI automatically installs the required dependencies and sets up a project structure using a selected template, allowing you to focus on building your dapp. ## Run the CLI [​](https://docs.gator.metamask.io/development/get-started/delegation-toolkit-cli-quickstart\#run-the-cli "Direct link to Run the CLI") Run the following command to automatically install the `create-gator-app` package: ```codeBlockLines_e6Vv npx create-gator-app@latest ``` Upon installation, you'll be asked the following prompts: ```codeBlockLines_e6Vv ? What is your project named? (my-gator-app) ? Pick a framework: (Use arrow keys) ❯ nextjs vite-react ? Pick a template: (Use arrow keys) ❯ Basic Delegator app with NextJS Experimental: Basic Gator app to try out ERC7715 Permissions ? Pick a package manager: (Use arrow keys) ❯ npm yarn pnpm ``` Once you've answered the prompts with the required configuration and selected a template, the CLI will create the project using the specified name and settings. See the following section to learn more about available CLI configurations. ## Options [​](https://docs.gator.metamask.io/development/get-started/delegation-toolkit-cli-quickstart\#options "Direct link to Options") The CLI provides the following options to display CLI details, and further customize the template configuration. | Option | Description | | --- | --- | | `-v` or `--version` | Check the current version of the `create-gator-app` CLI. | | `-h` or `--help` | Display the available options. | | `--skip-install` | Skip the installation of dependencies. | | `--add-web3auth` | Add Web3Auth Embedded Wallet as a signer for the delegator account.
Supported templates:
- Next.js starter
- Vite React starter | | `--add-llm-rules` | Add LLM rules for your IDE. Supported templates:
- Next.js ERC-7715 starter | ## Examples [​](https://docs.gator.metamask.io/development/get-started/delegation-toolkit-cli-quickstart\#examples "Direct link to Examples") ### Web3Auth configuration [​](https://docs.gator.metamask.io/development/get-started/delegation-toolkit-cli-quickstart\#web3auth-configuration "Direct link to Web3Auth configuration") To create a project that uses [Web3Auth](https://web3auth.io/docs/) Embedded Wallet as the signer for your delegator account, use the `--add-web3auth` option with `create-gator-app`: ```codeBlockLines_e6Vv npx create-gator-app --add-web3auth ``` You'll be prompted to provide additional Web3Auth configuration details: ```codeBlockLines_e6Vv ? Which Web3Auth network do you want to use? (Use arrow keys) ❯ Sapphire Devnet Sapphire Mainnet ``` ### LLM rules [​](https://docs.gator.metamask.io/development/get-started/delegation-toolkit-cli-quickstart\#llm-rules "Direct link to LLM rules") To create a project with LLM rules tailored to your preferred IDE, use the `--add-llm-rules` option with `create-gator-app`: ```codeBlockLines_e6Vv npx create-gator-app --add-llm-rules ``` You'll be prompted to select your IDE. Currently, only Cursor and Windsurf are supported. ```codeBlockLines_e6Vv ? Which IDE's LLM rules would you like to copy? (Use arrow keys) Cursor Windsurf ❯ Both ``` ## Supported templates [​](https://docs.gator.metamask.io/development/get-started/delegation-toolkit-cli-quickstart\#supported-templates "Direct link to Supported templates") | Template | Next.js | Vite React | | --- | --- | --- | | Basic dapp with delegation and redeem flow | βœ… | βœ… | | Experimental: Basic dapp with ERC-7715 permissions | βœ… | | - [Run the CLI](https://docs.gator.metamask.io/development/get-started/delegation-toolkit-cli-quickstart#run-the-cli) - [Options](https://docs.gator.metamask.io/development/get-started/delegation-toolkit-cli-quickstart#options) - [Examples](https://docs.gator.metamask.io/development/get-started/delegation-toolkit-cli-quickstart#examples) - [Web3Auth configuration](https://docs.gator.metamask.io/development/get-started/delegation-toolkit-cli-quickstart#web3auth-configuration) - [LLM rules](https://docs.gator.metamask.io/development/get-started/delegation-toolkit-cli-quickstart#llm-rules) - [Supported templates](https://docs.gator.metamask.io/development/get-started/delegation-toolkit-cli-quickstart#supported-templates) ## MetaMask Delegation Toolkit [Skip to main content](https://docs.gator.metamask.io/development/get-started/delegation-toolkit-llm-context#__docusaurus_skipToContent_fallback) This is a public beta release of the MetaMask Delegation Toolkit. This is the development version of the documentation and some features may not yet be available in the latest release. You can switch to the [latest version](https://docs.gator.metamask.io/get-started/delegation-toolkit-llm-context) (0.10.2). # Delegation Toolkit LLM context This website contains [`LLMs.txt`](https://docs.gator.metamask.io/assets/files/llms-09b0393f5a9cf109fd810479a33384ca.txt) and [`LLMs-full.txt`](https://docs.gator.metamask.io/assets/files/llms-full-96b4d69712bfe16e958bc67b7330ab8e.txt) files that are intended for use by large language models (LLMs). They provide information about the content and structure of the MetaMask Delegation Toolkit documentation, to facilitate better indexing, summarization, and understanding by LLMs. You can add these files to an LLM-based tool like [ChatGPT](https://chatgpt.com/) or [Cursor](https://docs.cursor.com/context/@-symbols/@-docs), to provide detailed context about the Delegation Toolkit. You can also ask the [Consensys documentation chatbot](https://docs.gator.metamask.io/development/chatbot) questions about the toolkit. ## MetaMask Delegation Toolkit [Skip to main content](https://docs.gator.metamask.io/development/get-started/delegation-toolkit-quickstart#__docusaurus_skipToContent_fallback) This is a public beta release of the MetaMask Delegation Toolkit. This is the development version of the documentation and some features may not yet be available in the latest release. You can switch to the [latest version](https://docs.gator.metamask.io/get-started/delegation-toolkit-quickstart) (0.10.2). On this page # Delegation Toolkit quickstart This page demonstrates how to get started quickly with the MetaMask Delegation Toolkit, by creating a delegator account and completing the delegation lifecycle (creating, signing, and redeeming a delegation). ## Prerequisites [​](https://docs.gator.metamask.io/development/get-started/delegation-toolkit-quickstart\#prerequisites "Direct link to Prerequisites") [Install and set up the Delegation Toolkit.](https://docs.gator.metamask.io/development/get-started/install-delegation-toolkit) ## Steps [​](https://docs.gator.metamask.io/development/get-started/delegation-toolkit-quickstart\#steps "Direct link to Steps") ### 1\. Set up a Public Client [​](https://docs.gator.metamask.io/development/get-started/delegation-toolkit-quickstart\#1-set-up-a-public-client "Direct link to 1. Set up a Public Client") Set up a [Viem Public Client](https://viem.sh/docs/clients/public) using Viem's `createPublicClient` function. This client will let the delegator account query the signer's account state and interact with smart contracts. ```codeBlockLines_e6Vv import { createPublicClient, http } from "viem"; import { lineaSepolia as chain } from "viem/chains"; const publicClient = createPublicClient({ chain, transport: http(), }); ``` ### 2\. Set up a Bundler Client [​](https://docs.gator.metamask.io/development/get-started/delegation-toolkit-quickstart\#2-set-up-a-bundler-client "Direct link to 2. Set up a Bundler Client") Set up a [Viem Bundler Client](https://viem.sh/account-abstraction/clients/bundler) using Viem's `createBundlerClient` function. This lets you use the bundler service to estimate gas for user operations and submit transactions to the network. ```codeBlockLines_e6Vv import { createBundlerClient } from "viem/account-abstraction"; const bundlerClient = createBundlerClient({ client: publicClient, transport: http("https://your-bundler-rpc.com"), }); ``` ### 3\. Create a delegator account [​](https://docs.gator.metamask.io/development/get-started/delegation-toolkit-quickstart\#3-create-a-delegator-account "Direct link to 3. Create a delegator account") [Create a delegator account](https://docs.gator.metamask.io/development/how-to/create-delegator-account) to set up a delegation. The delegator must be a smart account. This example configures a [Hybrid Delegator](https://docs.gator.metamask.io/development/how-to/configure-delegator-accounts-signers#configure-a-hybrid-delegator): ```codeBlockLines_e6Vv 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 }, }); ``` ### 4\. Create a delegate account [​](https://docs.gator.metamask.io/development/get-started/delegation-toolkit-quickstart\#4-create-a-delegate-account "Direct link to 4. Create a delegate account") Create a delegate account to receive the delegation. The delegate can be either a smart contract account (SCA) or an externally owned account (EOA). This example uses an SCA: ```codeBlockLines_e6Vv 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, deployParams: [delegateAccount.address, [], [], []], deploySalt: "0x", signatory: { account: delegateAccount }, }); ``` ### 5\. Create a delegation [​](https://docs.gator.metamask.io/development/get-started/delegation-toolkit-quickstart\#5-create-a-delegation "Direct link to 5. Create a delegation") [Create a root delegation](https://docs.gator.metamask.io/development/how-to/create-delegation#create-a-root-delegation) from the delegator account to the delegate account. This example passes an empty `caveats` array, which means the delegate can perform any action on the delegator's behalf. We recommend [restricting the delegation](https://docs.gator.metamask.io/development/how-to/create-delegation/restrict-delegation) by adding caveat enforcers. ```codeBlockLines_e6Vv import { createDelegation } from "@metamask/delegation-toolkit"; const delegation = createDelegation({ to: delegateSmartAccount.address, from: delegatorSmartAccount.address, caveats: [] // Empty caveats array - we recommend adding appropriate restrictions. }); ``` ### 6\. Sign the delegation [​](https://docs.gator.metamask.io/development/get-started/delegation-toolkit-quickstart\#6-sign-the-delegation "Direct link to 6. Sign the delegation") [Sign the delegation](https://docs.gator.metamask.io/development/how-to/create-delegation#sign-a-delegation) using the `signDelegation` method from `MetaMaskSmartAccount`. Alternatively, you can use the Delegation Toolkit's `signDelegation` utility. The signed delegation will be used later to perform actions on behalf of the delegator. ```codeBlockLines_e6Vv const signature = await delegatorSmartAccount.signDelegation({ delegation }); const signedDelegation = { ...delegation, signature, }; ``` ### 7\. Redeem the delegation [​](https://docs.gator.metamask.io/development/get-started/delegation-toolkit-quickstart\#7-redeem-the-delegation "Direct link to 7. Redeem the delegation") The delegate account can now [redeem the delegation](https://docs.gator.metamask.io/development/how-to/redeem-delegation). The redeem transaction is sent to the `DelegationManager` contract, which validates the delegation and executes actions on the delegator's behalf. To prepare the call data for the redeem transaction, use the `redeemDelegation` utility function from the Delegation Toolkit. ```codeBlockLines_e6Vv import { createExecution, DelegationFramework, SINGLE_DEFAULT_MODE, } from "@metamask/delegation-toolkit"; import { zeroAddress } from "viem"; const delegations = [ signedDelegation ]; const executions = [{\ target: zeroAddress,\ value: 0n,\ callData: "0x"\ }]; const redeemDelegationCalldata = DelegationFramework.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, }); ``` - [Prerequisites](https://docs.gator.metamask.io/development/get-started/delegation-toolkit-quickstart#prerequisites) - [Steps](https://docs.gator.metamask.io/development/get-started/delegation-toolkit-quickstart#steps) - [1\. Set up a Public Client](https://docs.gator.metamask.io/development/get-started/delegation-toolkit-quickstart#1-set-up-a-public-client) - [2\. Set up a Bundler Client](https://docs.gator.metamask.io/development/get-started/delegation-toolkit-quickstart#2-set-up-a-bundler-client) - [3\. Create a delegator account](https://docs.gator.metamask.io/development/get-started/delegation-toolkit-quickstart#3-create-a-delegator-account) - [4\. Create a delegate account](https://docs.gator.metamask.io/development/get-started/delegation-toolkit-quickstart#4-create-a-delegate-account) - [5\. Create a delegation](https://docs.gator.metamask.io/development/get-started/delegation-toolkit-quickstart#5-create-a-delegation) - [6\. Sign the delegation](https://docs.gator.metamask.io/development/get-started/delegation-toolkit-quickstart#6-sign-the-delegation) - [7\. Redeem the delegation](https://docs.gator.metamask.io/development/get-started/delegation-toolkit-quickstart#7-redeem-the-delegation) ## MetaMask Delegation Toolkit Setup [Skip to main content](https://docs.gator.metamask.io/development/get-started/install-delegation-toolkit#__docusaurus_skipToContent_fallback) This is a public beta release of the MetaMask Delegation Toolkit. This is the development version of the documentation and some features may not yet be available in the latest release. You can switch to the [latest version](https://docs.gator.metamask.io/get-started/install-delegation-toolkit) (0.10.2). On this page # Install and set up the Delegation Toolkit This page provides instructions to install and set up the MetaMask Delegation Toolkit. ## Prerequisites [​](https://docs.gator.metamask.io/development/get-started/install-delegation-toolkit\#prerequisites "Direct link to Prerequisites") - Install [Node.js](https://nodejs.org/en/blog/release/v18.18.0) v18 or later. - 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](https://docs.gator.metamask.io/development/how-to/create-delegation/create-custom-caveat-enforcer)), install [Foundry](https://book.getfoundry.sh/getting-started/installation). ## Steps [​](https://docs.gator.metamask.io/development/get-started/install-delegation-toolkit\#steps "Direct link to Steps") ### 1\. Install the toolkit [​](https://docs.gator.metamask.io/development/get-started/install-delegation-toolkit\#1-install-the-toolkit "Direct link to 1. Install the toolkit") Install the MetaMask Delegation Toolkit dependencies: - npm - Yarn - pnpm ```codeBlockLines_e6Vv npm install @metamask/delegation-toolkit ``` ```codeBlockLines_e6Vv yarn add @metamask/delegation-toolkit ``` ```codeBlockLines_e6Vv pnpm add @metamask/delegation-toolkit ``` ### 2\. (Optional) Install the contracts [​](https://docs.gator.metamask.io/development/get-started/install-delegation-toolkit\#2-optional-install-the-contracts "Direct link to 2. (Optional) Install the contracts") If you plan to extend the Delegation Framework smart contracts (for example, to [create a custom caveat enforcer](https://docs.gator.metamask.io/development/how-to/create-delegation/create-custom-caveat-enforcer)), install the contract package using Foundry's command-line tool, Forge: ```codeBlockLines_e6Vv forge install metamask/delegation-framework@v1.3.0 ``` Add `@metamask/delegation-framework/=lib/metamask/delegation-framework/` in your `remappings.txt` file. ### 3\. Get started [​](https://docs.gator.metamask.io/development/get-started/install-delegation-toolkit\#3-get-started "Direct link to 3. Get started") You're now ready to start using the MetaMask Delegation Toolkit. Check out the [Delegation Toolkit quickstart](https://docs.gator.metamask.io/development/get-started/delegation-toolkit-quickstart) to walk through a simple example. - [Prerequisites](https://docs.gator.metamask.io/development/get-started/install-delegation-toolkit#prerequisites) - [Steps](https://docs.gator.metamask.io/development/get-started/install-delegation-toolkit#steps) - [1\. Install the toolkit](https://docs.gator.metamask.io/development/get-started/install-delegation-toolkit#1-install-the-toolkit) - [2\. (Optional) Install the contracts](https://docs.gator.metamask.io/development/get-started/install-delegation-toolkit#2-optional-install-the-contracts) - [3\. Get started](https://docs.gator.metamask.io/development/get-started/install-delegation-toolkit#3-get-started) ## MetaMask Toolkit Guide [Skip to main content](https://docs.gator.metamask.io/development/how-to#__docusaurus_skipToContent_fallback) This is a public beta release of the MetaMask Delegation Toolkit. This is the development version of the documentation and some features may not yet be available in the latest release. You can switch to the [latest version](https://docs.gator.metamask.io/how-to) (0.10.2). [**πŸ“„οΈConfigure the toolkit** \\ Learn how to configure the MetaMask Delegation Toolkit using Viem.](https://docs.gator.metamask.io/development/how-to/configure-delegation-toolkit)[**πŸ“„οΈCreate a delegator account** \\ Learn how to create a delegator account using Viem.](https://docs.gator.metamask.io/development/how-to/create-delegator-account)[**πŸ“„οΈConfigure accounts and signers** \\ Learn how to configure different types of delegator accounts and signers using Viem.](https://docs.gator.metamask.io/development/how-to/configure-delegator-accounts-signers)[**πŸ“„οΈSend a user operation** \\ Learn how to send an ERC-4337 user operation using Viem.](https://docs.gator.metamask.io/development/how-to/send-user-operation)[**πŸ—ƒοΈCreate a delegation** \\ 2 items](https://docs.gator.metamask.io/development/how-to/create-delegation)[**πŸ“„οΈRedeem a delegation** \\ Learn how to redeem a delegation with a smart contract account (SCA) or an externally owned account (EOA).](https://docs.gator.metamask.io/development/how-to/redeem-delegation) ## MetaMask Delegation Toolkit [Skip to main content](https://docs.gator.metamask.io/development/how-to/configure-delegation-toolkit#__docusaurus_skipToContent_fallback) This is a public beta release of the MetaMask Delegation Toolkit. This is the development version of the documentation and some features may not yet be available in the latest release. You can switch to the [latest version](https://docs.gator.metamask.io/how-to/configure-delegation-toolkit) (0.10.2). On this page # Configure the Delegation Toolkit The MetaMask Delegation Toolkit enables you to easily integrate delegator accounts into your dapp, enabling a more flexible, secure, and frictionless experience for your users. The toolkit is highly configurable, allowing you to tailor it to your project's specific needs. It includes support for custom signers, multiple signatory schemes, custom paymasters and bundlers, and more. note The MetaMask Delegation Toolkit provides custom middleware for [Pimlico's](https://docs.pimlico.io/) gas fee resolver, paymaster, and bundler. Additional options will be made available soon. ## Prerequisites [​](https://docs.gator.metamask.io/development/how-to/configure-delegation-toolkit\#prerequisites "Direct link to Prerequisites") - [Install and set up the Delegation Toolkit](https://docs.gator.metamask.io/development/get-started/install-delegation-toolkit). - Optionally, complete the [Delegation Toolkit quickstart](https://docs.gator.metamask.io/development/get-started/delegation-toolkit-quickstart) to familiarize yourself with the toolkit's capabilities. ## Viem's Account Abstraction API [​](https://docs.gator.metamask.io/development/how-to/configure-delegation-toolkit\#viems-account-abstraction-api "Direct link to Viem's Account Abstraction API") The toolkit uses Viem's Account Abstraction API. This provides a robust and flexible foundation for creating and managing smart contract accounts. See Viem's [Smart Account documentation](https://viem.sh/account-abstraction/accounts/smart) for more information on the API's features, methods, and best practices. ## Configure Viem bundler and paymaster clients [​](https://docs.gator.metamask.io/development/how-to/configure-delegation-toolkit\#configure-viem-bundler-and-paymaster-clients "Direct link to Configure Viem bundler and paymaster clients") To use the bundler and paymaster clients with the toolkit, create instances of these clients and configure them as follows: ```codeBlockLines_e6Vv import { createPaymasterClient, createBundlerClient, } from "viem/account-abstraction"; import { http } from "viem"; import { lineaSepolia as chain } from "viem/chains"; // Replace these URLs with your actual bundler and paymaster endpoints. const bundlerUrl = "https://your-bundler-url.com"; const paymasterUrl = "https://your-paymaster-url.com"; // The paymaster is optional. const paymasterClient = createPaymasterClient({ transport: http(paymasterUrl), }); const bundlerClient = createBundlerClient({ transport: http(bundlerUrl), paymaster: paymasterClient, chain, }); ``` note Providing a paymaster is optional when configuring your bundler client. However, if you choose not to use a paymaster, the smart contract account must have sufficient funds to pay for gas fees directly. - [Prerequisites](https://docs.gator.metamask.io/development/how-to/configure-delegation-toolkit#prerequisites) - [Viem's Account Abstraction API](https://docs.gator.metamask.io/development/how-to/configure-delegation-toolkit#viems-account-abstraction-api) - [Configure Viem bundler and paymaster clients](https://docs.gator.metamask.io/development/how-to/configure-delegation-toolkit#configure-viem-bundler-and-paymaster-clients) ## Delegator Accounts Configuration [Skip to main content](https://docs.gator.metamask.io/development/how-to/configure-delegator-accounts-signers#__docusaurus_skipToContent_fallback) This is a public beta release of the MetaMask Delegation Toolkit. This is the development version of the documentation and some features may not yet be available in the latest release. You can switch to the [latest version](https://docs.gator.metamask.io/how-to/configure-delegator-accounts-signers) (0.10.2). On this page # Configure delegator accounts and signers The MetaMask Delegation Toolkit supports different [delegator account types](https://docs.gator.metamask.io/development/concepts/delegator-accounts#account-types), each with its own configuration and support for different signing mechanisms. You can create flexible and secure delegator accounts tailored to your specific needs. ## Prerequisites [​](https://docs.gator.metamask.io/development/how-to/configure-delegator-accounts-signers\#prerequisites "Direct link to Prerequisites") - [Install and set up the Delegation Toolkit.](https://docs.gator.metamask.io/development/get-started/install-delegation-toolkit) - [Configure the Delegation Toolkit.](https://docs.gator.metamask.io/development/how-to/configure-delegation-toolkit) - [Create a delegator account.](https://docs.gator.metamask.io/development/how-to/create-delegator-account) ## Configure a Hybrid Delegator [​](https://docs.gator.metamask.io/development/how-to/configure-delegator-accounts-signers\#configure-a-hybrid-delegator "Direct link to Configure a Hybrid Delegator") The [Hybrid Delegator](https://docs.gator.metamask.io/development/concepts/delegator-accounts#hybrid-delegator) supports both an EOA "owner" and any number of P256 (passkey) signers. To configure a Hybrid Delegator, provide the following parameters: - `owner`: The owner's account address as a hex string. The owner can be the zero address, indicating that there is no owner configured. - `p256KeyIds`: An array of key identifiers for P256 signers as hex strings. - `p256XValues`: An array of public key x-values for P256 signers as `bigint` s. - `p256YValues`: An array of public key y-values for P256 signers as `bigint` s. - `signatory`: A signer that will sign on behalf of the delegator account. note You can set all `p256` parameters to empty arrays to configure no WebAuthn signer. However, we recommend configuring at least one signer for account recoverability. For a Hybrid Delegator, you can configure the following types of signatories: ### Configure an account signatory [​](https://docs.gator.metamask.io/development/how-to/configure-delegator-accounts-signers\#configure-an-account-signatory "Direct link to Configure an account signatory") This example creates a signatory from a private key using Viem's [`privateKeyToAccount`](https://viem.sh/docs/accounts/local/privateKeyToAccount) function. - example.ts - client.ts - signatory.ts ```codeBlockLines_e6Vv import { publicClient } from "./client.ts" import { signatory } from "./signatory.ts"; import { Implementation, toMetaMaskSmartAccount, } from "@metamask/delegation-toolkit"; const smartAccount = await toMetaMaskSmartAccount({ client: publicClient, implementation: Implementation.Hybrid, deployParams: [owner, p256KeyIds, p256XValues, p256YValues], deploySalt: "0x", signatory, }); ``` ```codeBlockLines_e6Vv import { http, createPublicClient } from "viem"; import { lineaSepolia as chain } from "viem/chains"; const transport = http(); export const publicClient = createPublicClient({ transport, chain, }); ``` ```codeBlockLines_e6Vv import { privateKeyToAccount, generatePrivateKey } from "viem/accounts"; const privateKey = generatePrivateKey(); const account = privateKeyToAccount(privateKey); export const signatory = { account }; ``` ### Configure a Wallet Client signatory [​](https://docs.gator.metamask.io/development/how-to/configure-delegator-accounts-signers\#configure-a-wallet-client-signatory "Direct link to Configure a Wallet Client signatory") This example creates a [Viem Wallet Client](https://viem.sh/docs/clients/wallet) as the signatory, using Viem's `createWalletClient` function. - example.ts - client.ts - signatory.ts ```codeBlockLines_e6Vv import { publicClient } from "./client.ts" import { signatory } from "./signatory.ts"; import { Implementation, toMetaMaskSmartAccount, } from "@metamask/delegation-toolkit"; const smartAccount = await toMetaMaskSmartAccount({ client: publicClient, implementation: Implementation.Hybrid, deployParams: [owner, p256KeyIds, p256XValues, p256YValues], deploySalt: "0x", signatory, }); ``` ```codeBlockLines_e6Vv import { http, createPublicClient } from "viem"; import { lineaSepolia as chain } from "viem/chains"; const transport = http(); export const publicClient = createPublicClient({ transport, chain, }); ``` ```codeBlockLines_e6Vv import { privateKeyToAccount, generatePrivateKey } from "viem/accounts"; import { lineaSepolia as chain } from "viem/chains"; import { http, createWalletClient } from "viem"; const privateKey = generatePrivateKey(); const account = privateKeyToAccount(privateKey); const walletClient = createWalletClient({ account, chain, transport: http() }) export const signatory = { walletClient }; ``` ### Configure a WebAuthn (passkey) signatory [​](https://docs.gator.metamask.io/development/how-to/configure-delegator-accounts-signers\#configure-a-webauthn-passkey-signatory "Direct link to Configure a WebAuthn (passkey) signatory") This example creates a [Viem WebAuthn Account](https://viem.sh/account-abstraction/accounts/webauthn) as the signatory, using Viem's `toWebAuthnAccount` function. - example.ts - client.ts - signatory.ts ```codeBlockLines_e6Vv import { publicClient } from "./client.ts" import { signatory } from "./signatory.ts"; import { Implementation, toMetaMaskSmartAccount, } from "@metamask/delegation-toolkit"; const smartAccount = await toMetaMaskSmartAccount({ client: publicClient, implementation: Implementation.Hybrid, deployParams: [owner, p256KeyIds, p256XValues, p256YValues], deploySalt: "0x", signatory, }); ``` ```codeBlockLines_e6Vv import { http, createPublicClient } from "viem"; import { lineaSepolia as chain } from "viem/chains"; const transport = http(); export const publicClient = createPublicClient({ transport, chain, }); ``` ```codeBlockLines_e6Vv import { createCredential, parsePublicKey } from "webauthn-p256"; import { toWebAuthnAccount } from "viem/account-abstraction"; import { toHex } from "viem"; const credential = await createCredential({ name: "Your Delegator Passkey" }); const webAuthnAccount = toWebAuthnAccount({ credential }); const keyId = toHex("my-key-id"); const signatory = { webAuthnAccount, keyId }; ``` ## Configure a Multisig Delegator [​](https://docs.gator.metamask.io/development/how-to/configure-delegator-accounts-signers\#configure-a-multisig-delegator "Direct link to Configure a Multisig Delegator") The [Multisig Delegator](https://docs.gator.metamask.io/development/concepts/delegator-accounts#multisig-delegator) supports multiple EOA signers with a configurable threshold for execution. To configure a Multisig Delegator, provide the following parameters: - `signers`: An array of EOA signer addresses as hex strings. - `threshold`: The number of signers required to execute a transaction, as a `bigint`. - `signatory`: An array of signatories that will sign on behalf of the delegator account. ### Configure signatories [​](https://docs.gator.metamask.io/development/how-to/configure-delegator-accounts-signers\#configure-signatories "Direct link to Configure signatories") For a Multisig Delegator, you can use a combination of account signatories and Wallet Client signatories. For example: - example.ts - client.ts - signers.ts ```codeBlockLines_e6Vv import { publiClient } from "./client.ts"; import { account, walletClient } from "./signers.ts"; import { Implementation, toMetaMaskSmartAccount, } from "@metamask/delegation-toolkit"; const signers = [ account.address, walletClient.address ]; const signatory = { account, walletClient }; const threshold = 2n const smartAccount = await toMetaMaskSmartAccount({ client: publicClient, implementation: Implementation.MultiSig, deployParams: [signers, threshold], deploySalt: "0x", signatory, }); ``` ```codeBlockLines_e6Vv import { http, createPublicClient } from "viem"; import { lineaSepolia as chain } from "viem/chains"; const transport = http(); export const publicClient = createPublicClient({ transport, chain, }); ``` ```codeBlockLines_e6Vv import { privateKeyToAccount, generatePrivateKey } from "viem/accounts"; import { lineaSepolia as chain } from "viem/chains"; import { http, createWalletClient } from "viem"; // This private key will be used to generate the first signer. const privateKey = generatePrivateKey(); export const account = privateKeyToAccount(privateKey); // This private key will be used to generate the second signer. const walletClientPivatekey = generatePrivateKey(); const walletClientAccount = privateKeyToAccount(walletClientPivatekey); export const walletClient = createWalletClient({ account: walletClientAccount, chain, transport: http() }); ``` note The number of signers in the signatories must be at least equal to the threshold for valid signature generation. - [Prerequisites](https://docs.gator.metamask.io/development/how-to/configure-delegator-accounts-signers#prerequisites) - [Configure a Hybrid Delegator](https://docs.gator.metamask.io/development/how-to/configure-delegator-accounts-signers#configure-a-hybrid-delegator) - [Configure an account signatory](https://docs.gator.metamask.io/development/how-to/configure-delegator-accounts-signers#configure-an-account-signatory) - [Configure a Wallet Client signatory](https://docs.gator.metamask.io/development/how-to/configure-delegator-accounts-signers#configure-a-wallet-client-signatory) - [Configure a WebAuthn (passkey) signatory](https://docs.gator.metamask.io/development/how-to/configure-delegator-accounts-signers#configure-a-webauthn-passkey-signatory) - [Configure a Multisig Delegator](https://docs.gator.metamask.io/development/how-to/configure-delegator-accounts-signers#configure-a-multisig-delegator) - [Configure signatories](https://docs.gator.metamask.io/development/how-to/configure-delegator-accounts-signers#configure-signatories) ## MetaMask Delegation Guide [Skip to main content](https://docs.gator.metamask.io/development/how-to/create-delegation#__docusaurus_skipToContent_fallback) This is a public beta release of the MetaMask Delegation Toolkit. This is the development version of the documentation and some features may not yet be available in the latest release. You can switch to the [latest version](https://docs.gator.metamask.io/how-to/create-delegation) (0.10.2). On this page # Create a delegation The MetaMask Delegation Toolkit enables you to create [delegations](https://docs.gator.metamask.io/development/concepts/delegation) 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](https://docs.gator.metamask.io/development/experimental/erc-7715-request-permissions) and [redeeming ERC-7710 delegations](https://docs.gator.metamask.io/development/experimental/erc-7710-redeem-delegations) 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](https://docs.gator.metamask.io/development/how-to/create-delegation/restrict-delegation) using caveat enforcers. ## Prerequisites [​](https://docs.gator.metamask.io/development/how-to/create-delegation\#prerequisites "Direct link to Prerequisites") - [Install and set up the Delegation Toolkit.](https://docs.gator.metamask.io/development/get-started/install-delegation-toolkit) - [Configure the Delegation Toolkit.](https://docs.gator.metamask.io/development/how-to/configure-delegation-toolkit) - [Create a delegator account.](https://docs.gator.metamask.io/development/how-to/create-delegator-account) ## Create a root delegation [​](https://docs.gator.metamask.io/development/how-to/create-delegation\#create-a-root-delegation "Direct link to 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](https://docs.gator.metamask.io/development/how-to/create-delegation#create-a-redelegation). Create a root delegation as follows: - example.ts - config.ts ```codeBlockLines_e6Vv 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. }); ``` ```codeBlockLines_e6Vv import { createPublicClient, http } from "viem"; import { lineaSepolia 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 [​](https://docs.gator.metamask.io/development/how-to/create-delegation\#create-an-open-root-delegation "Direct link to 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`). - example.ts - config.ts ```codeBlockLines_e6Vv 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. }); ``` ```codeBlockLines_e6Vv import { createPublicClient, http } from "viem"; import { lineaSepolia 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 [​](https://docs.gator.metamask.io/development/how-to/create-delegation\#create-a-redelegation "Direct link to Create a redelegation") A recipient of a delegation (the delegate), can _redelegate_ that authority to a third party, potentially applying additional [restrictions](https://docs.gator.metamask.io/development/how-to/create-delegation/restrict-delegation). Create a redelegation as follows: - example.ts - config.ts ```codeBlockLines_e6Vv 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. }); ``` ```codeBlockLines_e6Vv import { createPublicClient, http } from "viem"; import { lineaSepolia 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 [​](https://docs.gator.metamask.io/development/how-to/create-delegation\#create-an-open-redelegation "Direct link to Create an open redelegation") An _open redelegation_ is a [redelegation](https://docs.gator.metamask.io/development/how-to/create-delegation#create-a-redelegation) that doesn't specify a delegate. This means that any account can redeem the redelegation. As with [open root delegations](https://docs.gator.metamask.io/development/how-to/create-delegation#create-an-open-root-delegation), you must create open redelegations carefully, to ensure that they are not misused. Create an open redelegation as follows: - example.ts - config.ts ```codeBlockLines_e6Vv 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. }); ``` ```codeBlockLines_e6Vv import { createPublicClient, http } from "viem"; import { lineaSepolia 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 [​](https://docs.gator.metamask.io/development/how-to/create-delegation\#sign-a-delegation "Direct link to 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: - example.ts - config.ts ```codeBlockLines_e6Vv 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 }; ``` ```codeBlockLines_e6Vv import { createPublicClient, http } from "viem"; import { lineaSepolia 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 }, }); ``` - [Prerequisites](https://docs.gator.metamask.io/development/how-to/create-delegation#prerequisites) - [Create a root delegation](https://docs.gator.metamask.io/development/how-to/create-delegation#create-a-root-delegation) - [Create an open root delegation](https://docs.gator.metamask.io/development/how-to/create-delegation#create-an-open-root-delegation) - [Create a redelegation](https://docs.gator.metamask.io/development/how-to/create-delegation#create-a-redelegation) - [Create an open redelegation](https://docs.gator.metamask.io/development/how-to/create-delegation#create-an-open-redelegation) - [Sign a delegation](https://docs.gator.metamask.io/development/how-to/create-delegation#sign-a-delegation) ## Custom Caveat Enforcer Guide [Skip to main content](https://docs.gator.metamask.io/development/how-to/create-delegation/create-custom-caveat-enforcer#__docusaurus_skipToContent_fallback) This is a public beta release of the MetaMask Delegation Toolkit. This is the development version of the documentation and some features may not yet be available in the latest release. You can switch to the [latest version](https://docs.gator.metamask.io/how-to/create-delegation/create-custom-caveat-enforcer) (0.10.2). On this page # Create a custom caveat enforcer When [restricting a delegation](https://docs.gator.metamask.io/development/how-to/create-delegation/restrict-delegation), the MetaMask Delegation Toolkit provides some [out-of-the-box caveat enforcers](https://docs.gator.metamask.io/development/how-to/create-delegation/restrict-delegation#caveat-types) 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. ## Prerequisites [​](https://docs.gator.metamask.io/development/how-to/create-delegation/create-custom-caveat-enforcer\#prerequisites "Direct link to Prerequisites") - [Install and set up the Delegation Toolkit.](https://docs.gator.metamask.io/development/get-started/install-delegation-toolkit) - [Configure the Delegation Toolkit.](https://docs.gator.metamask.io/development/how-to/configure-delegation-toolkit) ## Steps [​](https://docs.gator.metamask.io/development/how-to/create-delegation/create-custom-caveat-enforcer\#steps "Direct link to Steps") ### 1\. Create the caveat enforcer [​](https://docs.gator.metamask.io/development/how-to/create-delegation/create-custom-caveat-enforcer\#1-create-the-caveat-enforcer "Direct link to 1. Create the caveat enforcer") 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. AfterTimestampEnforcer.sol ```codeBlockLines_e6Vv // SPDX-License-Identifier: MIT pragma solidity 0.8.23; import { CaveatEnforcer } from "@delegator/src/enforcers/CaveatEnforcer.sol"; import { ModeCode } from "../utils/Types.sol"; contract AfterTimestampEnforcer is CaveatEnforcer { /** * @notice The delegation may only be redeemed after the specified timestamp - validAfter in seconds. * @param _terms The validAfter, timestamp in seconds after which the delegation may be redeemed. * @param _delegationHash - The hash of the delegation being operated on. */ function beforeHook( bytes calldata _terms, bytes calldata, ModeCode, bytes calldata, bytes32 _delegationHash, address, address _redeemer ) public override { // Enforces the conditions that should hold before a transaction is performed. // This function MUST revert if the conditions are not met. // Get the current timestamp uint256 timestamp = block.timestamp; uint256 validAfter = uint256(bytes32(_terms)); require(timestamp > validAfter, "AfterTimestampEnforcer:cannot-redeem-too-early"); } } ``` ### 2\. Deploy the caveat enforcer [​](https://docs.gator.metamask.io/development/how-to/create-delegation/create-custom-caveat-enforcer\#2-deploy-the-caveat-enforcer "Direct link to 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). ### 3\. Apply the caveat enforcer [​](https://docs.gator.metamask.io/development/how-to/create-delegation/create-custom-caveat-enforcer\#3-apply-the-caveat-enforcer "Direct link to 3. Apply the caveat enforcer") When creating a delegation, add the `Caveat` for the custom caveat to the `CaveatBuilder`. Learn more about [applying caveats to a delegation](https://docs.gator.metamask.io/development/how-to/create-delegation/restrict-delegation). 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. Important Depending on the use case, it may be necessary to add additional caveats to restrict the delegation further. - example.ts - config.ts ```codeBlockLines_e6Vv import { createCaveatBuilder, createDelegation, } from "@metamask/delegation-toolkit"; import { toHex } from "viem"; import { delegatorSmartAccount } from "./config.ts"; const environment = delegatorSmartAccount.enviroment; // Replace this with the address where the AfterTimestampEnforcer.sol contract is deployed. const afterTimestampEnforcer = "0x22Ae4c4919C3aB4B5FC309713Bf707569B74876F"; const caveatBuilder = createCaveatBuilder(environment); const tenAM = 10 * 60 * 60; // 10:00 AM as seconds since midnight. const caveats = caveatBuilder .addCaveat("nativeTokenTransferAmount", 1_000_000) .addCaveat({ enforcer: afterTimestampEnforcer, terms: toHex(tenAm) }); const delegation = createDelegation({ to: delegate, from: delegatorSmartAccount.address, caveats }); ``` ```codeBlockLines_e6Vv import { createPublicClient, http } from "viem"; import { lineaSepolia 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 }, }); ``` - [Prerequisites](https://docs.gator.metamask.io/development/how-to/create-delegation/create-custom-caveat-enforcer#prerequisites) - [Steps](https://docs.gator.metamask.io/development/how-to/create-delegation/create-custom-caveat-enforcer#steps) - [1\. Create the caveat enforcer](https://docs.gator.metamask.io/development/how-to/create-delegation/create-custom-caveat-enforcer#1-create-the-caveat-enforcer) - [2\. Deploy the caveat enforcer](https://docs.gator.metamask.io/development/how-to/create-delegation/create-custom-caveat-enforcer#2-deploy-the-caveat-enforcer) - [3\. Apply the caveat enforcer](https://docs.gator.metamask.io/development/how-to/create-delegation/create-custom-caveat-enforcer#3-apply-the-caveat-enforcer) ## Restrict Delegation Guide [Skip to main content](https://docs.gator.metamask.io/development/how-to/create-delegation/restrict-delegation#__docusaurus_skipToContent_fallback) This is a public beta release of the MetaMask Delegation Toolkit. This is the development version of the documentation and some features may not yet be available in the latest release. You can switch to the [latest version](https://docs.gator.metamask.io/how-to/create-delegation/restrict-delegation) (0.10.2). On this page # Restrict a delegation Use [caveat enforcers](https://docs.gator.metamask.io/development/concepts/caveat-enforcers) 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. Each caveat is specified as follows: ```codeBlockLines_e6Vv export type Caveat = { enforcer: Hex; // The address of the caveat enforcer contract. terms: Hex; // Data passed to the caveat enforcer, describing how the redemption should be validated. args: Hex; // Data that may be specified by the redeemer when redeeming the delegation (only used in limited cases). }; ``` The MetaMask Delegation Toolkit provides a `CaveatBuilder` interface, which offers an intuitive way to define the `caveats` array. Use the `CaveatBuilder` to easily ensure that your delegations grant only the necessary authority. ## Create the caveat builder [​](https://docs.gator.metamask.io/development/how-to/create-delegation/restrict-delegation\#create-the-caveat-builder "Direct link to Create the caveat builder") To create the caveat builder, call the `createCaveatBuilder()` function, passing an instance of `DeleGatorEnvironment`. The environment can be accessed from the `MetaMaskSmartAccount`, as in this example: ```codeBlockLines_e6Vv const environment = delegatorSmartAccount.environment; const caveatBuilder = createCaveatBuilder(environment); ``` note By default, the `CaveatBuilder` does not allow empty caveats. To allow the `CaveatBuilder` to build an empty caveats array, provide the following configuration: ```codeBlockLines_e6Vv const caveatBuilder = createCaveatBuilder(environment, { allowEmptyCaveats: true }); ``` ## Add caveats to the builder [​](https://docs.gator.metamask.io/development/how-to/create-delegation/restrict-delegation\#add-caveats-to-the-builder "Direct link to Add caveats to the builder") Add caveats to the builder using the `addCaveat` method, specifying the [caveat type](https://docs.gator.metamask.io/development/how-to/create-delegation/restrict-delegation#caveat-types) and its parameters. You can chain multiple calls to `addCaveat` as in the following example: ```codeBlockLines_e6Vv const caveats = caveatBuilder // allowedTargets accepts an array of addresses. // This caveat restricts the caller to only use the delegation to interact with the specified address. .addCaveat("allowedTargets", ["0xc11F3a8E5C7D16b75c9E2F60d26f5321C6Af5E92"]) // allowedMethods accepts an array of methods. // This caveat restricts the caller to only use the delegation to invoke the specified methods. .addCaveat("allowedMethods", [\ "approve(address,uint256)",\ "transfer(address,uint256)"\ ]) // limitedCalls accepts a number. // This caveat restricts the caller to only use the delegation one time. .addCaveat("limitedCalls", 1) .build(); ``` **Important considerations when using caveat enforcers** - Delegations without caveats are entirely permissive. It is crucial to add appropriate caveats to restrict the delegated authority sufficiently. Failing to do so could result in unintended access or actions. - Caveat enforcers safeguard the execution process but do not guarantee a final state post-redemption. Always combine caveat enforcers thoughtfully to create comprehensive protection. - When using multiple caveat enforcers that modify external contract states, the order matters. For example, if you include both [`NativeBalanceGteEnforcer`](https://docs.gator.metamask.io/development/how-to/create-delegation/restrict-delegation#nativebalancegte) to ensure a balance has increased and [`NativeTokenPaymentEnforcer`](https://docs.gator.metamask.io/development/how-to/create-delegation/restrict-delegation#nativetokenpayment) to deduct from that balance, executing `NativeTokenPaymentEnforcer` first might cause `NativeBalanceGteEnforcer` to fail validation. Consider the sequence of enforcers carefully when creating delegations with interdependent caveats. For convenience, you can also pass the `CaveatBuilder` directly to the various helper methods for creating a delegation. For example: ```codeBlockLines_e6Vv const caveats = caveatBuilder // allowedTargets accepts an array of addresses. .addCaveat("allowedTargets", ["0xc11F3a8E5C7D16b75c9E2F60d26f5321C6Af5E92"]) // allowedMethods accepts an array of methods. .addCaveat("allowedMethods", [\ "approve(address,uint256)",\ "transfer(address,uint256)"\ ]) // limitedCalls accepts a number. .addCaveat("limitedCalls", 1); const delegation = createDelegation({ to: delegate, from: delegator, caveats }); ``` ## Caveat types [​](https://docs.gator.metamask.io/development/how-to/create-delegation/restrict-delegation\#caveat-types "Direct link to Caveat types") The `CaveatBuilder` supports various caveat types, each serving a specific purpose. These caveat types correspond to the out-of-the-box caveat enforcers that the MetaMask Delegation Toolkit provides. For more granular or custom control, you can also [create custom caveat enforcers](https://docs.gator.metamask.io/development/how-to/create-delegation/create-custom-caveat-enforcer) and add them to the caveat builder. ### `allowedCalldata` [​](https://docs.gator.metamask.io/development/how-to/create-delegation/restrict-delegation\#allowedcalldata "Direct link to allowedcalldata") Limits the calldata that is executed. You can use this caveat to enforce function parameters. We strongly recommend using this caveat to validate static types and not dynamic types. You can validate dynamic types through a series of `allowedCalldata` terms, but this is tedious and error-prone. **Caveat enforcer contract:** [`AllowedCalldataEnforcer.sol`](https://github.com/MetaMask/delegation-framework/blob/main/src/enforcers/AllowedCalldataEnforcer.sol) #### Parameters [​](https://docs.gator.metamask.io/development/how-to/create-delegation/restrict-delegation\#parameters "Direct link to Parameters") 1. Index in the calldata byte array (including the 4-byte method selector) where the expected calldata starts 2. Expected calldata as a hex string #### Example [​](https://docs.gator.metamask.io/development/how-to/create-delegation/restrict-delegation\#example "Direct link to Example") ```codeBlockLines_e6Vv caveatBuilder.addCaveat("allowedCalldata", 4, encodeAbiParameters([\ { type: "string" },\ { type: "uint256" }\ ], [\ "Hello Gator",\ 12345n\ ]) ); ``` note This example uses Viem's [`encodeAbiParameters`](https://viem.sh/docs/abi/encodeAbiParameters) utility to encode the parameters as ABI-encoded hex strings. ### `allowedMethods` [​](https://docs.gator.metamask.io/development/how-to/create-delegation/restrict-delegation\#allowedmethods "Direct link to allowedmethods") Limits what methods the delegate can call. **Caveat enforcer contract:** [`AllowedMethodsEnforcer.sol`](https://github.com/MetaMask/delegation-framework/blob/main/src/enforcers/AllowedMethodsEnforcer.sol) #### Parameters [​](https://docs.gator.metamask.io/development/how-to/create-delegation/restrict-delegation\#parameters-1 "Direct link to Parameters") 1. An array of methods as 4-byte hex strings, ABI function signatures, or `ABIFunction` objects #### Example [​](https://docs.gator.metamask.io/development/how-to/create-delegation/restrict-delegation\#example-1 "Direct link to Example") ```codeBlockLines_e6Vv caveatBuilder.addCaveat("allowedMethods", [\ "0xa9059cbb",\ "transfer(address,uint256)",\ {\ name: 'transfer',\ type: 'function',\ inputs: [\ { name: 'recipient', type: 'address' },\ { name: 'amount', type: 'uint256' }\ ],\ outputs: [],\ stateMutability: 'nonpayable',\ }\ ]); ``` note This example adds the `transfer` function to the allowed methods in three different ways - as the 4-byte function selector, the ABI function signature, and the `ABIFunction` object. ### `allowedTargets` [​](https://docs.gator.metamask.io/development/how-to/create-delegation/restrict-delegation\#allowedtargets "Direct link to allowedtargets") Limits what addresses the delegate can call. **Caveat enforcer contract:** [`AllowedTargetsEnforcer.sol`](https://github.com/MetaMask/delegation-framework/blob/main/src/enforcers/AllowedTargetsEnforcer.sol) #### Parameters [​](https://docs.gator.metamask.io/development/how-to/create-delegation/restrict-delegation\#parameters-2 "Direct link to Parameters") 1. An array of addresses as hex strings #### Example [​](https://docs.gator.metamask.io/development/how-to/create-delegation/restrict-delegation\#example-2 "Direct link to Example") ```codeBlockLines_e6Vv caveatBuilder.addCaveat("allowedTargets", [\ "0xc11F3a8E5C7D16b75c9E2F60d26f5321C6Af5E92",\ "0xB2880E3862f1024cAC05E66095148C0a9251718b"\ ]); ``` ### `argsEqualityCheck` [​](https://docs.gator.metamask.io/development/how-to/create-delegation/restrict-delegation\#argsequalitycheck "Direct link to argsequalitycheck") Ensures that the `args` provided when redeeming the delegation are equal to the terms specified on the caveat. **Caveat enforcer contract:** [`ArgsEqualityCheckEnforcer.sol`](https://github.com/MetaMask/delegation-framework/blob/main/src/enforcers/ArgsEqualityCheckEnforcer.sol) #### Parameters [​](https://docs.gator.metamask.io/development/how-to/create-delegation/restrict-delegation\#parameters-3 "Direct link to Parameters") 1. The expected `args` as a hex string #### Example [​](https://docs.gator.metamask.io/development/how-to/create-delegation/restrict-delegation\#example-3 "Direct link to Example") ```codeBlockLines_e6Vv caveatBuilder.addCaveat("argsEqualityCheck", "0xf2bef872456302645b7c0bb59dcd96ffe6d4a844f311ebf95e7cf439c9393de2" ); ``` ### `blockNumber` [​](https://docs.gator.metamask.io/development/how-to/create-delegation/restrict-delegation\#blocknumber "Direct link to blocknumber") Specifies a range of blocks through which the delegation will be valid. **Caveat enforcer contract:** [`BlockNumberEnforcer.sol`](https://github.com/MetaMask/delegation-framework/blob/main/src/enforcers/BlockNumberEnforcer.sol) #### Parameters [​](https://docs.gator.metamask.io/development/how-to/create-delegation/restrict-delegation\#parameters-4 "Direct link to Parameters") 1. After threshold block number as a `bigint` 2. Before threshold block number as a `bigint` You can specify `0n` to indicate that there is no limitation on a threshold. #### Example [​](https://docs.gator.metamask.io/development/how-to/create-delegation/restrict-delegation\#example-4 "Direct link to Example") ```codeBlockLines_e6Vv caveatBuilder.addCaveat("blocknumber", 19426587n, 0n ); ``` ### `deployed` [​](https://docs.gator.metamask.io/development/how-to/create-delegation/restrict-delegation\#deployed "Direct link to deployed") Ensures a contract is deployed, and if not, deploys the contract. **Caveat enforcer contract:** [`DeployedEnforcer.sol`](https://github.com/MetaMask/delegation-framework/blob/main/src/enforcers/DeployedEnforcer.sol) #### Parameters [​](https://docs.gator.metamask.io/development/how-to/create-delegation/restrict-delegation\#parameters-5 "Direct link to Parameters") 1. A contract address as a hex string 2. The salt to use with the contract, as a hex string 3. The bytecode of the contract as a hex string #### Example [​](https://docs.gator.metamask.io/development/how-to/create-delegation/restrict-delegation\#example-5 "Direct link to Example") ```codeBlockLines_e6Vv caveatBuilder.addCaveat("deployed", "0xc11F3a8E5C7D16b75c9E2F60d26f5321C6Af5E92", "0x0e3e8e2381fde0e8515ed47ec9caec8ba2bc12603bc2b36133fa3e3fa4d88587", "0x..." // The deploy bytecode for the contract at 0xc11F3a8E5C7D16b75c9E2F60d26f5321C6Af5E92 ); ``` ### `erc1155BalanceGte` [​](https://docs.gator.metamask.io/development/how-to/create-delegation/restrict-delegation\#erc1155balancegte "Direct link to erc1155balancegte") Ensures the ERC-1155 balance of a specified address has increased by at least a specified amount after the execution has been performed, regardless of what the execution is. **Caveat enforcer contract:** [`ERC1155BalanceGteEnforcer.sol`](https://github.com/MetaMask/delegation-framework/blob/main/src/enforcers/ERC1155BalanceGteEnforcer.sol) #### Parameters [​](https://docs.gator.metamask.io/development/how-to/create-delegation/restrict-delegation\#parameters-6 "Direct link to Parameters") 1. An ERC-1155 contract address as a hex string 2. The recipient's address as a hex string 3. The ID of the ERC-1155 token as a bigint 4. The amount by which the balance must have increased as a bigint #### Example [​](https://docs.gator.metamask.io/development/how-to/create-delegation/restrict-delegation\#example-6 "Direct link to Example") ```codeBlockLines_e6Vv caveatBuilder.addCaveat("erc1155BalanceGte", "0xc11F3a8E5C7D16b75c9E2F60d26f5321C6Af5E92", "0x3fF528De37cd95b67845C1c55303e7685c72F319", 1n, 1_000_000n ); ``` ### `erc20BalanceGte` [​](https://docs.gator.metamask.io/development/how-to/create-delegation/restrict-delegation\#erc20balancegte "Direct link to erc20balancegte") Ensures the delegator's ERC-20 balance increases by at least the specified amount after execution, regardless of the execution. **Caveat enforcer contract:** [`ERC20BalanceGteEnforcer.sol`](https://github.com/MetaMask/delegation-framework/blob/main/src/enforcers/ERC20BalanceGteEnforcer.sol) #### Parameters [​](https://docs.gator.metamask.io/development/how-to/create-delegation/restrict-delegation\#parameters-7 "Direct link to Parameters") 1. An ERC-20 contract address as a hex string 2. Amount as a `bigint` #### Example [​](https://docs.gator.metamask.io/development/how-to/create-delegation/restrict-delegation\#example-7 "Direct link to Example") ```codeBlockLines_e6Vv caveatBuilder.addCaveat("erc20BalanceGte", "0xc11F3a8E5C7D16b75c9E2F60d26f5321C6Af5E92", 1_000_000n ); ``` ### `erc20PeriodTransfer` [​](https://docs.gator.metamask.io/development/how-to/create-delegation/restrict-delegation\#erc20periodtransfer "Direct link to erc20periodtransfer") Ensures that ERC-20 token transfers remain within a predefined limit during a specified time window. At the start of each new period, the allowed transfer amount resets. Any unused transfer allowance from the previous period does not carry over and is forfeited. **Caveat enforcer contract:** [`ERC20PeriodTransferEnforcer.sol`](https://github.com/MetaMask/delegation-framework/blob/main/src/enforcers/ERC20PeriodTransferEnforcer.sol) #### Parameters [​](https://docs.gator.metamask.io/development/how-to/create-delegation/restrict-delegation\#parameters-8 "Direct link to Parameters") 1. The address of the ERC-20 token contract. 2. The maximum amount of tokens that can be transferred per period, in wei. 3. The duration of each period in seconds. 4. The timestamp when the first period begins. #### Example [​](https://docs.gator.metamask.io/development/how-to/create-delegation/restrict-delegation\#example-8 "Direct link to Example") ```codeBlockLines_e6Vv caveatBuilder.addCaveat("erc20PeriodTransfer", "0xb4aE654Aca577781Ca1c5DE8FbE60c2F423f37da", // Address of the ERC-20 token 1000000000000000000n, // 1 ERC-20 token - 18 decimals, in wei 86400, // 1 day in seconds 1743763600, // April 4th, 2025, at 00:00:00 UTC ); ``` ### `erc20Streaming` [​](https://docs.gator.metamask.io/development/how-to/create-delegation/restrict-delegation\#erc20streaming "Direct link to erc20streaming") Enforces a linear streaming transfer limit for ERC-20 tokens. Block token access until the specified start timestamp. At the start timestamp, immediately release the specified initial amount. Afterward, accrue tokens linearly at the specified rate, up to the specified maximum. **Caveat enforcer contract:** [`ERC20StreamingEnforcer.sol`](https://github.com/MetaMask/delegation-framework/blob/main/src/enforcers/ERC20StreamingEnforcer.sol) #### Parameters [​](https://docs.gator.metamask.io/development/how-to/create-delegation/restrict-delegation\#parameters-9 "Direct link to Parameters") 1. An ERC-20 contract address as a hex string 2. Initial amount available at start time as a `bigint` 3. Maximum total amount that can be unlocked as a `bigint` 4. Rate at which tokens accrue per second as a `bigint` 5. Start timestamp as a number #### Example [​](https://docs.gator.metamask.io/development/how-to/create-delegation/restrict-delegation\#example-9 "Direct link to Example") ```codeBlockLines_e6Vv caveatBuilder.addCaveat("erc20Streaming", "0xc11F3a8E5C7D16b75c9E2F60d26f5321C6Af5E92", 1_000_000n, 10_000_000n, 100n, 1703980800 ); ``` ### `erc20TransferAmount` [​](https://docs.gator.metamask.io/development/how-to/create-delegation/restrict-delegation\#erc20transferamount "Direct link to erc20transferamount") Limits the transfer of ERC-20 tokens. **Caveat enforcer contract:** [`ERC20TransferAmountEnforcer.sol`](https://github.com/MetaMask/delegation-framework/blob/main/src/enforcers/ERC20TransferAmountEnforcer.sol) #### Parameters [​](https://docs.gator.metamask.io/development/how-to/create-delegation/restrict-delegation\#parameters-10 "Direct link to Parameters") 1. An ERC-20 contract address as a hex string 2. Amount as a `bigint` #### Example [​](https://docs.gator.metamask.io/development/how-to/create-delegation/restrict-delegation\#example-10 "Direct link to Example") ```codeBlockLines_e6Vv caveatBuilder.addCaveat("erc20TransferAmount", "0xc11F3a8E5C7D16b75c9E2F60d26f5321C6Af5E92", 1_000_000n ); ``` ### `erc721BalanceGte` [​](https://docs.gator.metamask.io/development/how-to/create-delegation/restrict-delegation\#erc721balancegte "Direct link to erc721balancegte") Ensures the ERC-721 balance of the specified recipient address increases by at least the specified amount after execution, regardless of execution type. **Caveat enforcer contract:** [`ERC721BalanceGteEnforcer.sol`](https://github.com/MetaMask/delegation-framework/blob/main/src/enforcers/ERC721BalanceGteEnforcer.sol) #### Parameters [​](https://docs.gator.metamask.io/development/how-to/create-delegation/restrict-delegation\#parameters-11 "Direct link to Parameters") 1. An ERC-721 contract address as a hex string 2. The recipient's address as a hex string 3. The amount by which the balance must have increased as a `bigint` #### Example [​](https://docs.gator.metamask.io/development/how-to/create-delegation/restrict-delegation\#example-11 "Direct link to Example") ```codeBlockLines_e6Vv caveatBuilder.addCaveat("erc721BalanceGte", "0xc11F3a8E5C7D16b75c9E2F60d26f5321C6Af5E92", "0x3fF528De37cd95b67845C1c55303e7685c72F319", 1_000_000n ); ``` ### `erc721Transfer` [​](https://docs.gator.metamask.io/development/how-to/create-delegation/restrict-delegation\#erc721transfer "Direct link to erc721transfer") Restricts the execution to only allow ERC-721 token transfers, specifically the `transferFrom(from, to, tokenId)` function, for a specified token ID and contract. **Caveat enforcer contract:** [`ERC721TransferEnforcer.sol`](https://github.com/MetaMask/delegation-framework/blob/main/src/enforcers/ERC721TransferEnforcer.sol) #### Parameters [​](https://docs.gator.metamask.io/development/how-to/create-delegation/restrict-delegation\#parameters-12 "Direct link to Parameters") 1. The permitted ERC-721 contract address as a hex string 2. The permitted ID of the ERC-721 token as a `bigint` #### Example [​](https://docs.gator.metamask.io/development/how-to/create-delegation/restrict-delegation\#example-12 "Direct link to Example") ```codeBlockLines_e6Vv caveatBuilder.addCaveat("erc721Transfer", "0x3fF528De37cd95b67845C1c55303e7685c72F319", 1n ); ``` ### `exactCalldata` [​](https://docs.gator.metamask.io/development/how-to/create-delegation/restrict-delegation\#exactcalldata "Direct link to exactcalldata") Verifies that the transaction calldata matches the expected calldata. For batch transactions, see [`exactCalldataBatch`](https://docs.gator.metamask.io/development/how-to/create-delegation/restrict-delegation#exactcalldatabatch). **Caveat enforcer contract:** [`ExactCalldataEnforcer.sol`](https://github.com/MetaMask/delegation-framework/blob/main/src/enforcers/ExactCalldataEnforcer.sol) #### Parameters [​](https://docs.gator.metamask.io/development/how-to/create-delegation/restrict-delegation\#parameters-13 "Direct link to Parameters") 1. A hex value for calldata. #### Example [​](https://docs.gator.metamask.io/development/how-to/create-delegation/restrict-delegation\#example-13 "Direct link to Example") ```codeBlockLines_e6Vv caveatBuilder.addCaveat("exactCalldata", "0x1234567890abcdef" // Calldata to be matched ); ``` ### `exactCalldataBatch` [​](https://docs.gator.metamask.io/development/how-to/create-delegation/restrict-delegation\#exactcalldatabatch "Direct link to exactcalldatabatch") Verifies that the provided batch execution calldata matches the expected calldata for each individual execution in the batch. **Caveat enforcer contract:** [`ExactCalldataBatchEnforcer.sol`](https://github.com/MetaMask/delegation-framework/blob/main/src/enforcers/ExactCalldataBatchEnforcer.sol) #### Parameters [​](https://docs.gator.metamask.io/development/how-to/create-delegation/restrict-delegation\#parameters-14 "Direct link to Parameters") 1. Array of expected `ExecutionStruct`, each containing target address, value, and calldata. #### Example [​](https://docs.gator.metamask.io/development/how-to/create-delegation/restrict-delegation\#example-14 "Direct link to Example") ```codeBlockLines_e6Vv const executions = [\ {\ target: "0xb4aE654Aca577781Ca1c5DE8FbE60c2F423f37da",\ value: 1000000000000000000n, // 1 ETH\ callData: "0x",\ },\ {\ target: "0xb4aE654Aca577781Ca1c5DE8FbE60c2F423f37da",\ value: 0n,\ callData: "0x",\ },\ ]; caveatBuilder.addCaveat("exactCalldataBatch", executions ); ``` ### `exactExecution` [​](https://docs.gator.metamask.io/development/how-to/create-delegation/restrict-delegation\#exactexecution "Direct link to exactexecution") Verifies that the provided execution matches the expected execution. For batch transactions, see [`exactExecutionBatch`](https://docs.gator.metamask.io/development/how-to/create-delegation/restrict-delegation#exactExecutionBatch). **Caveat enforcer contract:** [`ExactExecutionEnforcer.sol`](https://github.com/MetaMask/delegation-framework/blob/main/src/enforcers/ExactExecutionEnforcer.sol) #### Parameters [​](https://docs.gator.metamask.io/development/how-to/create-delegation/restrict-delegation\#parameters-15 "Direct link to Parameters") 1. `ExecutionStruct` to be expected. #### Example [​](https://docs.gator.metamask.io/development/how-to/create-delegation/restrict-delegation\#example-15 "Direct link to Example") ```codeBlockLines_e6Vv caveatBuilder.addCaveat("exactExecution", { target: "0xb4aE654Aca577781Ca1c5DE8FbE60c2F423f37da", value: 1000000000000000000n, // 1 ETH callData: "0x", }) ``` ### `exactExecutionBatch` [​](https://docs.gator.metamask.io/development/how-to/create-delegation/restrict-delegation\#exactexecutionbatch "Direct link to exactexecutionbatch") Verifies that each execution in the batch matches the expected execution parameters - including target, value, and calldata. **Caveat enforcer contract:** [`ExactExecutionBatchEnforcer.sol`](https://github.com/MetaMask/delegation-framework/blob/main/src/enforcers/ExactExecutionBatchEnforcer.sol) #### Parameters [​](https://docs.gator.metamask.io/development/how-to/create-delegation/restrict-delegation\#parameters-16 "Direct link to Parameters") 1. Array of expected `ExecutionStruct`, each containing target address, value, and calldata. #### Example [​](https://docs.gator.metamask.io/development/how-to/create-delegation/restrict-delegation\#example-16 "Direct link to Example") ```codeBlockLines_e6Vv const executions = [\ {\ target: "0xb4aE654Aca577781Ca1c5DE8FbE60c2F423f37da",\ value: 1000000000000000000n, // 1 ETH\ callData: "0x",\ },\ {\ target: "0xb4aE654Aca577781Ca1c5DE8FbE60c2F423f37da",\ value: 0n,\ callData: "0x",\ },\ ]; caveatBuilder.addCaveat("exactExecutionBatch", executions ); ``` ### `id` [​](https://docs.gator.metamask.io/development/how-to/create-delegation/restrict-delegation\#id "Direct link to id") Specifies an ID for multiple delegations. Once one of them is redeemed, the other delegations with the same ID are revoked. **Caveat enforcer contract:** [`IdEnforcer.sol`](https://github.com/MetaMask/delegation-framework/blob/main/src/enforcers/IdEnforcer.sol) #### Parameters [​](https://docs.gator.metamask.io/development/how-to/create-delegation/restrict-delegation\#parameters-17 "Direct link to Parameters") 1. An ID as a number #### Example [​](https://docs.gator.metamask.io/development/how-to/create-delegation/restrict-delegation\#example-17 "Direct link to Example") ```codeBlockLines_e6Vv caveatBuilder.addCaveat("id", 123456 ); ``` ### `limitedCalls` [​](https://docs.gator.metamask.io/development/how-to/create-delegation/restrict-delegation\#limitedcalls "Direct link to limitedcalls") Limits the number of times the delegate can perform executions on the delegator's behalf. **Caveat enforcer contract:** [`LimitedCallsEnforcer.sol`](https://github.com/MetaMask/delegation-framework/blob/main/src/enforcers/LimitedCallsEnforcer.sol) #### Parameters [​](https://docs.gator.metamask.io/development/how-to/create-delegation/restrict-delegation\#parameters-18 "Direct link to Parameters") 1. A count as a number #### Example [​](https://docs.gator.metamask.io/development/how-to/create-delegation/restrict-delegation\#example-18 "Direct link to Example") ```codeBlockLines_e6Vv caveatBuilder.addCaveat("limitedCalls", 1 ); ``` ### `nativeBalanceGte` [​](https://docs.gator.metamask.io/development/how-to/create-delegation/restrict-delegation\#nativebalancegte "Direct link to nativebalancegte") Ensures that the recipient's native token balance has increased by at least the specified amount. **Caveat enforcer contract:** [`NativeBalanceGteEnforcer.sol`](https://github.com/MetaMask/delegation-framework/blob/main/src/enforcers/NativeBalanceGteEnforcer.sol) #### Parameters [​](https://docs.gator.metamask.io/development/how-to/create-delegation/restrict-delegation\#parameters-19 "Direct link to Parameters") 1. The recipient's address as a hex string 2. The amount by which the balance must have increased as a `bigint` #### Example [​](https://docs.gator.metamask.io/development/how-to/create-delegation/restrict-delegation\#example-19 "Direct link to Example") ```codeBlockLines_e6Vv caveatBuilder.addCaveat("nativeBalanceGte", "0x3fF528De37cd95b67845C1c55303e7685c72F319", 1_000_000n ); ``` ### `nativeTokenPayment` [​](https://docs.gator.metamask.io/development/how-to/create-delegation/restrict-delegation\#nativetokenpayment "Direct link to nativetokenpayment") Enforces payment in native token (for example, ETH) for the right to use the delegation. A permissions context allowing payment must be provided as the `args` when redeeming the delegation. **Caveat enforcer contract:** [`NativeTokenPaymentEnforcer.sol`](https://github.com/MetaMask/delegation-framework/blob/main/src/enforcers/NativeTokenPaymentEnforcer.sol) #### Parameters [​](https://docs.gator.metamask.io/development/how-to/create-delegation/restrict-delegation\#parameters-20 "Direct link to Parameters") 1. The recipient's address as a hex string 2. The amount that must be paid as a `bigint` #### Example [​](https://docs.gator.metamask.io/development/how-to/create-delegation/restrict-delegation\#example-20 "Direct link to Example") ```codeBlockLines_e6Vv caveatBuilder.addCaveat("nativeTokenPayment", "0x3fF528De37cd95b67845C1c55303e7685c72F319", 1_000_000n ); ``` ### `nativeTokenPeriodTransfer` [​](https://docs.gator.metamask.io/development/how-to/create-delegation/restrict-delegation\#nativetokenperiodtransfer "Direct link to nativetokenperiodtransfer") Ensures that native token transfers remain within a predefined limit during a specified time window. At the start of each new period, the allowed transfer amount resets. Any unused transfer allowance from the previous period does not carry over and is forfeited. **Caveat enforcer contract:** [`NativeTokenPeriodTransferEnforcer.sol`](https://github.com/MetaMask/delegation-framework/blob/main/src/enforcers/NativeTokenPeriodTransferEnforcer.sol) #### Parameters [​](https://docs.gator.metamask.io/development/how-to/create-delegation/restrict-delegation\#parameters-21 "Direct link to Parameters") 1. The maximum amount of tokens that can be transferred per period, in wei. 2. The duration of each period in seconds. 3. The timestamp when the first period begins. #### Example [​](https://docs.gator.metamask.io/development/how-to/create-delegation/restrict-delegation\#example-21 "Direct link to Example") ```codeBlockLines_e6Vv caveatBuilder.addCaveat("nativeTokenPeriodTransfer", 1000000000000000000n, // 1 ETH in wei 86400, // 1 day in seconds 1743763600, // April 4th, 2025, at 00:00:00 UTC ) ``` ### `nativeTokenStreaming` [​](https://docs.gator.metamask.io/development/how-to/create-delegation/restrict-delegation\#nativetokenstreaming "Direct link to nativetokenstreaming") Enforces a linear streaming limit for native tokens (for example, ETH). Nothing is available before the specified start timestamp. At the start timestamp, the specified initial amount becomes immediately available. After that, tokens accrue linearly at the specified rate, capped by the specified maximum. **Caveat enforcer contract:** [`NativeTokenStreamingEnforcer.sol`](https://github.com/MetaMask/delegation-framework/blob/main/src/enforcers/NativeTokenStreamingEnforcer.sol) #### Parameters [​](https://docs.gator.metamask.io/development/how-to/create-delegation/restrict-delegation\#parameters-22 "Direct link to Parameters") 1. Initial amount available at start time as a `bigint` 2. Maximum total amount that can be unlocked as a `bigint` 3. Rate at which tokens accrue per second as a `bigint` 4. Start timestamp as a number #### Example [​](https://docs.gator.metamask.io/development/how-to/create-delegation/restrict-delegation\#example-22 "Direct link to Example") ```codeBlockLines_e6Vv caveatBuilder.addCaveat("nativeTokenStreaming", 1_000_000n, 10_000_000n, 100n, 1703980800 ); ``` ### `nativeTokenTransferAmount` [​](https://docs.gator.metamask.io/development/how-to/create-delegation/restrict-delegation\#nativetokentransferamount "Direct link to nativetokentransferamount") Enforces an allowance of native currency (for example, ETH). **Caveat enforcer contract:** [`NativeTokenTransferAmountEnforcer.sol`](https://github.com/MetaMask/delegation-framework/blob/main/src/enforcers/NativeTokenTransferAmountEnforcer.sol) #### Parameters [​](https://docs.gator.metamask.io/development/how-to/create-delegation/restrict-delegation\#parameters-23 "Direct link to Parameters") 1. The allowance as a `bigint` #### Example [​](https://docs.gator.metamask.io/development/how-to/create-delegation/restrict-delegation\#example-23 "Direct link to Example") ```codeBlockLines_e6Vv caveatBuilder.addCaveat("nativeTokenTransferAmount", 1_000_000n ); ``` ### `nonce` [​](https://docs.gator.metamask.io/development/how-to/create-delegation/restrict-delegation\#nonce "Direct link to nonce") Adds a nonce to a delegation, and revokes previous delegations by incrementing the current nonce by calling `incrementNonce(address _delegationManager)`. **Caveat enforcer contract:** [`NonceEnforcer.sol`](https://github.com/MetaMask/delegation-framework/blob/main/src/enforcers/NonceEnforcer.sol) #### Parameters [​](https://docs.gator.metamask.io/development/how-to/create-delegation/restrict-delegation\#parameters-24 "Direct link to Parameters") 1. A nonce as a hex string #### Example [​](https://docs.gator.metamask.io/development/how-to/create-delegation/restrict-delegation\#example-24 "Direct link to Example") ```codeBlockLines_e6Vv caveatBuilder.addCaveat("nonce", "0x1" ); ``` ### `ownershipTransfer` [​](https://docs.gator.metamask.io/development/how-to/create-delegation/restrict-delegation\#ownershiptransfer "Direct link to ownershiptransfer") Restricts the execution to only allow ownership transfers, specifically the `transferOwnership(address _newOwner)` function, for a specified contract. **Caveat enforcer contract:** [`OwnershipTransferEnforcer.sol`](https://github.com/MetaMask/delegation-framework/blob/main/src/enforcers/OwnershipTransferEnforcer.sol) #### Parameters [​](https://docs.gator.metamask.io/development/how-to/create-delegation/restrict-delegation\#parameters-25 "Direct link to Parameters") 1. The target contract address as a hex string #### Example [​](https://docs.gator.metamask.io/development/how-to/create-delegation/restrict-delegation\#example-25 "Direct link to Example") ```codeBlockLines_e6Vv caveatBuilder.addCaveat("ownershipTransfer", "0xc11F3a8E5C7D16b75c9E2F60d26f5321C6Af5E92" ); ``` ### `redeemer` [​](https://docs.gator.metamask.io/development/how-to/create-delegation/restrict-delegation\#redeemer "Direct link to redeemer") Limits the addresses that can redeem the delegation. This caveat is designed for restricting smart contracts or EOAs lacking delegation support, and can be placed anywhere in the delegation chain to restrict the redeemer. note Delegator accounts with delegation functionalities can bypass these restrictions by delegating to other addresses. For example, Alice makes Bob the redeemer. This condition is enforced, but if Bob is a delegator he can create a separate delegation to Carol that allows her to redeem Alice's delegation through Bob. **Caveat enforcer contract:** [`RedeemerEnforcer.sol`](https://github.com/MetaMask/delegation-framework/blob/main/src/enforcers/RedeemerEnforcer.sol) #### Parameters [​](https://docs.gator.metamask.io/development/how-to/create-delegation/restrict-delegation\#parameters-26 "Direct link to Parameters") 1. An array of addresses as hex strings #### Example [​](https://docs.gator.metamask.io/development/how-to/create-delegation/restrict-delegation\#example-26 "Direct link to Example") ```codeBlockLines_e6Vv caveatBuilder.addCaveat("redeemer", [\ "0xb4aE654Aca577781Ca1c5DE8FbE60c2F423f37da",\ "0x6be97c23596ECed7170fdFb28e8dA1Ca5cdc54C5"\ ] ); ``` ### `specificActionERC20TransferBatch` [​](https://docs.gator.metamask.io/development/how-to/create-delegation/restrict-delegation\#specificactionerc20transferbatch "Direct link to specificactionerc20transferbatch") Ensures validation of a batch consisting of exactly two transactions: 1. The first transaction must call a specific target contract with predefined calldata. 2. The second transaction must be an ERC-20 token transfer that matches specified parametersβ€”including the ERC-20 token contract address, amount, and recipient. **Caveat enforcer contract:** [`SpecificActionERC20TransferBatchEnforcer.sol`](https://github.com/MetaMask/delegation-framework/blob/main/src/enforcers/SpecificActionERC20TransferBatchEnforcer.sol) #### Parameters [​](https://docs.gator.metamask.io/development/how-to/create-delegation/restrict-delegation\#parameters-27 "Direct link to Parameters") 1. The address of the ERC-20 token contract. 2. The address that will receive the tokens. 3. The amount of tokens to transfer, in wei. 4. The target address for the first transaction. 5. The calldata for the first transaction. #### Example [​](https://docs.gator.metamask.io/development/how-to/create-delegation/restrict-delegation\#example-27 "Direct link to Example") ```codeBlockLines_e6Vv caveatBuilder.addCaveat("specificActionERC20TransferBatch", "0xb4aE654Aca577781Ca1c5DE8FbE60c2F423f37da" // Address of ERC-20 token contract "0x027aeAFF3E5C33c4018FDD302c20a1B83aDCD96C", // Address that will receive the tokens 1000000000000000000n, // 1 ERC-20 token - 18 decimals, in wei "0xb49830091403f1Aa990859832767B39c25a8006B", // Target address for first transaction "0x1234567890abcdef" // Calldata to be matched for first transaction ) ``` ### `timestamp` [​](https://docs.gator.metamask.io/development/how-to/create-delegation/restrict-delegation\#timestamp "Direct link to timestamp") Specifies a range of timestamps through which the delegation will be valid. **Caveat enforcer contract:** [`TimestampEnforcer.sol`](https://github.com/MetaMask/delegation-framework/blob/main/src/enforcers/TimestampEnforcer.sol) #### Parameters [​](https://docs.gator.metamask.io/development/how-to/create-delegation/restrict-delegation\#parameters-28 "Direct link to Parameters") 1. After threshold timestamp as a number 2. Before threshold timestamp as a number You can specify `0` to indicate that there is no limitation on a threshold. #### Example [​](https://docs.gator.metamask.io/development/how-to/create-delegation/restrict-delegation\#example-28 "Direct link to Example") ```codeBlockLines_e6Vv caveatBuilder.addCaveat("timestamp", 499165200, 1445412480 ); ``` ### `valueLte` [​](https://docs.gator.metamask.io/development/how-to/create-delegation/restrict-delegation\#valuelte "Direct link to valuelte") Limits the value of native tokens that the delegate can spend. **Caveat enforcer contract:** [`ValueLteEnforcer.sol`](https://github.com/MetaMask/delegation-framework/blob/main/src/enforcers/ValueLteEnforcer.sol) #### Parameters [​](https://docs.gator.metamask.io/development/how-to/create-delegation/restrict-delegation\#parameters-29 "Direct link to Parameters") 1. A value as a `bigint` #### Example [​](https://docs.gator.metamask.io/development/how-to/create-delegation/restrict-delegation\#example-29 "Direct link to Example") ```codeBlockLines_e6Vv caveatBuilder.addCaveat("valueLte", 1_000_000_000_000_000_000n // 1 ETH in wei ); ``` - [Create the caveat builder](https://docs.gator.metamask.io/development/how-to/create-delegation/restrict-delegation#create-the-caveat-builder) - [Add caveats to the builder](https://docs.gator.metamask.io/development/how-to/create-delegation/restrict-delegation#add-caveats-to-the-builder) - [Caveat types](https://docs.gator.metamask.io/development/how-to/create-delegation/restrict-delegation#caveat-types) - [`allowedCalldata`](https://docs.gator.metamask.io/development/how-to/create-delegation/restrict-delegation#allowedcalldata) - [`allowedMethods`](https://docs.gator.metamask.io/development/how-to/create-delegation/restrict-delegation#allowedmethods) - [`allowedTargets`](https://docs.gator.metamask.io/development/how-to/create-delegation/restrict-delegation#allowedtargets) - [`argsEqualityCheck`](https://docs.gator.metamask.io/development/how-to/create-delegation/restrict-delegation#argsequalitycheck) - [`blockNumber`](https://docs.gator.metamask.io/development/how-to/create-delegation/restrict-delegation#blocknumber) - [`deployed`](https://docs.gator.metamask.io/development/how-to/create-delegation/restrict-delegation#deployed) - [`erc1155BalanceGte`](https://docs.gator.metamask.io/development/how-to/create-delegation/restrict-delegation#erc1155balancegte) - [`erc20BalanceGte`](https://docs.gator.metamask.io/development/how-to/create-delegation/restrict-delegation#erc20balancegte) - [`erc20PeriodTransfer`](https://docs.gator.metamask.io/development/how-to/create-delegation/restrict-delegation#erc20periodtransfer) - [`erc20Streaming`](https://docs.gator.metamask.io/development/how-to/create-delegation/restrict-delegation#erc20streaming) - [`erc20TransferAmount`](https://docs.gator.metamask.io/development/how-to/create-delegation/restrict-delegation#erc20transferamount) - [`erc721BalanceGte`](https://docs.gator.metamask.io/development/how-to/create-delegation/restrict-delegation#erc721balancegte) - [`erc721Transfer`](https://docs.gator.metamask.io/development/how-to/create-delegation/restrict-delegation#erc721transfer) - [`exactCalldata`](https://docs.gator.metamask.io/development/how-to/create-delegation/restrict-delegation#exactcalldata) - [`exactCalldataBatch`](https://docs.gator.metamask.io/development/how-to/create-delegation/restrict-delegation#exactcalldatabatch) - [`exactExecution`](https://docs.gator.metamask.io/development/how-to/create-delegation/restrict-delegation#exactexecution) - [`exactExecutionBatch`](https://docs.gator.metamask.io/development/how-to/create-delegation/restrict-delegation#exactexecutionbatch) - [`id`](https://docs.gator.metamask.io/development/how-to/create-delegation/restrict-delegation#id) - [`limitedCalls`](https://docs.gator.metamask.io/development/how-to/create-delegation/restrict-delegation#limitedcalls) - [`nativeBalanceGte`](https://docs.gator.metamask.io/development/how-to/create-delegation/restrict-delegation#nativebalancegte) - [`nativeTokenPayment`](https://docs.gator.metamask.io/development/how-to/create-delegation/restrict-delegation#nativetokenpayment) - [`nativeTokenPeriodTransfer`](https://docs.gator.metamask.io/development/how-to/create-delegation/restrict-delegation#nativetokenperiodtransfer) - [`nativeTokenStreaming`](https://docs.gator.metamask.io/development/how-to/create-delegation/restrict-delegation#nativetokenstreaming) - [`nativeTokenTransferAmount`](https://docs.gator.metamask.io/development/how-to/create-delegation/restrict-delegation#nativetokentransferamount) - [`nonce`](https://docs.gator.metamask.io/development/how-to/create-delegation/restrict-delegation#nonce) - [`ownershipTransfer`](https://docs.gator.metamask.io/development/how-to/create-delegation/restrict-delegation#ownershiptransfer) - [`redeemer`](https://docs.gator.metamask.io/development/how-to/create-delegation/restrict-delegation#redeemer) - [`specificActionERC20TransferBatch`](https://docs.gator.metamask.io/development/how-to/create-delegation/restrict-delegation#specificactionerc20transferbatch) - [`timestamp`](https://docs.gator.metamask.io/development/how-to/create-delegation/restrict-delegation#timestamp) - [`valueLte`](https://docs.gator.metamask.io/development/how-to/create-delegation/restrict-delegation#valuelte) ## Create Delegator Account [Skip to main content](https://docs.gator.metamask.io/development/how-to/create-delegator-account#__docusaurus_skipToContent_fallback) This is a public beta release of the MetaMask Delegation Toolkit. This is the development version of the documentation and some features may not yet be available in the latest release. You can switch to the [latest version](https://docs.gator.metamask.io/how-to/create-delegator-account) (0.10.2). On this page # Create a delegator account The MetaMask Delegation Toolkit is embedded, meaning that the end user can instantly interact with a dapp without wallet authorization, confirmations, or corporate logos. Enable users to create a [delegator account](https://docs.gator.metamask.io/development/concepts/delegator-accounts) directly in your dapp. ## Prerequisites [​](https://docs.gator.metamask.io/development/how-to/create-delegator-account\#prerequisites "Direct link to Prerequisites") - [Install and set up the Delegation Toolkit.](https://docs.gator.metamask.io/development/get-started/install-delegation-toolkit) - [Configure the Delegation Toolkit.](https://docs.gator.metamask.io/development/how-to/configure-delegation-toolkit) ## Create a `MetaMaskSmartAccount` [​](https://docs.gator.metamask.io/development/how-to/create-delegator-account\#create-a-metamasksmartaccount "Direct link to create-a-metamasksmartaccount") The following is an example of creating a delegator account using Viem Core SDK. Viem Core SDK provides low-level interfaces to offer flexibility and control over the delegator account creation lifecycle. In the example, the Viem [`privateKeyToAccount`](https://viem.sh/docs/accounts/privateKey.html) function creates an externally owned account as the owner of the delegator account. - example.ts - config.ts ```codeBlockLines_e6Vv import { publicClient, owner } from "./config.ts"; import { Implementation, toMetaMaskSmartAccount, } from "@metamask/delegation-toolkit"; const deploySalt = "0x"; const smartAccount = await toMetaMaskSmartAccount({ client: publicClient, implementation: Implementation.Hybrid, deployParams: [owner.address, [], [], []], deploySalt, signatory: { account: owner }, }); ``` ```codeBlockLines_e6Vv import { http, createPublicClient } from "viem"; import { privateKeyToAccount, generatePrivateKey } from "viem/accounts"; import { lineaSepolia as chain } from "viem/chains"; const transport = http(); export const publicClient = createPublicClient({ transport, chain, }); const privateKey = generatePrivateKey(); export const owner = privateKeyToAccount(privateKey); ``` This example creates the `MetaMaskSmartAccount`, which can perform several functions: - In conjunction with [Viem Account Abstraction clients](https://docs.gator.metamask.io/development/how-to/configure-delegation-toolkit), deploy the smart contract account, and [send user operations](https://docs.gator.metamask.io/development/how-to/send-user-operation). - [Sign delegations](https://docs.gator.metamask.io/development/how-to/create-delegation) that can be used to grant specific rights and permissions to other accounts. note The example above uses the Hybrid Delegator smart contract account, which is configurable to have an EOA "owner" and any number of P256 (passkey) signers. You can also [configure other delegator account types](https://docs.gator.metamask.io/development/how-to/configure-delegator-accounts-signers). - [Prerequisites](https://docs.gator.metamask.io/development/how-to/create-delegator-account#prerequisites) - [Create a `MetaMaskSmartAccount`](https://docs.gator.metamask.io/development/how-to/create-delegator-account#create-a-metamasksmartaccount) ## Redeem Delegations Guide [Skip to main content](https://docs.gator.metamask.io/development/how-to/redeem-delegation#__docusaurus_skipToContent_fallback) This is a public beta release of the MetaMask Delegation Toolkit. This is the development version of the documentation and some features may not yet be available in the latest release. You can switch to the [latest version](https://docs.gator.metamask.io/how-to/redeem-delegation) (0.10.2). On this page # 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 smart contract account (SCA) or 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 call data for the redeem transaction, use the `redeemDelegation` utility function. The function supports batch redemption, allowing multiple delegations to be processed within a single transaction. ## Prerequisites [​](https://docs.gator.metamask.io/development/how-to/redeem-delegation\#prerequisites "Direct link to Prerequisites") - [Install and set up the Delegation Toolkit.](https://docs.gator.metamask.io/development/get-started/install-delegation-toolkit) - [Configure the Delegation Toolkit.](https://docs.gator.metamask.io/development/how-to/configure-delegation-toolkit) - [Create a delegator account.](https://docs.gator.metamask.io/development/how-to/create-delegator-account) - [Create a delegation.](https://docs.gator.metamask.io/development/how-to/create-delegation) ## Redeem a delegation [​](https://docs.gator.metamask.io/development/how-to/redeem-delegation\#redeem-a-delegation-1 "Direct link to Redeem a delegation") Redeem a delegation with a [smart contract account (SCA)](https://docs.gator.metamask.io/development/how-to/redeem-delegation#redeem-with-an-sca) or an [externally owned account (EOA)](https://docs.gator.metamask.io/development/how-to/redeem-delegation#redeem-with-an-eoa). ### Redeem with an SCA [​](https://docs.gator.metamask.io/development/how-to/redeem-delegation\#redeem-with-an-sca "Direct link to Redeem with an SCA") 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 an SCA. - example.ts - account.ts - client.ts ```codeBlockLines_e6Vv import { DelegationFramework, SINGLE_DEFAULT_MODE, ExecutionStruct } from "@metamask/delegation-toolkit"; 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 = DelegationFramework.encode.redeemDelegations({ delegations: [ delegations ], modes: [ mode ], executions: [ executions ] }); const { fast: fee } = await pimlicoClient.getUserOperationGasPrice(); const userOperationHash = await bundlerClient.sendUserOperation({ account: delegateSmartAccount, calls: [\ {\ to: "",\ data: redeemDelegationCalldata\ }\ ], ...fee }); ``` ```codeBlockLines_e6Vv import { Implementation, toMetaMaskSmartAccount, } from "@metamask/delegation-toolkit"; import { privateKeyToAccount } from "viem/accounts"; improt { 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 }, }); ``` ```codeBlockLines_e6Vv import { createPublicClient, http } from "viem"; import { lineaSepolia 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/59141/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 [​](https://docs.gator.metamask.io/development/how-to/redeem-delegation\#redeem-with-an-eoa "Direct link to 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. - example.ts - account.ts ```codeBlockLines_e6Vv import { DelegationFramework, SINGLE_DEFAULT_MODE, ExecutionStruct } from "@metamask/delegation-toolkit"; import { lineaSepolia 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 = DelegationFramework.encode.redeemDelegations({ delegations: [ delegations ], modes: [ mode ], executions: [ executions ] }); const transactionHash = await walletClient.sendTransaction({ to: getDeleGatorEnvironment(chain.id).DelegationManager, data: redeemDelegationCalldata, chain, }); ``` ```codeBlockLines_e6Vv import { privateKeyToAccount } from "viem/accounts"; import { lineaSepolia 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 [​](https://docs.gator.metamask.io/development/how-to/redeem-delegation\#redeem-multiple-delegations "Direct link to 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 an SCA. The preparation of the call data is the same when [using an EOA as the delegate](https://docs.gator.metamask.io/development/how-to/redeem-delegation#redeem-with-an-eoa); the primary difference is that an EOA submits a regular transaction instead of a user operation. - example.ts - account.ts - client.ts ```codeBlockLines_e6Vv import { DelegationFramework, SINGLE_DEFAULT_MODE, ExecutionStruct } from "@metamask/delegation-toolkit"; 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 = DelegationFramework.encode.redeemDelegations({ delegations: [ delegations ], modes: [ mode ], executions: [ executions ] }); const { fast: fee } = await pimlicoClient.getUserOperationGasPrice(); const userOperationHash = await bundlerClient.sendUserOperation({ account: delegateSmartAccount, calls: [\ {\ to: "",\ data: redeemDelegationCalldata\ }\ ], ...fee }); ``` ```codeBlockLines_e6Vv 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 }, }); ``` ```codeBlockLines_e6Vv import { createPublicClient, http } from "viem"; import { lineaSepolia 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/59141/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 [​](https://docs.gator.metamask.io/development/how-to/redeem-delegation\#execution-modes "Direct link to 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 [​](https://docs.gator.metamask.io/development/how-to/redeem-delegation\#single-execution-modes "Direct link to 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 [​](https://docs.gator.metamask.io/development/how-to/redeem-delegation\#batch-execution-modes "Direct link to 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 [​](https://docs.gator.metamask.io/development/how-to/redeem-delegation\#default-modes "Direct link to default-modes") In `DEFAULT` modes, if a revert occurs during redemption, the entire user operation reverts at that point. ### `TRY` modes [​](https://docs.gator.metamask.io/development/how-to/redeem-delegation\#try-modes "Direct link to try-modes") In `TRY` modes, if a revert occurs during redemption, execution of the user operation continues. - [Prerequisites](https://docs.gator.metamask.io/development/how-to/redeem-delegation#prerequisites) - [Redeem a delegation](https://docs.gator.metamask.io/development/how-to/redeem-delegation#redeem-a-delegation-1) - [Redeem with an SCA](https://docs.gator.metamask.io/development/how-to/redeem-delegation#redeem-with-an-sca) - [Redeem with an EOA](https://docs.gator.metamask.io/development/how-to/redeem-delegation#redeem-with-an-eoa) - [Redeem multiple delegations](https://docs.gator.metamask.io/development/how-to/redeem-delegation#redeem-multiple-delegations) - [Execution modes](https://docs.gator.metamask.io/development/how-to/redeem-delegation#execution-modes) - [`SINGLE` execution modes](https://docs.gator.metamask.io/development/how-to/redeem-delegation#single-execution-modes) - [`BATCH` execution modes](https://docs.gator.metamask.io/development/how-to/redeem-delegation#batch-execution-modes) - [`DEFAULT` modes](https://docs.gator.metamask.io/development/how-to/redeem-delegation#default-modes) - [`TRY` modes](https://docs.gator.metamask.io/development/how-to/redeem-delegation#try-modes) ## Send User Operations [Skip to main content](https://docs.gator.metamask.io/development/how-to/send-user-operation#__docusaurus_skipToContent_fallback) This is a public beta release of the MetaMask Delegation Toolkit. This is the development version of the documentation and some features may not yet be available in the latest release. You can switch to the [latest version](https://docs.gator.metamask.io/how-to/send-user-operation) (0.10.2). On this page # Send a user operation User operations are the [ERC-4337](https://eips.ethereum.org/EIPS/eip-4337) counterpart to traditional blockchain transactions. They incorporate significant enhancements that improve user experience and provide greater flexibility in account management and transaction execution. Viem's Account Abstraction API allows a developer to specify an array of `Calls` that will be executed as a user operation via Viem's [`sendUserOperation`](https://viem.sh/account-abstraction/actions/bundler/sendUserOperation) method. The MetaMask Delegation Toolkit encodes and executes the provided calls. User operations are not directly sent to the network. Instead, they are sent to a bundler, which validates, optimizes, and aggregates them before network submission. See [Viem's Bundler Client](https://viem.sh/account-abstraction/clients/bundler) for details on how to interact with the bundler. note If a user operation is sent from a smart contract account that has not been deployed, the toolkit configures the user operation to automatically deploy the account. ## Prerequisites [​](https://docs.gator.metamask.io/development/how-to/send-user-operation\#prerequisites "Direct link to Prerequisites") - [Install and set up the Delegation Toolkit.](https://docs.gator.metamask.io/development/get-started/install-delegation-toolkit) - [Configure the Delegation Toolkit.](https://docs.gator.metamask.io/development/how-to/configure-delegation-toolkit) - [Create a delegator account.](https://docs.gator.metamask.io/development/how-to/create-delegator-account) ## Send a user operation [​](https://docs.gator.metamask.io/development/how-to/send-user-operation\#send-a-user-operation-1 "Direct link to Send a user operation") The following is a simplified example of sending a user operation using Viem Core SDK. Viem Core SDK offers more granular control for developers who require it. In the example, a user operation is created with the necessary gas limits. This user operation is passed to a bundler instance, and the `EntryPoint` address is retrieved from the client. - example.ts - config.ts ```codeBlockLines_e6Vv import { bundlerClient, smartAccount } from "./config.ts"; // Appropriate fee per gas must be determined for the specific bundler being used. const maxFeePerGas = 1n; const maxPriorityFeePerGas = 1n; const userOperationHash = await bundlerClient.sendUserOperation({ account: smartAccount, calls: [\ {\ to: "0x1234567890123456789012345678901234567890",\ value: parseEther("1")\ }\ ], maxFeePerGas, maxPriortyFeePerGas }); ``` ```codeBlockLines_e6Vv import { createPublicClient, http } from "viem"; import { createBundlerClient } from "viem/account-abstraction"; import { lineaSepolia 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 smartAccount = await toMetaMaskSmartAccount({ client: publicClient, implementation: Implementation.Hybrid, deployParams: [account.address, [], [], []], deploySalt: "0x", signatory: { account }, }); export const bundlerClient = createBundlerClient({ publicClient, transport: http("https://public.pimlico.io/v2/1/rpc") }); ``` ### Estimate fee per gas [​](https://docs.gator.metamask.io/development/how-to/send-user-operation\#estimate-fee-per-gas "Direct link to Estimate fee per gas") Different bundlers have different ways to estimate `maxFeePerGas` and `maxPriorityFeePerGas`, and can reject requests with insufficient values. The following example updates the previous example to estimate the fees. This example uses constant values, but the [Hello Gator example](https://github.com/MetaMask/hello-gator) uses Pimlico's Alto bundler, which fetches user operation gas price using the RPC method [`pimlico_getUserOperationPrice`](https://docs.pimlico.io/infra/bundler/endpoints/pimlico_getUserOperationGasPrice). example.ts ```codeBlockLines_e6Vv + import { createPimlicoClient } from "permissionless/clients/pimlico"; import { bundlerClient, smartAccount } from "./config.ts" // The config.ts is the same as in the previous example. - const maxFeePerGas = 1n; - const maxPriorityFeePerGas = 1n; + const pimlicoClient = createPimlicoClient({ + transport: http("https://api.pimlico.io/v2/59141/rpc"), // You can get the API Key from the Pimlico dashboard. + }); + + const { fast: fee } = await pimlicoClient.getUserOperationGasPrice(); const userOperationHash = await bundlerClient.sendUserOperation({ account: smartAccount, calls: [\ {\ to: "0x1234567890123456789012345678901234567890",\ value: parseEther("1")\ }\ ], - maxFeePerGas, - maxPriortyFeePerGas + ...fee }); ``` ### Wait for the transaction receipt [​](https://docs.gator.metamask.io/development/how-to/send-user-operation\#wait-for-the-transaction-receipt "Direct link to Wait for the transaction receipt") After submitting the user operation, it's crucial to wait for the receipt to ensure that it has been successfully included in the blockchain. Use the `waitForUserOperationReceipt` method provided by the bundler client. example.ts ```codeBlockLines_e6Vv import { createPimlicoClient } from "permissionless/clients/pimlico"; import { bundlerClient, smartAccount } from "./config.ts" // The config.ts is the same as in the previous example. const pimlicoClient = createPimlicoClient({ transport: http("https://api.pimlico.io/v2/59141/rpc"), // You can get the API Key from the Pimlico dashboard. }); const { fast: fee } = await pimlicoClient.getUserOperationGasPrice(); const userOperationHash = await bundlerClient.sendUserOperation({ account: smartAccount, calls: [\ {\ to: "0x1234567890123456789012345678901234567890",\ value: parseEther("1")\ }\ ], ...fee }); + const { receipt } = await bundlerClient.waitForUserOperationReceipt({ + hash: userOperationHash + }); + + console.log(receipt.transactionHash); ``` - [Prerequisites](https://docs.gator.metamask.io/development/how-to/send-user-operation#prerequisites) - [Send a user operation](https://docs.gator.metamask.io/development/how-to/send-user-operation#send-a-user-operation-1) - [Estimate fee per gas](https://docs.gator.metamask.io/development/how-to/send-user-operation#estimate-fee-per-gas) - [Wait for the transaction receipt](https://docs.gator.metamask.io/development/how-to/send-user-operation#wait-for-the-transaction-receipt)