Skip to main content

Simple 7702 Account (EntryPoint v0.9)

The Simple7702AccountV09 is a minimalist smart contract account for EIP-7702, targeting EntryPoint v0.9 (0x433709009B8330FDa32311DF1C2AFA402eD8D009). It shares the same audited contract implementation and API surface as Simple7702Account, with type specialization for UserOperationV9.

EntryPoint v0.9 maintains ABI compatibility with v0.8 while adding:

  • Parallelizable Paymaster Signing: New paymasterSignature field allows passing data to Paymasters after UserOperation signing.
  • Block Number-Based Validity Ranges: validAfter and validUntil can now specify block numbers instead of timestamps.
  • Flexible InitCode Handling: initCode is silently ignored if the Account already exists, enabling two-dimensional nonce usage.
  • UserOp Hash Query: New getCurrentUserOpHash function exposes the current UserOperation hash during execution.

The following ERCs are supported:

  • ERC-165
  • ERC-721
  • ERC-1155
  • ERC-1271
  • ERC-4337 v0.9
Full Example

A complete working example is available on GitHub: upgrade-eoa-ep-v09.ts

Smart Contracts and Audits

The contracts were developed by the Ethereum Foundation Account Abstraction Team and audited by Cantina.

How to Use

Prerequisites

Before using Simple7702AccountV09, you must have:

  • Node.js: Version 18.0 or higher.
  • EIP-7702 Compatible Network: Ethereum mainnet, Sepolia, or other EIP-7702 enabled chains with EP v0.9 support.
  • Private Key Access: Required for signing authorizations and user operations.

Installation

npm install abstractionkit

Usage

import { Simple7702AccountV09 } from "abstractionkit";

const delegatorPublicAddress = "0xBdbc5FBC9cA8C3F514D073eC3de840Ac84FC6D31"; // EOA public key
const smartAccount = new Simple7702AccountV09(delegatorPublicAddress);

Constructor defaults:

  • entrypointAddress: 0x433709009B8330FDa32311DF1C2AFA402eD8D009 (EntryPoint v0.9)
  • delegateeAddress: 0xa46cc63eBF4Bd77888AA327837d20b23A63a56B5

Both can be overridden by passing an overrides object as the second constructor argument.

Essential Methods

createUserOperation

Creates a UserOperation for EIP-7702 accounts that can be sent to bundlers for execution.

example.ts
import { Simple7702AccountV09 } from "abstractionkit";

const delegatorPublicAddress = "0xBdbc5FBC9cA8C3F514D073eC3de840Ac84FC6D31";
const smartAccount = new Simple7702AccountV09(delegatorPublicAddress);

const transactions = [
{
to: "0x...",
value: 0n,
data: "0x...",
},
];

const userOperation = await smartAccount.createUserOperation(
transactions,
"https://ethereum-sepolia-rpc.publicnode.com", // provider RPC
"https://your-ep-v09-bundler-rpc", // bundler RPC (must support EP v0.9)
{
eip7702Auth: {
chainId, // chainId at which the account will be authorized
},
// Optional overrides
maxFeePerGas: 20000000000n,
maxPriorityFeePerGas: 2000000000n,
}
);

signUserOperation

Signs a UserOperation with the provided private key for the EIP-7702 account.

example.ts
const signature = smartAccount.signUserOperation(
userOperation,
"0x...private-key",
11155111n // chain ID
);

userOperation.signature = signature;

sendUserOperation

Sends a signed UserOperation to the bundler for execution on-chain.

example.ts
const response = await smartAccount.sendUserOperation(
userOperation,
"https://your-ep-v09-bundler-rpc" // bundler URL (must support EP v0.9)
);

console.log("UserOperation hash:", response.userOperationHash);

// Wait for the transaction to be included
const receipt = await response.included();
console.log("Transaction receipt:", receipt);

prependTokenPaymasterApproveToCallDataStatic

Prepends a token approval transaction to existing call data for use with token paymasters.

example.ts
const callDataWithApproval = Simple7702AccountV09.prependTokenPaymasterApproveToCallDataStatic(
"0x...", // existing call data
"0xa0b86a33e6b3e96bb24b8e4b28e80e0fb3a4f4b6", // USDC token address
"0x...", // paymaster address
1000000n // approve amount (1 USDC)
);

prependTokenPaymasterApproveToCallData

Instance method to prepend token approval to call data for paymaster usage.

example.ts
const callDataWithApproval = smartAccount.prependTokenPaymasterApproveToCallData(
"0x...", // existing call data
"0xa0b86a33e6b3e96bb24b8e4b28e80e0fb3a4f4b6", // USDC token address
"0x...", // paymaster address
1000000n // approve amount
);

Advanced Methods

createAccountCallData

Creates call data for a basic transaction with specified target, value, and data.

example.ts
const callData = Simple7702AccountV09.createAccountCallData(
"0x...", // to address
1000000000000000000n, // value in wei
"0x..." // transaction data
);

createAccountCallDataSingleTransaction

Creates call data for a single SimpleMetaTransaction.

example.ts
const metaTransaction = {
to: "0x...",
value: 0n,
data: "0x...",
};

const callData = Simple7702AccountV09.createAccountCallDataSingleTransaction(metaTransaction);

createAccountCallDataBatchTransactions

Creates call data for batching multiple SimpleMetaTransactions together.

example.ts
const transactions = [
{ to: "0x...", value: 0n, data: "0x..." },
{ to: "0x...", value: 0n, data: "0x..." },
];

const callData = Simple7702AccountV09.createAccountCallDataBatchTransactions(transactions);

estimateUserOperationGas

Estimates gas limits for a UserOperation using the bundler.

example.ts
const [preVerificationGas, verificationGasLimit, callGasLimit] =
await smartAccount.estimateUserOperationGas(
userOperation,
"https://your-ep-v09-bundler-rpc",
{
// Optional overrides
stateOverrideSet: {...},
dummySignature: "0x...",
}
);

Delegation Methods

isDelegatedToThisAccount

Checks if the EOA is currently delegated to the expected smart account address via EIP-7702. Returns true only when delegated to the account's delegateeAddress.

example.ts
const isDelegated = await smartAccount.isDelegatedToThisAccount(
"https://ethereum-sepolia-rpc.publicnode.com"
);

if (isDelegated) {
console.log("EOA is delegated to this smart account");
} else {
console.log("EOA is not delegated");
}

createRevokeDelegationTransaction

Creates a signed EIP-7702 transaction that revokes the delegation, restoring the EOA to a regular account. The transaction delegates to address(0), removing the smart account code from the EOA.

This is a regular Ethereum transaction (type 0x04), not a UserOperation. The EOA needs native tokens to pay for gas.

note

Revocation cannot be done via a UserOperation because the authorization list is processed before execution, which would remove the account's code mid-transaction.

example.ts
const signedTransaction = await smartAccount.createRevokeDelegationTransaction(
"0x...private-key",
"https://ethereum-sepolia-rpc.publicnode.com",
);

// Send using your preferred method (e.g., viem, ethers)
// const txHash = await client.request({
// method: 'eth_sendRawTransaction',
// params: [signedTransaction],
// });

Error Handling & Common Issues

// Missing eip7702Auth on the first UserOperation authorization
const userOperation = await smartAccount.createUserOperation(
transactions,
providerRpc,
bundlerRpc,
{
eip7702Auth: { chainId: 11155111n }, // Required for EIP-7702
}
);