EIP-7702 quickstart
This quickstart demonstrates how to upgrade your EOAExternally owned account (EOA) A private-key-controlled account with no built-in programmable execution logic. to support MetaMask smart accountMetaMask smart account A smart contract account that supports programmable behavior, delegated permissions, flexible signing options, and other advanced features. functionality using an EIP-7702 transaction. This enables your EOA to leverage the benefits of account abstractionAccount abstraction A mechanism that enables users to manage smart contract accounts containing arbitrary verification logic., such as batch transactions, gas sponsorship, and delegationDelegation The ability for a MetaMask smart account to authorize another account to perform specific executions on its behalf..
Prerequisites
- Install Node.js v18 or later.
- Install Yarn, npm, or another package manager.
- Install Viem.
Steps
1. Install the Smart Accounts Kit
Install the Smart Accounts Kit:
- npm
- Yarn
- pnpm
- Bun
npm install @metamask/smart-accounts-kit
yarn add @metamask/smart-accounts-kit
pnpm add @metamask/smart-accounts-kit
bun add @metamask/smart-accounts-kit
2. Set up a Public Client
Set up a Public ClientPublic Client An interface for fetching blockchain state, reading from smart contracts, and monitoring transactions. using Viem's createPublicClient function.
This client will let the EOA query the account state and interact with the blockchain network.
import { createPublicClient, http } from "viem";
import { sepolia as chain } from "viem/chains";
const publicClient = createPublicClient({
chain,
transport: http(),
});
3. Set up a Bundler Client
Set up a Bundler ClientBundler A service that collects user operations from smart accounts, packages them, and submits them to the network. using Viem's createBundlerClient function.
This lets you use the bundler service to estimate gas for user operationsUser operation A signed instruction package that tells a smart account what executions to perform. and submit transactions to the network.
import { createBundlerClient } from "viem/account-abstraction";
const bundlerClient = createBundlerClient({
client: publicClient,
transport: http("https://your-bundler-rpc.com"),
});
4. Set up a Wallet Client
Set up a Wallet ClientWallet Client An interface for interacting with blockchain accounts, executing transactions, and signing messages. using Viem's createWalletClient function.
This lets you sign and submit EIP-7702 authorizations.
import { createWalletClient, http } from "viem";
import { sepolia as chain } from "viem/chains";
import { privateKeyToAccount } from "viem/accounts";
export const account = privateKeyToAccount("0x...");
export const walletClient = createWalletClient({
account,
chain,
transport: http(),
});
5. Authorize a 7702 delegation
Create an authorization to map the contract code to an EOAExternally owned account (EOA) A private-key-controlled account with no built-in programmable execution logic., and sign it
using Viem's signAuthorization action. The signAuthorization action
does not support JSON-RPC accounts.
This example uses EIP7702StatelessDeleGator as the EIP-7702 delegator contract.
It follows a stateless design, as it does not store signer data in the contract's state. This approach
provides a lightweight and secure way to upgrade an EOA to a MetaMask smart accountMetaMask smart account A smart contract account that supports programmable behavior, delegated permissions, flexible signing options, and other advanced features..
import {
Implementation,
toMetaMaskSmartAccount,
getSmartAccountsEnvironment,
} from "@metamask/smart-accounts-kit";
import { privateKeyToAccount } from "viem/accounts";
const environment = getSmartAccountsEnvironment(sepolia.id);
const contractAddress = environment.implementations.EIP7702StatelessDeleGatorImpl;
const authorization = await walletClient.signAuthorization({
account,
contractAddress,
executor: "self",
});
6. Submit the authorization
Once you have signed an authorization, you can send an EIP-7702 transaction to set the EOA code. Since the authorization cannot be sent by itself, you can include it alongside a dummy transaction.
import { zeroAddress } from "viem";
const hash = await walletClient.sendTransaction({
authorizationList: [authorization],
data: "0x",
to: zeroAddress,
});
7. Create a MetaMask smart account
Create a smart accountMetaMask smart account A smart contract account that supports programmable behavior, delegated permissions, flexible signing options, and other advanced features. instance for the EOA and start leveraging the benefits of account abstractionAccount abstraction A mechanism that enables users to manage smart contract accounts containing arbitrary verification logic..
import {
Implementation,
toMetaMaskSmartAccount,
} from "@metamask/smart-accounts-kit";
const addresses = await walletClient.getAddresses();
const address = addresses[0];
const smartAccount = await toMetaMaskSmartAccount({
client: publicClient,
implementation: Implementation.Stateless7702,
address,
signer: { walletClient },
});
8. Send a user operation
Send a user operationUser operation A signed instruction package that tells a smart account what executions to perform. through the upgraded EOA, using Viem's sendUserOperation method.
import { parseEther } from "viem";
// Appropriate fee per gas must be determined for the specific bundler being used.
const maxFeePerGas = 1n;
const maxPriorityFeePerGas = 1n;
const userOperationHash = await bundlerClient.sendUserOperation({
account: smartAccount,
calls: [
{
to: "0x1234567890123456789012345678901234567890",
value: parseEther("1")
}
],
maxFeePerGas,
maxPriorityFeePerGas
});
Next steps
- To grant specific permissions to other accounts from your smart account, create a delegation.
- To quickly bootstrap a MetaMask Smart Accounts project, use the CLI.
- You can also use MetaMask Connect to upgrade a MetaMask account to a smart account.