Skip to content
Merged
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,14 @@ description: Learn how to use the function call scope for a delegation.
keywords: [delegation scope, function call, restrict, delegation]
---

import Tabs from "@theme/Tabs";
import TabItem from "@theme/TabItem";

# Use the function call scope

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

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

## Prerequisites

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

## Function call scope

This scope requires `targets` and `selectors` as mandatory parameters for the configuration.
You can specify the allowed methods in `selectors` and the permitted contract addresses in `targets`.
This scope requires `targets`, which specifies the permitted contract addresses, and `selectors`, which specifies the allowed methods.

Internally, this scope uses the [`allowedTargets`](../../../reference/delegation/caveats.md#allowedtargets) and [`allowedMethods`](../../../reference/delegation/caveats.md#allowedmethods) caveat enforcers, and
optionally uses the [`allowedCalldata`](../../../reference/delegation/caveats.md#allowedcalldata) or [`exactCalldata`](../../../reference/delegation/caveats.md#exactcalldata) caveat enforcers when those parameters are specified.
See the [function call scope reference](../../../reference/delegation/delegation-scopes.md#function-call-scope) for more details.

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

```typescript
import { createDelegation } from "@metamask/delegation-toolkit";
Expand All @@ -35,7 +38,85 @@ const delegation = createDelegation({
scope: {
type: "functionCall",
targets: [USDC_ADDRESS],
selectors: ["approve(address, uint256)"]
selectors: ["approve(address, uint256)"],
},
to: delegateAccount,
from: delegatorAccount,
environment: delegatorAccount.environment,
});
```

### Define allowed calldata

You can further restrict the scope by defining the `allowedCalldata`. For example, you can set
`allowedCalldata` so the delegate is only permitted to call the `approve` function on the
USDC token contract with an allowance value of `0`. This effectively limits the delegate to
revoking ERC-20 approvals.

:::important Usage
The `allowedCalldata` doesn't support multiple selectors. Each entry in the
list represents a portion of calldata corresponding to the same function signature.

You can include or exclude specific parameters to precisely define what parts of the calldata are valid.
:::

```typescript
import { createDelegation } from "@metamask/delegation-toolkit";
import { encodeAbiParameters, erc20Abi } from "viem";

// USDC address on Sepolia.
const USDC_ADDRESS = "0x1c7D4B196Cb0C7B01d743Fbc6116a902379C7238";

const delegation = createDelegation({
scope: {
type: "functionCall",
targets: [USDC_ADDRESS],
selectors: ["approve(address, uint256)"],
allowedCalldata: [
{
// Limits the allowance amount to be 0.
value: encodeAbiParameters(
[{ name: 'amount', type: 'uint256' }],
[0n],
),
// The first 4 bytes are for selector, and next 32 bytes
// are for spender address.
startIndex: 36,
},
]
},
to: delegateAccount,
from: delegatorAccount,
environment: delegatorAccount.environment,
});
```

### Define exact calldata

You can define the `exactCalldata` instead of the `allowedCalldata`. For example, you can
set `exactCalldata` so the delegate is permitted to call only the `approve` function on the USDC token
contract, with a specific spender address and an allowance value of 0. This effectively limits the delegate to
revoking ERC-20 approvals for a specific spender.

```typescript
import { createDelegation } from "@metamask/delegation-toolkit";
import { encodeFunctionData, erc20Abi } from "viem";

// USDC address on Sepolia.
const USDC_ADDRESS = "0x1c7D4B196Cb0C7B01d743Fbc6116a902379C7238";

const delegation = createDelegation({
scope: {
type: "functionCall",
targets: [USDC_ADDRESS],
selectors: ["approve(address, uint256)"],
exactCalldata: {
calldata: encodeFunctionData({
abi: erc20Abi,
args: ["0x0227628f3F023bb0B980b67D528571c95c6DaC1c", 0n],
functionName: 'approve',
})
}
},
to: delegateAccount,
from: delegatorAccount,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,6 @@ keywords: [delegation scope, ownership transfer, restrict, delegation]
The ownership transfer scope restricts a delegation to ownership transfer calls only.
For example, Alice has deployed a smart contract, and she delegates to Bob the ability to transfer ownership of that contract.

Internally, this scope uses the [`ownershipTransfer`](../../../reference/delegation/caveats.md#ownershiptransfer) caveat enforcer.

## Prerequisites

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

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

Internally, this scope uses the [`ownershipTransfer`](../../../reference/delegation/caveats.md#ownershiptransfer) caveat enforcer.
See the [ownership transfer scope reference](../../../reference/delegation/delegation-scopes.md#ownership-transfer-scope) for more details.

```typescript
import { createDelegation } from "@metamask/delegation-toolkit";

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,14 +18,15 @@ You can set transfer limits with or without time-based (periodic) or streaming c
## ERC-20 periodic scope

This scope ensures a per-period limit for ERC-20 token transfers.
You set the amount and the time window.
You set the amount, period, and start data.
At the start of each new period, the allowance resets.
For example, Alice creates a delegation that lets Bob spend up to 10 USDC on her behalf each day.
Bob can transfer a total of 10 USDC per day; the limit resets at the beginning of the next day.

When this scope is applied, the toolkit automatically disallows native token transfers (sets the native token transfer limit to `0`).

Internally, this scope uses the [`erc20PeriodTransfer`](../../../reference/delegation/caveats.md#erc20periodtransfer) and [`valueLte`](../../../reference/delegation/caveats.md#valuelte) caveat enforcers.
See the [ERC-20 periodic scope reference](../../../reference/delegation/delegation-scopes.md#erc-20-periodic-scope) for more details.

```typescript
import { createDelegation } from "@metamask/delegation-toolkit";
Expand Down Expand Up @@ -59,6 +60,7 @@ For example, Alice creates a delegation that allows Bob to spend 0.1 USDC per se
When this scope is applied, the toolkit automatically disallows native token transfers (sets the native token transfer limit to `0`).

Internally, this scope uses the [`erc20Streaming`](../../../reference/delegation/caveats.md#erc20streaming) and [`valueLte`](../../../reference/delegation/caveats.md#valuelte) caveat enforcers.
See the [ERC-20 streaming scope reference](../../../reference/delegation/delegation-scopes.md#erc-20-streaming-scope) for more details.

```typescript
import { createDelegation } from "@metamask/delegation-toolkit";
Expand Down Expand Up @@ -86,13 +88,14 @@ const delegation = createDelegation({
## ERC-20 transfer scope

This scope ensures that ERC-20 token transfers are limited to a predefined maximum amount.
This scope is useful for setting simple, fixed transfer limits without any time based or streaming conditions.
This scope is useful for setting simple, fixed transfer limits without any time-based or streaming conditions.
For example, Alice creates a delegation that allows Bob to spend up to 10 USDC without any conditions.
Bob may use the 10 USDC in a single transaction or make multiple transactions, as long as the total does not exceed 10 USDC.

When this scope is applied, the toolkit automatically disallows native token transfers (sets the native token transfer limit to `0`).

Internally, this scope uses the [`erc20TransferAmount`](../../../reference/delegation/caveats.md#erc20transferamount) and [`valueLte`](../../../reference/delegation/caveats.md#valuelte) caveat enforcers.
See the [ERC-20 transfer scope reference](../../../reference/delegation/delegation-scopes.md#erc-20-transfer-scope) for more details.

```typescript
import { createDelegation } from "@metamask/delegation-toolkit";
Expand All @@ -117,6 +120,7 @@ This scope limits the delegation to ERC-721 token transfers only.
For example, Alice creates a delegation that allows Bob to transfer an NFT she owns on her behalf.

Internally, this scope uses the [`erc721Transfer`](../../../reference/delegation/caveats.md#erc721transfer) caveat enforcer.
See the [ERC-721 scope reference](../../../reference/delegation/delegation-scopes.md#erc-721-scope) for more details.

```typescript
import { createDelegation } from "@metamask/delegation-toolkit";
Expand All @@ -136,14 +140,18 @@ const delegation = createDelegation({
## Native token periodic scope

This scope ensures a per-period limit for native token transfers.
You set the amount and the time window.
You set the amount, period, and start date.
At the start of each new period, the allowance resets.
For example, Alice creates a delegation that lets Bob spend up to 0.01 ETH on her behalf each day.
Bob can transfer a total of 0.01 ETH per day; the limit resets at the beginning of the next day.

When this scope is applied, the toolkit disallows ERC-20 and ERC-721 token transfers by default, setting the allowed `calldata` to `0x`.
When this scope is applied, the toolkit disallows ERC-20 and ERC-721 token transfers by default (sets `exactCalldata` to `0x`).
You can optionally configure `exactCalldata` to restrict transactions to a specific operation, or configure
`allowedCalldata` to allow transactions that match certain patterns or ranges.

Internally, this scope uses the [`exactCalldata`](../../../reference/delegation/caveats.md#exactcalldata) and [`nativeTokenPeriodTransfer`](../../../reference/delegation/caveats.md#nativetokenperiodtransfer) caveat enforcers.
Internally, this scope uses the [`nativeTokenPeriodTransfer`](../../../reference/delegation/caveats.md#nativetokenperiodtransfer) caveat enforcer, and
optionally uses the [`allowedCalldata`](../../../reference/delegation/caveats.md#allowedcalldata) or [`exactCalldata`](../../../reference/delegation/caveats.md#exactcalldata) caveat enforcers when those parameters are specified.
See the [native token periodic scope reference](../../../reference/delegation/delegation-scopes.md#native-token-periodic-scope) for more details.

```typescript
import { createDelegation } from "@metamask/delegation-toolkit";
Expand Down Expand Up @@ -172,9 +180,13 @@ Token transfers are blocked until the defined start timestamp.
At the start, a specified initial amount is released, after which tokens accrue linearly at the configured rate, up to the maximum allowed amount.
For example, Alice creates delegation that allows Bob to spend 0.001 ETH per second, starting with an initial amount of 0.01 ETH, up to a maximum of 0.1 ETH.

When this scope is applied, the toolkit disallows ERC-20 and ERC-721 token transfers by default, setting the allowed `calldata` to `0x`.
When this scope is applied, the toolkit disallows ERC-20 and ERC-721 token transfers by default (sets `exactCalldata` to `0x`).
You can optionally configure `exactCalldata` to restrict transactions to a specific operation, or configure
`allowedCalldata` to allow transactions that match certain patterns or ranges.

Internally, this scope uses the [`exactCalldata`](../../../reference/delegation/caveats.md#exactcalldata) and [`nativeTokenStreaming`](../../../reference/delegation/caveats.md#nativetokenstreaming) caveat enforcers.
Internally, this scope uses the [`nativeTokenStreaming`](../../../reference/delegation/caveats.md#nativetokenstreaming) caveat enforcer, and
optionally uses the [`allowedCalldata`](../../../reference/delegation/caveats.md#allowedcalldata) or [`exactCalldata`](../../../reference/delegation/caveats.md#exactcalldata) caveat enforcers when those parameters are specified.
See the [native token streaming scope reference](../../../reference/delegation/delegation-scopes.md#native-token-streaming-scope) for more details.

```typescript
import { createDelegation } from "@metamask/delegation-toolkit";
Expand All @@ -200,13 +212,17 @@ const delegation = createDelegation({
## Native token transfer scope

This scope ensures that native token transfers are limited to a predefined maximum amount.
This scope is useful for setting simple, fixed transfer limits without any time based or streaming conditions.
This scope is useful for setting simple, fixed transfer limits without any time-based or streaming conditions.
For example, Alice creates a delegation that allows Bob to spend up to 0.1 ETH without any conditions.
Bob may use the 0.1 ETH in a single transaction or make multiple transactions, as long as the total does not exceed 0.1 ETH.

When this scope is applied, the toolkit disallows ERC-20 and ERC-721 token transfers by default, setting the allowed `calldata` to `0x`.
When this scope is applied, the toolkit disallows ERC-20 and ERC-721 token transfers by default (sets `exactCalldata` to `0x`).
You can optionally configure `exactCalldata` to restrict transactions to a specific operation, or configure
`allowedCalldata` to allow transactions that match certain patterns or ranges.

Internally, this scope uses the [`exactCalldata`](../../../reference/delegation/caveats.md#exactcalldata) and [`nativeTokenTransferAmount`](../../../reference/delegation/caveats.md#nativetokentransferamount) caveat enforcers.
Internally, this scope uses the [`nativeTokenTransferAmount`](../../../reference/delegation/caveats.md#nativetokentransferamount) caveat enforcer, and
optionally uses the [`allowedCalldata`](../../../reference/delegation/caveats.md#allowedcalldata) or [`exactCalldata`](../../../reference/delegation/caveats.md#exactcalldata) caveat enforcers when those parameters are specified.
See the [native token transfer scope reference](../../../reference/delegation/delegation-scopes.md#native-token-transfer-scope) for more details.

```typescript
import { createDelegation } from "@metamask/delegation-toolkit";
Expand Down
6 changes: 3 additions & 3 deletions delegation-toolkit/reference/delegation/caveats.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,8 @@ Caveat enforcer contract: [`AllowedCalldataEnforcer.sol`](https://github.com/Met

| Name | Type | Required | Description |
| ------------ | -------- | -------- | -------------------------------------------------------------------------------------------------------------------- |
| `startIndex` | `number` | Yes | The index in the `calldata` byte array (including the 4-byte method selector) where the expected `calldata` starts. |
| `value` | `Hex` | Yes | The expected `calldata` that must match at the specified index. |
| `startIndex` | `number` | Yes | The index in the calldata byte array (including the 4-byte method selector) where the expected calldata starts. |
| `value` | `Hex` | Yes | The expected calldata that must match at the specified index. |

### Example

Expand Down Expand Up @@ -400,7 +400,7 @@ Caveat enforcer contract: [`ExactCalldataEnforcer.sol`](https://github.com/MetaM

| Name | Type | Required | Description |
| ----------------- | -------------------------------- | -------- | ----------------------------------------------------- |
| `calldata` | `Hex` | Yes | The `calldata` that the delegate is allowed to call. |
| `calldata` | `Hex` | Yes | The calldata that the delegate is allowed to call. |

### Example

Expand Down
Loading
Loading