Skip to main content

Simple 7702 Account

The Simple7702Account is a fully audited minimalist smart contract account that can be safely authorized by any EOA. It adds full support for major smart account features like batching and gas sponsorship.

The following ERCs are supported:

  • ERC-165
  • ERC-721
  • ERC-1155
  • ERC-1271
  • ERC-4337 v0.8

Smart Contracts and Audits

The contracts have been developed by the Ethereum Foundation Account Abstraction Team, and have been audited by Spearbit.

How to use

Prerequisites

Before using Simple7702Account, you must have:

  • Node.js: Version 18.0 or higher.
  • EIP-7702 Compatible Network: Ethereum mainnet, Sepolia, Optimism, Base, or other EIP-7702 enabled chains
  • Private Key acccess: Required for signing authorizations and user operations

Installation

npm install abstractionkit

Usage

import { Simple7702Account } from "abstractionkit"; 

const delegatorPublicAddress = "0xBdbc5FBC9cA8C3F514D073eC3de840Ac84FC6D31"; // eoa public key
const smartAccount = Simple7702Account.initializeNewAccount([delegatorPublicAddress]);

Essential Methods

createUserOperation

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

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

const delegatorPublicAddress = "0xBdbc5FBC9cA8C3F514D073eC3de840Ac84FC6D31";
const smartAccount = Simple7702Account.initializeNewAccount([delegatorPublicAddress]);

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

const userOperation = await smartAccount.createUserOperation(
transactions,
"https://ethereum-sepolia-rpc.publicnode.com", // provider RPC
"https://api.candide.dev/public/v3/sepolia", // bundler RPC
{
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://api.candide.dev/public/v3/sepolia" // bundler URL
);

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

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

Advanced Methods

createAccountCallData

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

example.ts
const callData = Simple7702Account.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 = Simple7702Account.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 = Simple7702Account.createAccountCallDataBatchTransactions(transactions);

prependTokenPaymasterApproveToCallDataStatic

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

example.ts
const callDataWithApproval = Simple7702Account.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
);

estimateUserOperationGas

Estimates gas limits for a UserOperation using the bundler.

example.ts
const [callGasLimit, verificationGasLimit, preVerificationGas] = 
await smartAccount.estimateUserOperationGas(
userOperation,
"https://api.candide.dev/public/v3/sepolia",
{
// Optional overrides
stateOverrideSet: {...},
dummySignature: "0x...",
}
);

Error Handling & Common Issues

Common Errors

// ❌ Missing eip7702Auth on the first UserOperation authorization
const userOperation = await smartAccount.createUserOperation(
transactions,
providerRpc,
bundlerRpc
// Missing eip7702Auth causes delegation failure
);

// ✅ Correct usage
const userOperation = await smartAccount.createUserOperation(
transactions,
providerRpc,
bundlerRpc,
{
eip7702Auth: { chainId: 11155111n }, // Required for EIP-7702
}
);

Error Recovery

async function robustTransactionExecution() {
try {
const response = await smartAccount.sendUserOperation(userOperation, bundlerRpc);
const receipt = await response.included();

if (!receipt.success) {
console.error("Transaction failed:", receipt.logs);
// Handle transaction failure
}

return receipt;
} catch (error) {
if (error.code === -32500) {
// Transaction rejected by entrypoint simulation
console.error("Simulation failed, check transaction data");
} else if (error.code === -32501) {
// Paymaster rejection
console.error("Paymaster rejected transaction");
}
throw error;
}
}