Skills smart-accounts-kit
Web3 development using MetaMask Smart Accounts Kit. Use when the user wants to build dApps with ERC-4337 smart accounts, send user operations, batch transactions, configure signers (EOA, passkey, multisig), implement gas abstraction with paymasters, create delegations, or request advanced permissions (ERC-7715). Supports Viem integration, multiple signer types (Dynamic, Web3Auth, Wagmi), gasless transactions, and the Delegation Framework.
git clone https://github.com/openclaw/skills
T=$(mktemp -d) && git clone --depth=1 https://github.com/openclaw/skills "$T" && mkdir -p ~/.claude/skills && cp -r "$T/skills/ayushbherwani1998/metamask-smart-accounts-kit" ~/.claude/skills/clawdbot-skills-smart-accounts-kit && rm -rf "$T"
skills/ayushbherwani1998/metamask-smart-accounts-kit/SKILL.mdQuick Reference
This skill file provides quick access to the MetaMask Smart Accounts Kit v0.3.0. For detailed information, refer to the specific reference files.
📚 Detailed References:
- Smart Accounts Reference - Account creation, implementations, signers
- Delegations Reference - Delegation lifecycle, scopes, caveats
- Advanced Permissions Reference - ERC-7715 permissions via MetaMask
Package Installation
npm install @metamask/smart-accounts-kit@0.3.0
For custom caveat enforcers:
forge install metamask/delegation-framework@v1.3.0
Core Concepts Summary
1. Smart Accounts (ERC-4337)
Three implementation types:
- Hybrid (
) - EOA + passkey signersImplementation.Hybrid - Multisig (
) - Multiple signers with thresholdImplementation.MultiSig - Stateless7702 (
) - EIP-7702 upgraded EOAImplementation.Stateless7702
2. Delegation Framework (ERC-7710)
Grant permissions from delegator to delegate:
- Scopes - Initial authority (spending limits, function calls)
- Caveats - Restrictions enforced by smart contracts
- Types - Root, open root, redelegation, open redelegation
- Lifecycle - Create → Sign → Store → Redeem
3. Advanced Permissions (ERC-7715)
Request permissions via MetaMask extension:
- Human-readable UI confirmations
- ERC-20 and native token permissions
- Requires MetaMask Flask 13.5.0+
- User must have smart account
Quick Code Examples
Create Smart Account
import { Implementation, toMetaMaskSmartAccount } from '@metamask/smart-accounts-kit' import { privateKeyToAccount } from 'viem/accounts' const account = privateKeyToAccount('0x...') const smartAccount = await toMetaMaskSmartAccount({ client: publicClient, implementation: Implementation.Hybrid, deployParams: [account.address, [], [], []], deploySalt: '0x', signer: { account }, })
Create Delegation
import { createDelegation } from '@metamask/smart-accounts-kit' import { parseUnits } from 'viem' const delegation = createDelegation({ to: delegateAddress, from: delegatorSmartAccount.address, environment: delegatorSmartAccount.environment, scope: { type: 'erc20TransferAmount', tokenAddress: '0x1c7D4B196Cb0C7B01d743Fbc6116a902379C7238', maxAmount: parseUnits('10', 6), }, caveats: [ { type: 'timestamp', afterThreshold: now, beforeThreshold: expiry }, { type: 'limitedCalls', limit: 5 }, ], })
Sign Delegation
const signature = await smartAccount.signDelegation({ delegation }) const signedDelegation = { ...delegation, signature }
Redeem Delegation
import { createExecution, ExecutionMode } from '@metamask/smart-accounts-kit' import { DelegationManager } from '@metamask/smart-accounts-kit/contracts' import { encodeFunctionData, erc20Abi } from 'viem' const callData = encodeFunctionData({ abi: erc20Abi, args: [recipient, parseUnits('1', 6)], functionName: 'transfer', }) const execution = createExecution({ target: tokenAddress, callData }) const redeemCalldata = DelegationManager.encode.redeemDelegations({ delegations: [[signedDelegation]], modes: [ExecutionMode.SingleDefault], executions: [[execution]], }) // Via smart account const userOpHash = await bundlerClient.sendUserOperation({ account: delegateSmartAccount, calls: [{ to: delegateSmartAccount.address, data: redeemCalldata }], }) // Via EOA const txHash = await delegateWalletClient.sendTransaction({ to: environment.DelegationManager, data: redeemCalldata, })
Request Advanced Permissions
import { erc7715ProviderActions } from '@metamask/smart-accounts-kit/actions' const walletClient = createWalletClient({ transport: custom(window.ethereum), }).extend(erc7715ProviderActions()) const grantedPermissions = await walletClient.requestExecutionPermissions([ { chainId: chain.id, expiry: now + 604800, signer: { type: 'account', data: { address: sessionAccount.address }, }, permission: { type: 'erc20-token-periodic', data: { tokenAddress, periodAmount: parseUnits('10', 6), periodDuration: 86400, justification: 'Transfer 10 USDC daily', }, }, isAdjustmentAllowed: true, }, ])
Redeem Advanced Permissions
// Smart account import { erc7710BundlerActions } from '@metamask/smart-accounts-kit/actions' const bundlerClient = createBundlerClient({ client: publicClient, transport: http(bundlerUrl), }).extend(erc7710BundlerActions()) const permissionsContext = grantedPermissions[0].context const delegationManager = grantedPermissions[0].signerMeta.delegationManager const userOpHash = await bundlerClient.sendUserOperationWithDelegation({ publicClient, account: sessionAccount, calls: [ { to: tokenAddress, data: calldata, permissionsContext, delegationManager, }, ], }) // EOA import { erc7710WalletActions } from '@metamask/smart-accounts-kit/actions' const walletClient = createWalletClient({ account: sessionAccount, chain, transport: http(), }).extend(erc7710WalletActions()) const txHash = await walletClient.sendTransactionWithDelegation({ to: tokenAddress, data: calldata, permissionsContext, delegationManager, })
Key API Methods
Smart Accounts
- Create smart accounttoMetaMaskSmartAccount()
- Combine multisig signaturesaggregateSignature()
- Sign delegationsignDelegation()
- Sign user operationsignUserOperation()
/signMessage()
- Standard signingsignTypedData()
Delegations
- Create delegation with delegatecreateDelegation()
- Create open delegationcreateOpenDelegation()
- Build caveats arraycreateCaveatBuilder()
- Create execution structcreateExecution()
- Encode redemption calldataredeemDelegations()
- Sign with private keysignDelegation()
- Resolve environmentgetSmartAccountsEnvironment()
- Deploy contractsdeploySmartAccountsEnvironment()
- Override environmentoverrideDeployedEnvironment()
Advanced Permissions
- Wallet client extension for requestingerc7715ProviderActions()
- Request permissionsrequestExecutionPermissions()
- Bundler client extensionerc7710BundlerActions()
- Redeem with smart accountsendUserOperationWithDelegation()
- Wallet client extensionerc7710WalletActions()
- Redeem with EOAsendTransactionWithDelegation()
Supported ERC-7715 Permission Types
ERC-20 Token Permissions
| Permission Type | Description |
|---|---|
| Per-period limit that resets at each period |
| Linear streaming with amountPerSecond rate |
Native Token Permissions
| Permission Type | Description |
|---|---|
| Per-period ETH limit that resets |
| Linear ETH streaming with amountPerSecond rate |
Common Delegation Scopes
Spending Limits
| Scope | Description |
|---|---|
| Fixed ERC-20 limit |
| Per-period ERC-20 limit |
| Linear streaming ERC-20 |
| Fixed native token limit |
| Per-period native token limit |
| Linear streaming native |
| ERC-721 (NFT) transfer |
Function Calls
| Scope | Description |
|---|---|
| Specific methods/addresses allowed |
| Ownership transfers only |
Common Caveat Enforcers
Target & Method
- Limit callable addressesallowedTargets
- Limit callable methodsallowedMethods
- Validate specific calldataallowedCalldata
/exactCalldata
- Exact calldata matchexactCalldataBatch
/exactExecution
- Exact execution matchexactExecutionBatch
Value & Token
- Limit native token valuevalueLte
- Limit ERC-20 amounterc20TransferAmount
- Validate ERC-20 balance changeerc20BalanceChange
/erc721Transfer
- ERC-721 restrictionserc721BalanceChange
- ERC-1155 validationerc1155BalanceChange
Time & Frequency
- Valid time range (seconds)timestamp
- Valid block rangeblockNumber
- Limit redemption countlimitedCalls
/erc20PeriodTransfer
- Time-based ERC-20erc20Streaming
/nativeTokenPeriodTransfer
- Time-based nativenativeTokenStreaming
Security & State
- Limit redemption to specific addressesredeemer
- One-time delegation with IDid
- Bulk revocation via noncenonce
- Auto-deploy contractdeployed
- Ownership transfer onlyownershipTransfer
- Require paymentnativeTokenPayment
- Validate native balancenativeBalanceChange
- Multi-token period limitsmultiTokenPeriod
Execution Modes
| Mode | Chains | Processing | On Failure |
|---|---|---|---|
| One | Sequential | Revert |
| One | Sequential | Continue |
| Multiple | Interleaved | Revert |
| Multiple | Interleaved | Continue |
Contract Addresses (v1.3.0)
Core
| Contract | Address |
|---|---|
| EntryPoint | |
| SimpleFactory | |
| DelegationManager | |
| MultiSigDeleGatorImpl | |
| HybridDeleGatorImpl | |
Critical Rules
Always Required
- Always use caveats - Never create unrestricted delegations
- Deploy delegator first - Account must be deployed before redeeming
- Check smart account status - ERC-7715 requires user has smart account
Behavior
- Caveats are cumulative - In delegation chains, restrictions stack
- Function call default - v0.3.0 defaults to NO native token (use
)valueLte - Batch mode caveat - No compatible caveat enforcers available
Requirements
- ERC-7715 requirements - MetaMask Flask 13.5.0+, smart account
- Multisig threshold - Need at least threshold signers
- 7702 upgrade - Stateless7702 requires EIP-7702 upgrade first
Common Patterns
Pattern 1: ERC-20 with Time Limit
const delegation = createDelegation({ to: delegate, from: delegator, environment, scope: { type: 'erc20TransferAmount', tokenAddress, maxAmount: parseUnits('100', 6), }, caveats: [ { type: 'timestamp', afterThreshold: now, beforeThreshold: expiry }, { type: 'limitedCalls', limit: 10 }, { type: 'redeemer', redeemers: [delegate] }, ], })
Pattern 2: Function Call with Value
const delegation = createDelegation({ to: delegate, from: delegator, environment, scope: { type: 'functionCall', targets: [contractAddress], selectors: ['transfer(address,uint256)'], valueLte: { maxValue: parseEther('0.1') }, }, caveats: [{ type: 'allowedMethods', selectors: ['transfer(address,uint256)'] }], })
Pattern 3: Periodic Native Token
const delegation = createDelegation({ to: delegate, from: delegator, environment, scope: { type: 'nativeTokenPeriodTransfer', periodAmount: parseEther('0.01'), periodDuration: 86400, startDate: now, }, })
Pattern 4: Redelegation Chain
// Alice → Bob (100 USDC) const aliceToBob = createDelegation({ to: bob, from: alice, environment, scope: { type: 'erc20TransferAmount', tokenAddress, maxAmount: parseUnits('100', 6) }, }) // Bob → Carol (50 USDC, subset of authority) const bobToCarol = createDelegation({ to: carol, from: bob, environment, scope: { type: 'erc20TransferAmount', tokenAddress, maxAmount: parseUnits('50', 6) }, parentDelegation: aliceToBob, caveats: [{ type: 'timestamp', afterThreshold: now, beforeThreshold: expiry }], })
Troubleshooting Quick Fixes
| Issue | Solution |
|---|---|
| Account not deployed | Use to deploy |
| Invalid signature | Verify chain ID, delegation manager, signer permissions |
| Caveat enforcer reverted | Check caveat parameters match execution, verify order |
| Redemption failed | Check delegator balance, calldata validity, target contracts |
| ERC-7715 not working | Upgrade to Flask 13.5.0+, ensure user has smart account |
| Permission denied | Handle gracefully, provide manual fallback |
| Threshold not met | Add more signers for multisig |
| 7702 not working | Confirm EOA upgraded via EIP-7702 first |
Resources
- NPM:
@metamask/smart-accounts-kit - Contracts:
metamask/delegation-framework@v1.3.0 - ERC Standards: ERC-4337, ERC-7710, ERC-7715, ERC-7579
- MetaMask Flask: https://metamask.io/flask
Version Info
- Toolkit: 0.3.0
- Delegation Framework: 1.3.0
- Breaking Change: Function call scope defaults to no native token transfer
For detailed documentation, see the reference files in the
directory./references