Skip to content

Commit 633d478

Browse files
authored
Merge branch 'main' into restructure-ew
2 parents 1c4c6b5 + 66260e7 commit 633d478

File tree

133 files changed

+1785
-8607
lines changed

Some content is hidden

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

133 files changed

+1785
-8607
lines changed

delegation-toolkit/concepts/erc7715.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ ERC-7715 eliminates the need for users to approve every transaction, which is us
1313
It also enables dapps to execute transactions for users without an active wallet connection.
1414

1515
:::note
16-
This feature requires [MetaMask Flask 12.14.2](/snaps/get-started/install-flask) or later.
16+
This feature requires [MetaMask Flask 13.5.0](/snaps/get-started/install-flask) or later.
1717
:::
1818

1919
## ERC-7715 technical overview

delegation-toolkit/experimental/erc-7715-request-permissions.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ import TabItem from "@theme/TabItem";
99

1010
:::caution Experimental
1111
This is an experimental feature.
12-
It requires MetaMask Flask 12.14.2 or later, and may change in future releases.
12+
It requires MetaMask Flask 13.5.0 or later, and may change in future releases.
1313
:::
1414

1515
[ERC-7715](https://eip.tools/eip/7715) introduces a standard way for dapps to request permissions from a wallet to execute

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.

delegation-toolkit/guides/delegation/use-delegation-scopes/function-call.md

Lines changed: 88 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -3,14 +3,14 @@ description: Learn how to use the function call scope for a delegation.
33
keywords: [delegation scope, function call, restrict, delegation]
44
---
55

6+
import Tabs from "@theme/Tabs";
7+
import TabItem from "@theme/TabItem";
8+
69
# Use the function call scope
710

811
The function call scope defines the specific methods, contract addresses, and calldata that are allowed for the delegation.
912
For example, Alice delegates to Bob the ability to call the `approve` function on the USDC contract, with the approval amount set to `0`.
1013

11-
Internally, this scope uses the [`allowedTargets`](../../../reference/delegation/caveats.md#allowedtargets) and [`allowedMethods`](../../../reference/delegation/caveats.md#allowedmethods) caveat enforcers, and
12-
optionally uses the [`allowedCalldata`](../../../reference/delegation/caveats.md#allowedcalldata) or [`exactCalldata`](../../../reference/delegation/caveats.md#exactcalldata) caveat enforcers when those parameters are specified.
13-
1414
## Prerequisites
1515

1616
- [Install and set up the Delegation Toolkit.](../../../get-started/install.md)
@@ -20,10 +20,13 @@ optionally uses the [`allowedCalldata`](../../../reference/delegation/caveats.md
2020

2121
## Function call scope
2222

23-
This scope requires `targets` and `selectors` as mandatory parameters for the configuration.
24-
You can specify the allowed methods in `selectors` and the permitted contract addresses in `targets`.
23+
This scope requires `targets`, which specifies the permitted contract addresses, and `selectors`, which specifies the allowed methods.
24+
25+
Internally, this scope uses the [`allowedTargets`](../../../reference/delegation/caveats.md#allowedtargets) and [`allowedMethods`](../../../reference/delegation/caveats.md#allowedmethods) caveat enforcers, and
26+
optionally uses the [`allowedCalldata`](../../../reference/delegation/caveats.md#allowedcalldata) or [`exactCalldata`](../../../reference/delegation/caveats.md#exactcalldata) caveat enforcers when those parameters are specified.
27+
See the [function call scope reference](../../../reference/delegation/delegation-scopes.md#function-call-scope) for more details.
2528

26-
The following example sets the delegation scope to allow the delegate to call the `approve` function on the USDC token contract.
29+
The following example sets the delegation scope to allow the delegate to call the `approve` function on the USDC token contract:
2730

2831
```typescript
2932
import { createDelegation } from "@metamask/delegation-toolkit";
@@ -35,7 +38,85 @@ const delegation = createDelegation({
3538
scope: {
3639
type: "functionCall",
3740
targets: [USDC_ADDRESS],
38-
selectors: ["approve(address, uint256)"]
41+
selectors: ["approve(address, uint256)"],
42+
},
43+
to: delegateAccount,
44+
from: delegatorAccount,
45+
environment: delegatorAccount.environment,
46+
});
47+
```
48+
49+
### Define allowed calldata
50+
51+
You can further restrict the scope by defining the `allowedCalldata`. For example, you can set
52+
`allowedCalldata` so the delegate is only permitted to call the `approve` function on the
53+
USDC token contract with an allowance value of `0`. This effectively limits the delegate to
54+
revoking ERC-20 approvals.
55+
56+
:::important Usage
57+
The `allowedCalldata` doesn't support multiple selectors. Each entry in the
58+
list represents a portion of calldata corresponding to the same function signature.
59+
60+
You can include or exclude specific parameters to precisely define what parts of the calldata are valid.
61+
:::
62+
63+
```typescript
64+
import { createDelegation } from "@metamask/delegation-toolkit";
65+
import { encodeAbiParameters, erc20Abi } from "viem";
66+
67+
// USDC address on Sepolia.
68+
const USDC_ADDRESS = "0x1c7D4B196Cb0C7B01d743Fbc6116a902379C7238";
69+
70+
const delegation = createDelegation({
71+
scope: {
72+
type: "functionCall",
73+
targets: [USDC_ADDRESS],
74+
selectors: ["approve(address, uint256)"],
75+
allowedCalldata: [
76+
{
77+
// Limits the allowance amount to be 0.
78+
value: encodeAbiParameters(
79+
[{ name: 'amount', type: 'uint256' }],
80+
[0n],
81+
),
82+
// The first 4 bytes are for selector, and next 32 bytes
83+
// are for spender address.
84+
startIndex: 36,
85+
},
86+
]
87+
},
88+
to: delegateAccount,
89+
from: delegatorAccount,
90+
environment: delegatorAccount.environment,
91+
});
92+
```
93+
94+
### Define exact calldata
95+
96+
You can define the `exactCalldata` instead of the `allowedCalldata`. For example, you can
97+
set `exactCalldata` so the delegate is permitted to call only the `approve` function on the USDC token
98+
contract, with a specific spender address and an allowance value of 0. This effectively limits the delegate to
99+
revoking ERC-20 approvals for a specific spender.
100+
101+
```typescript
102+
import { createDelegation } from "@metamask/delegation-toolkit";
103+
import { encodeFunctionData, erc20Abi } from "viem";
104+
105+
// USDC address on Sepolia.
106+
const USDC_ADDRESS = "0x1c7D4B196Cb0C7B01d743Fbc6116a902379C7238";
107+
108+
const delegation = createDelegation({
109+
scope: {
110+
type: "functionCall",
111+
targets: [USDC_ADDRESS],
112+
selectors: ["approve(address, uint256)"],
113+
exactCalldata: {
114+
calldata: encodeFunctionData({
115+
abi: erc20Abi,
116+
args: ["0x0227628f3F023bb0B980b67D528571c95c6DaC1c", 0n],
117+
functionName: 'approve',
118+
})
119+
}
39120
},
40121
to: delegateAccount,
41122
from: delegatorAccount,

delegation-toolkit/guides/delegation/use-delegation-scopes/ownership-transfer.md

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,6 @@ keywords: [delegation scope, ownership transfer, restrict, delegation]
88
The ownership transfer scope restricts a delegation to ownership transfer calls only.
99
For example, Alice has deployed a smart contract, and she delegates to Bob the ability to transfer ownership of that contract.
1010

11-
Internally, this scope uses the [`ownershipTransfer`](../../../reference/delegation/caveats.md#ownershiptransfer) caveat enforcer.
12-
1311
## Prerequisites
1412

1513
- [Install and set up the Delegation Toolkit.](../../../get-started/install.md)
@@ -21,6 +19,9 @@ Internally, this scope uses the [`ownershipTransfer`](../../../reference/delegat
2119

2220
This scope requires a `contractAddress`, which represents the address of the deployed contract.
2321

22+
Internally, this scope uses the [`ownershipTransfer`](../../../reference/delegation/caveats.md#ownershiptransfer) caveat enforcer.
23+
See the [ownership transfer scope reference](../../../reference/delegation/delegation-scopes.md#ownership-transfer-scope) for more details.
24+
2425
```typescript
2526
import { createDelegation } from "@metamask/delegation-toolkit";
2627

0 commit comments

Comments
 (0)