Skip to main content

Redeem a delegation

To redeem a delegation, a delegate must submit a user operation that calls the redeemDelegation function on the MetaMaskSmartAccount instance. Multiple delegations may be redeemed within a single user operation.

Prerequisites

Redeem a delegation

Assuming the existence of a bundler client, a MetaMaskSmartAccount instance, and a signed delegation granted to this smart contract account, the following example shows how to submit a user operation redeeming the delegation.

import { DelegationFramework } from '@codefi/delegator-core-viem';

//...

// The delegations array is a chain of delegations. If the delegation is a root, then it will be only one.
// Otherwise it must be all of the delegations in the chain, in order from leaf to root. This is the order
// returned from the delegation service.
const delegations: DelegationStruct[] = [ delegation ];

// SINGLE_DEFAULT is the default execution mode. See below for an explanation of the different execution modes available.
const mode: ExecutionMode = SINGLE_DEFAULT;

// For SINGLE execution modes, the executions array must be length 1.
const executions: ExecutionStruct[] = [{
target, // the address being called as a hex string
value, // the value of the call as a bigint
callData // the calldata as a hex string
}];

const redeemDelegationCalldata = DelegationFramework.encode.redeemDelegations(
[ delegations ],
[ mode ],
[ executions ]
);

const userOperationHash = await bundler.sendUserOperation({
account: delegatorSmartAccount,
calls: [
{
to: delegatorSmartAccount.address,
data: redeemDelegationCalldata
}
],
maxFeePerGas,
maxPriortyFeePerGas
});

Redeem multiple delegations

Multiple delegations may be redeemed in a single user operation, each independent of the others.

Each element in the delegationsArray, must have a corresponding element in the executionsArray and modes.

import { DelegationFramework } from '@codefi/delegator-core-viem';

//...

const delegationsArray: DelegationStruct[][] = [
[ delegation1 ]
[ delegation2 ]
[ delegation3 ]
];

const modes: ExecutionMode = [
SINGLE_DEFAULT,
SINGLE_DEFAULT,
SINGLE_DEFAULT
];

const executionsArray: ExecutionStruct = [
[ execution1 ],
[ execution2 ],
[ execution3 ]
];

const redeemDelegationsCalldata = DelegationFramework.encode.redeemDelegations(
delegationsArray,
modes,
executionsArray
);

const userOperationHash = await bundler.sendUserOperation({
account: delegatorSmartAccount,
calls: [
{
to: delegatorSmartAccount.address,
data: redeemDelegationsCalldata
}
],
maxFeePerGas,
maxPriortyFeePerGas
});

Execution modes

The Delegation Toolkit supports a number of execution modes, which are based on ERC-7579. See the ERC implementation which describes execution modes in detail

The supported execution modes are SINGLE_DEFAULT_MODE, SINGLE_TRY_MODE, BATCH_DEFAULT_MODE, and BATCH_TRY_MODE.

SINGLE execution modes

In SINGLE execution modes, only a single delegation chain and a single execution may 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

In BATCH execution modes, multiple delegation chains and multiple executions may be provided. This mode executes delegations interleaved:

  1. For each chain in the batch, and each delegation in the chain, all caveats' before hooks are called`
  2. Each redeemed actions 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

In DEFAULT modes, if a revert occurs during redemption, the entire user operation will revert at that point.

TRY modes

In TRY modes, if a revert occurs during redemption of the delegation, execution of the user operation will continue.