Skip to content

Commit 39b9b16

Browse files
committed
Merge branch 'main' into sdk-new-structure
2 parents ef20ee1 + 3e17894 commit 39b9b16

File tree

408 files changed

+15721
-609
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

408 files changed

+15721
-609
lines changed

.github/workflows/crowdin.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ jobs:
1515
uses: actions/checkout@v5
1616

1717
- name: Synchronize with Crowdin
18-
uses: crowdin/github-action@v1
18+
uses: crowdin/github-action@v2
1919
with:
2020
upload_sources: true
2121
upload_translations: true
87.3 KB
Loading

delegation-toolkit/concepts/delegation/caveat-enforcers.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ keywords: [caveats, caveat enforcers, delegation]
66
# Caveat enforcers
77

88
The MetaMask Delegation Toolkit provides *caveat enforcers*, which are smart contracts that implement rules and restrictions (*caveats*) on delegations.
9-
They serve as the underlying mechanism that enables conditional execution within the [Delegation Framework](index.md#delegation-framework).
9+
They serve as the underlying mechanism that enables conditional execution within the [Delegation Framework](./index.md#delegation-framework).
1010

1111
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.
1212

@@ -164,7 +164,7 @@ For other restriction patterns, you can also [create custom caveat enforcers](/t
164164

165165
## Attenuating authority with redelegations
166166

167-
When creating chains of delegations via [redelegations](index.md#delegation-types), it's important to understand how authority flows and can be restricted.
167+
When creating chains of delegations via [redelegations](./index.md#delegation-types), it's important to understand how authority flows and can be restricted.
168168

169169
Caveats applied to a chain of delegations are *accumulative*—they stack on top of each other:
170170

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
---
2+
description: Learn about MetaMask ERC-7715 permissions.
3+
keywords: [ERC-7715, 7715, permissions, wallet, smart account]
4+
---
5+
6+
# ERC-7715 permissions
7+
8+
The Delegation Toolkit supports [ERC-7715](https://eips.ethereum.org/EIPS/eip-7715), which lets you request fine-grained permissions from a MetaMask user to execute transactions on their behalf.
9+
For example, a user can grant your dapp permission to spend 10 USDC per day to buy ETH over the course of a month.
10+
Once the permission is granted, your dapp can use the allocated 10 USDC each day to purchase ETH directly from the MetaMask user's account.
11+
12+
ERC-7715 eliminates the need for users to approve every transaction, which is useful for highly interactive dapps.
13+
It also enables dapps to execute transactions for users without an active wallet connection.
14+
15+
:::note
16+
This feature requires [MetaMask Flask 12.14.2](/snaps/get-started/install-flask) or later.
17+
:::
18+
19+
## ERC-7715 technical overview
20+
21+
[ERC-7715](https://eips.ethereum.org/EIPS/eip-7715) defines a JSON-RPC method `wallet_grantPermissions`.
22+
Dapps can use this method to request a wallet to grant the dapp permission to execute transactions on a user's behalf.
23+
`wallet_grantPermissions` requires a `signer` parameter, which identifies the entity requesting or managing the permission.
24+
Common signer implementations include wallet signers, single key and multisig signers, and account signers.
25+
26+
The Delegation Toolkit supports multiple types of signers, but [an account signer is used in this documentation's examples](../guides/erc7715/execute-on-metamask-users-behalf.md) as a common implementation.
27+
With an account signer, a session account is created and used for the single purpose of requesting and redeeming ERC-7715 permissions, and does not contain tokens.
28+
The session account can be granted with permissions and redeem them as specified in [ERC-7710](https://eips.ethereum.org/EIPS/eip-7710).
29+
The session account can be a smart account or an externally owned account (EOA).
30+
31+
The MetaMask user that the session account requests permissions from must be upgraded to a [MetaMask smart account](smart-accounts.md).
32+
33+
## ERC-7715 vs. delegations
34+
35+
ERC-7715 expands on regular [delegations](delegation/index.md) by enabling permission sharing *via the MetaMask browser extension*.
36+
37+
With regular delegations, the dapp constructs a delegation and requests the user to sign it.
38+
These delegations are not human-readable, so it is the dapp's responsibility to provide context for the user.
39+
Regular delegations cannot be signed through the MetaMask extension, because if a dapp requests a delegation without constraints, the whole wallet can be exposed to the dapp.
40+
41+
In contrast, ERC-7715 enables dapps (and AI agents) to request permissions from a user directly via the MetaMask extension.
42+
ERC-7715 requires a permission configuration which displays a human-readable confirmation for the MetaMask user.
43+
The user can modify the permission parameters if the request is configured to allow adjustments.
44+
45+
For example, the following ERC-7715 permission request displays a rich UI including the start time, amount, and period duration for an [ERC-20 token periodic transfer](../guides/erc7715/use-permissions/erc20-token.md#erc-20-periodic-permission):
46+
47+
<p align="center">
48+
<img src={require("../assets/erc7715-request.png").default} alt="ERC-7715 request" width="450px" class="appScreen" />
49+
</p>
50+
51+
## ERC-7715 permissions lifecycle
52+
53+
The ERC-7715 permissions lifecycle is as follows:
54+
55+
1. **Set up a session account** - Set up a session account to execute transactions on behalf of the MetaMask user.
56+
It can be a [smart account](smart-accounts.md) or an externally owned account (EOA).
57+
58+
2. **Request permissions** - Request permissions from the user.
59+
The Delegation Toolkit supports [ERC-20 token permissions](../guides/erc7715/use-permissions/erc20-token.md) and
60+
[native token permissions](../guides/erc7715/use-permissions/native-token.md).
61+
62+
4. **Redeem permissions** - Once the permission is granted, the session account can redeem the permission, executing on the user's behalf.
63+
64+
See [how to perform executions on a MetaMask user's behalf](../guides/erc7715/execute-on-metamask-users-behalf.md) to get started with the ERC-7715 lifecycle.

delegation-toolkit/get-started/supported-networks.md

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ If you don't see the network you're looking for, you can request support by emai
2323
| Unichain ||||
2424
| Arbitrum Nova ||||
2525
| Berachain ||||
26+
| Ink ||||
2627

2728
## Testnet networks
2829

@@ -38,4 +39,6 @@ If you don't see the network you're looking for, you can request support by emai
3839
| Optimism Sepolia ||||
3940
| Binance Smart Chain ||||
4041
| Polygon Amoy ||||
41-
| Monad ||||
42+
| Monad ||||
43+
| Ink Sepolia ||||
44+
| Citrea ||||

delegation-toolkit/guides/configure-toolkit.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -135,7 +135,7 @@ const environment: DeleGatorEnvironment = getDelegatorEnvironment(11155111);
135135

136136
You can deploy the contracts using any method, but the toolkit provides a convenient [`deployDelegatorEnvironment`](../reference/delegation/index.md#deploydelegatorenvironment) function. This function simplifies deploying the Delegation Framework contracts to your desired EVM chain.
137137

138-
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)
138+
This function requires a Viem [Public Client](https://viem.sh/docs/clients/public), [Wallet Client](https://viem.sh/docs/clients/wallet), and [Chain](https://viem.sh/docs/glossary/types#chain)
139139
to deploy the contracts and resolve the `DeleGatorEnvironment`.
140140

141141
Your wallet must have a sufficient native token balance to deploy the contracts.

delegation-toolkit/guides/delegation/check-delegation-state.md

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -82,14 +82,18 @@ const { availableAmount } = await caveatEnforcerClient.getErc20PeriodTransferEnf
8282
8383
```typescript
8484
import { createDelegation } from '@metamask/delegation-toolkit'
85+
import { parseUnits } from 'viem'
86+
87+
// startDate should be in seconds.
88+
const startDate = Math.floor(Date.now() / 1000);
8589

8690
export const delegation = createDelegation({
8791
scope: {
8892
type: 'erc20PeriodTransfer',
8993
tokenAddress: '0xb4aE654Aca577781Ca1c5DE8FbE60c2F423f37da',
90-
periodAmount: 1000000000000000000n,
94+
periodAmount: parseUnits('10', 6),
9195
periodDuration: 86400,
92-
startDate: 1743763600,
96+
startDate,
9397
},
9498
to: delegateAccount,
9599
from: delegatorAccount,
Lines changed: 99 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,99 @@
1+
---
2+
description: Learn how to disable the delegation.
3+
sidebar_label: Disable a delegation
4+
toc_max_heading_level: 3
5+
keywords: [delegation, disable, revoke]
6+
---
7+
8+
import Tabs from "@theme/Tabs";
9+
import TabItem from "@theme/TabItem";
10+
11+
# Disable a delegation
12+
13+
Delegations are created off-chain and can be stored anywhere, but you can disable a delegation on-chain using the
14+
toolkit. When a delegation is disabled, any attempt to redeem it will revert, effectively revoking the permissions
15+
that were previously granted.
16+
17+
For example, if Alice has given permission to Bob to spend 10 USDC on her behalf, and after a week she wants to
18+
revoke that permission, Alice can disable the delegation she created for Bob. If Bob tries to redeem the disabled
19+
delegation, the transaction will revert, preventing him from spending Alice's USDC.
20+
21+
## Prerequisites
22+
23+
- [Install and set up the Delegation Toolkit.](../../get-started/install.md)
24+
- [Create a delegator account.](execute-on-smart-accounts-behalf.md#3-create-a-delegator-account)
25+
- [Create a delegate account.](execute-on-smart-accounts-behalf.md#4-create-a-delegate-account)
26+
27+
28+
## Disable a delegation
29+
30+
To disable a delegation, you can use the [`disableDelegation`](../../reference/delegation/index.md#disabledelegation) utility function from the
31+
toolkit to generate calldata. Once the calldata is prepared, you can send it to the
32+
Delegation Manager to disable the delegation.
33+
34+
<Tabs>
35+
<TabItem value="example.ts">
36+
37+
```typescript
38+
import { DelegationManager } from '@metamask/delegation-toolkit/contracts';
39+
import { environment, delegation, bundlerClient } from "./config.ts";
40+
41+
const disableDelegationData = DelegationManager.encode.disableDelegation({
42+
delegation,
43+
});
44+
45+
// Appropriate fee per gas must be determined for the specific bundler being used.
46+
const maxFeePerGas = 1n;
47+
const maxPriorityFeePerGas = 1n;
48+
49+
const userOperationHash = await bundlerClient.sendUserOperation({
50+
account: delegatorAccount,
51+
calls: [
52+
{
53+
to: environment.DelegationManager,
54+
data: disableDelegationData
55+
}
56+
],
57+
maxFeePerGas,
58+
maxPriorityFeePerGas
59+
});
60+
```
61+
62+
</TabItem>
63+
<TabItem value="config.ts">
64+
65+
```typescript
66+
import { sepolia as chain } from 'viem/chains'
67+
import { createPublicClient, http, parseEther } from 'viem'
68+
import { createBundlerClient } from 'viem/account-abstraction'
69+
import { getDeleGatorEnvironment, createDelegation } from '@metamask/delegation-toolkit'
70+
71+
export const environment = getDeleGatorEnvironment(chain.id)
72+
73+
const currentTime = Math.floor(Date.now() / 1000)
74+
75+
export const delegation = createDelegation({
76+
scope: {
77+
type: 'nativeTokenPeriodTransfer',
78+
periodAmount: parseEther('0.01'),
79+
periodDuration: 86400,
80+
startDate: currentTime,
81+
},
82+
to: delegateAccount,
83+
from: delegatorAccount,
84+
environment: delegatorAccount.environment,
85+
})
86+
87+
const publicClient = createPublicClient({
88+
chain,
89+
transport: http()
90+
})
91+
92+
export const bundlerClient = createBundlerClient({
93+
client: publicClient,
94+
transport: http('https://api.pimlico.io/v2/11155111/rpc')
95+
});
96+
```
97+
98+
</TabItem>
99+
</Tabs>

delegation-toolkit/guides/delegation/execute-on-smart-accounts-behalf.md

Lines changed: 32 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -137,9 +137,10 @@ Before creating a delegation, ensure that the delegator account (in this example
137137

138138
```typescript
139139
import { createDelegation } from "@metamask/delegation-toolkit"
140+
import { parseUnits } from "viem"
140141

141142
// USDC address on Ethereum Sepolia.
142-
const tokenAddress = "0x1c7D4B196Cb0C7B01d743Fbc6116a902379C7238";
143+
const tokenAddress = "0x1c7D4B196Cb0C7B01d743Fbc6116a902379C7238"
143144

144145
const delegation = createDelegation({
145146
to: delegateSmartAccount.address, // This example uses a delegate smart account
@@ -148,7 +149,8 @@ const delegation = createDelegation({
148149
scope: {
149150
type: "erc20TransferAmount",
150151
tokenAddress,
151-
maxAmount: 10000000n,
152+
// 10 USDC
153+
maxAmount: parseUnits("10", 6),
152154
},
153155
})
154156
```
@@ -175,7 +177,7 @@ Bob can now redeem the delegation. The redeem transaction is sent to the `Delega
175177
To prepare the calldata for the redeem transaction, use the [`redeemDelegations`](../../reference/delegation/index.md#redeemdelegations) method from `DelegationManager`.
176178
Since Bob is redeeming a single delegation chain, use the [`SingleDefault`](../../concepts/delegation/index.md#execution-modes) execution mode.
177179

178-
Bob can redeem the delegation by submitting a user operation if his account is a smart account, or a regular transaction if his account is an EOA:
180+
Bob can redeem the delegation by submitting a user operation if his account is a smart account, or a regular transaction if his account is an EOA. In this example, Bob transfers 1 USDC from Alice’s account to his own.
179181

180182
<Tabs>
181183
<TabItem value="Redeem with a smart account">
@@ -184,10 +186,14 @@ Bob can redeem the delegation by submitting a user operation if his account is a
184186
import { createExecution, ExecutionMode } from "@metamask/delegation-toolkit"
185187
import { DelegationManager } from "@metamask/delegation-toolkit/contracts"
186188
import { zeroAddress } from "viem"
189+
import { callData } from "./config.ts"
187190

188191
const delegations = [signedDelegation]
189192

190-
const executions = createExecution({ target: zeroAddress })
193+
// USDC address on Ethereum Sepolia.
194+
const tokenAddress = "0x1c7D4B196Cb0C7B01d743Fbc6116a902379C7238"
195+
196+
const executions = createExecution({ target: tokenAddress, callData })
191197

192198
const redeemDelegationCalldata = DelegationManager.encode.redeemDelegations({
193199
delegations: [delegations],
@@ -215,10 +221,14 @@ const userOperationHash = await bundlerClient.sendUserOperation({
215221
import { createExecution, getDeleGatorEnvironment, ExecutionMode } from "@metamask/delegation-toolkit"
216222
import { DelegationManager } from "@metamask/delegation-toolkit/contracts"
217223
import { zeroAddress } from "viem"
224+
import { callData } from "./config.ts"
218225

219226
const delegations = [signedDelegation]
220227

221-
const executions = createExecution({ target: zeroAddress })
228+
// USDC address on Ethereum Sepolia.
229+
const tokenAddress = "0x1c7D4B196Cb0C7B01d743Fbc6116a902379C7238"
230+
231+
const executions = createExecution({ target: tokenAddress, callData })
222232

223233
const redeemDelegationCalldata = DelegationManager.encode.redeemDelegations({
224234
delegations: [delegations],
@@ -233,10 +243,26 @@ const transactionHash = await delegateWalletClient.sendTransaction({
233243
})
234244
```
235245

246+
</TabItem>
247+
248+
<TabItem value="config.ts">
249+
250+
```typescript
251+
import { encodeFunctionData, erc20Abi, parseUnits } from "viem"
252+
253+
// calldata to transfer 1 USDC to delegate address.
254+
export const callData = encodeFunctionData({
255+
abi: erc20Abi,
256+
args: [ delegateSmartAccount.address, parseUnits("1", 6) ],
257+
functionName: 'transfer',
258+
})
259+
```
260+
236261
</TabItem>
237262
</Tabs>
238263

239264
## Next steps
240265

241266
- See [how to configure different scopes](use-delegation-scopes/index.md) to define the initial authority of a delegation.
242-
- See [how to further refine the authority of a delegation](use-delegation-scopes/constrain-scope.md) using caveat enforcers.
267+
- See [how to further refine the authority of a delegation](use-delegation-scopes/constrain-scope.md) using caveat enforcers.
268+
- See [how to disable a delegation](disable-delegation.md) to revoke permissions.

0 commit comments

Comments
 (0)