Skip to main content

EIP-7702 quickstart

This quickstart demonstrates how to upgrade your externally owned account (EOA) to support MetaMask Smart Accounts functionality using an EIP-7702 transaction. This enables your EOA to leverage the benefits of account abstraction, such as batch transactions, gas sponsorship, and delegation capabilities.

Prerequisites

Steps

1. Install the toolkit

Install the MetaMask Delegation Toolkit:

npm install @metamask/delegation-toolkit

2. Set up a Public Client

Set up a Viem Public Client using Viem's createPublicClient function. This client will let the EOA query the account state and interact with 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 Viem Bundler Client using Viem's createBundlerClient function. This lets you use the bundler service to estimate gas for user operations 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 Viem Wallet Client using Viem's createWalletClient function. This lets you sign and submit EIP-7702 authorization.

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 EOA, 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 smart account.

import {
Implementation,
toMetaMaskSmartAccount,
getDeleGatorEnvironment,
} from "@metamask/delegation-toolkit";
import { privateKeyToAccount } from "viem/accounts";

const environment = getDeleGatorEnvironment(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 account instance for the EOA and start leveraging the benefits of account abstraction.

import { 
Implementation,
toMetaMaskSmartAccount,
} from "@metamask/delegation-toolkit";

const addresses = await walletClient.getAddresses();
const address = addresses[0];

const smartAccount = await toMetaMaskSmartAccount({
client: publicClient,
implementation: Implementation.Stateless7702,
address,
signatory: { walletClient },
});

8. Send a user operation

Send a user operation 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