Skip to main content

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

Steps

1. Install the Smart Accounts Kit

Install the Smart Accounts Kit:

npm install @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