Overview
EIP-7710 is the on-chain delegation standard that underpins the MetaMask Delegation Framework. It lets a smart account (the delegator) sign a delegation granting a second account (the delegate) the right to execute transactions on its behalf — subject to optional caveats like an ERC-20 spend cap. The common pattern with Dynamic is a user’s embedded wallet acting as delegator and an agent wallet (or another user’s embedded wallet) acting as delegate. Both sides are MetaMask smart accounts. Signer vs smart account: Each smart account is controlled by an underlying signer—a viemAccount whose address appears in walletClient.account. The signer holds the key material (MPC for embedded wallets). The smart account address (delegatorSmartAccount.address, delegateSmartAccount.address) is the on-chain contract that holds assets and appears in delegation from / to fields. Do not confuse the two addresses.
This guide uses the JavaScript SDK throughout.
The delegator account must be deployed on-chain before any delegation can be redeemed. The guide covers deployment via a direct factory call — no bundler required on the delegator side.
Stack
Dynamic’s role
The MetaMask Delegation Framework requires a smart account as the delegator. Normally you’d use a plain private key as the signer for that smart account — Dynamic replaces that key with an embedded wallet backed by MPC. Everything else (smart accounts, delegation signing, on-chain redemption) is standard MetaMask SDK behaviour, documented in the MetaMask Smart Accounts Kit guides.Setup
1
Install dependencies
2
Initialize Dynamic and get the embedded wallet
Call
addWaasEvmExtension() immediately after creating the client to register the embedded wallet provider.publicClient— read-only RPC (bytecode checks, receipts).walletClient— signs and sends transactions as the user’s embedded wallet (walletClient.accountissignerAccountin the next step).
3
Wrap signers as MetaMask smart accounts
toMetaMaskSmartAccount turns a viem signer into a MetaMask Hybrid smart account. Implementation.Hybrid supports an EOA signer (your embedded wallet) controlling a contract wallet.Delegator (user embedded wallet)
signerAccount is the authenticated user’s embedded wallet—the account behind walletClient from the previous step.delegatorSmartAccount.address is the on-chain delegator contract address (not signerAccount.address).Delegate signer (agentSignerAccount)
The delegate redeems the delegation—often a backend agent or a second embedded wallet. It needs its own viem signer, same shape as signerAccount.agentSignerAccount is that delegate signer: agentWalletClient.account from whichever wallet backs your agent. Common sources:- A server wallet you create for the agent (see Agents overview)
- A second embedded wallet authenticated in your app
- Any viem
Account/PrivateKeyAccountyou control
createWalletClientForWalletAccount for embedded wallets, or your server wallet’s viem client:Delegate smart account
WrapagentSignerAccount the same way as the delegator:delegateSmartAccount.address is what you pass to createDelegation as to.4
Deploy the delegator smart account
Counterfactual smart accounts have no bytecode until deployed. The DelegationManager verifies delegations by calling
isValidSignature on the delegator contract, so that contract must exist on-chain before redemption.getFactoryArgs() returns the MetaMask factory to address and data calldata. A single sendTransaction from the user’s walletClient deploys the contract—no bundler on the delegator side.5
Create and sign a delegation
createDelegation builds the unsigned delegation struct. Fields that often need clarification:signDelegation signs the struct as EIP-712 typed data through the delegator’s MPC key. signedDelegation is { ...delegation, signature }—store or pass it to the delegate for redemption. The DelegationManager checks this signature on-chain.For an unrestricted delegation, use
createOpenDelegation instead. The scope field is required on createDelegation. Unrestricted delegations should only be used in trusted contexts such as agent wallets you control.6
Redeem the delegation (delegate side)
The delegate smart account submits an ERC-4337 UserOperation (via a bundler RPC). The UserOp calls
redeemDelegations on the delegate contract; the DelegationManager validates signedDelegation and executes the inner call (for example the ERC-20 transfer) on the delegator’s behalf.EOA delegate (simpler alternative)
EOA delegate (simpler alternative)
If the delegate is a plain EOA rather than a smart account, it sends a regular transaction to the DelegationManager directly — no bundler needed.
delegateWalletClient is a viem WalletClient for that EOA (same pattern as walletClient, but using the delegate’s account as account). The delegate signs and sends the redemption transaction itself.Revoking a delegation
Send a UserOp from the delegator’s smart account to disable the delegation on-chain. Reuse the samebundlerClient and publicClient from the redemption step.
Available scope types
A single
scope sets one caveat. Combine several by passing a caveats array on createDelegation (each entry uses a ScopeType like the table above).
Network support
UsegetSmartAccountsEnvironment(chainId) to retrieve contract addresses for the target network — it throws if the chain is unsupported. Check MetaMask’s supported networks list before going to production.