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
- Param Types
- Return Type
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,
}
);
key | type | description | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
transactions | SimpleMetaTransaction[] | Array of transactions to include in the user operation | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
providerRpc? | string | Optional JSON-RPC provider URL for blockchain queries | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
bundlerRpc? | string | Optional bundler RPC URL for gas estimation | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
overrides? |
| Optional overrides for user operation creation |
SimpleMetaTransaction
key | type | description | ||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
SimpleMetaTransaction |
| SimpleMetaTransaction is the type of transaction used with Simple7702Account. |
key | type | description | |||||||||||||||||||||||||||||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
userOperation |
| The constructed user operation for EIP-7702 |
signUserOperation
Signs a UserOperation with the provided private key for the EIP-7702 account.
- example.ts
- Param Types
- Return Type
const signature = smartAccount.signUserOperation(
userOperation,
"0x...private-key",
11155111n // chain ID
);
userOperation.signature = signature;
key | type | description | |||||||||||||||||||||||||||||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
userOperation |
| The user operation to sign | |||||||||||||||||||||||||||||||||||||||||||||||||||
privateKey | string | Private key to sign the user operation with | |||||||||||||||||||||||||||||||||||||||||||||||||||
chainId | bigint | Chain ID for the target blockchain |
key | type | description |
---|---|---|
signature | string | The signature for the user operation |
sendUserOperation
Sends a signed UserOperation to the bundler for execution on-chain.
- example.ts
- Param Types
- Return Type
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);
key | type | description | |||||||||||||||||||||||||||||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
userOperation |
| The signed user operation to send | |||||||||||||||||||||||||||||||||||||||||||||||||||
bundlerRpc | string | Bundler RPC URL to send the user operation to |
key | type | description | |||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
response |
| Response containing user operation hash and bundler details |
SendUseroperationResponse
key | type | description |
---|---|---|
userOperationHash | string | The hash over the userOp (except signature), entryPoint and chainId |
bundler | Bundler | The Bundler class |
entrypointAddress | string | The entrypoint address where the useroperation got executed |
included() | Promise<UserOperationReceiptResult | BundlerJsonRpcError> | Waits for the user operation to be included onchain and returns the user operation receipt on success, or the bundler error on failture |
BundlerJsonRpcError
key | type | description |
---|---|---|
code | number | Bundler RPC error code |
message | string | Bundler RPC error message description |
UserOperationReceiptResult
key | type | description | |||||||||||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
userOpHash | string | The hash of the user operation. | |||||||||||||||||||||||||||||||||
entryPoint | string | The address of the entry point contract that processed the operation. | |||||||||||||||||||||||||||||||||
sender | string | The address of the sender of the user operation. | |||||||||||||||||||||||||||||||||
nonce | bigint | The nonce of the user operation. | |||||||||||||||||||||||||||||||||
paymaster | string | The address of the paymaster that paid for the gas of the user operation. | |||||||||||||||||||||||||||||||||
actualGasCost | bigint | The actual gas cost incurred for executing the user operation. | |||||||||||||||||||||||||||||||||
actualGasUsed | bigint | The actual amount of gas used for the user operation. | |||||||||||||||||||||||||||||||||
success | boolean | Indicates whether the user operation was successful. | |||||||||||||||||||||||||||||||||
logs | string | The logs produced during the execution of the user operation. | |||||||||||||||||||||||||||||||||
receipt |
| The detailed receipt of the user operation. |
Advanced Methods
createAccountCallData
Creates call data for a basic transaction with specified target, value, and data.
- example.ts
- Param Types
- Return Type
const callData = Simple7702Account.createAccountCallData(
"0x...", // to address
1000000000000000000n, // value in wei
"0x..." // transaction data
);
key | type | description |
---|---|---|
to | string | Target address for the transaction |
value | bigint | Value to transfer in the transaction |
data | string | Call data for the transaction |
key | type | description |
---|---|---|
callData | string | Encoded call data for the account transaction |
createAccountCallDataSingleTransaction
Creates call data for a single SimpleMetaTransaction.
- example.ts
- Param Types
- Return Type
const metaTransaction = {
to: "0x...",
value: 0n,
data: "0x...",
};
const callData = Simple7702Account.createAccountCallDataSingleTransaction(metaTransaction);
key | type | description | ||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
metaTransaction |
| The SimpleMetaTransaction to create call data for |
key | type | description |
---|---|---|
callData | string | Encoded call data for the account transaction |
createAccountCallDataBatchTransactions
Creates call data for batching multiple SimpleMetaTransactions together.
- example.ts
- Param Types
- Return Type
const transactions = [
{ to: "0x...", value: 0n, data: "0x..." },
{ to: "0x...", value: 0n, data: "0x..." },
];
const callData = Simple7702Account.createAccountCallDataBatchTransactions(transactions);
key | type | description |
---|---|---|
transactions | SimpleMetaTransaction[] | Array of SimpleMetaTransactions to batch together |
key | type | description |
---|---|---|
callData | string | Encoded call data for the account transaction |
prependTokenPaymasterApproveToCallDataStatic
Prepends a token approval transaction to existing call data for use with token paymasters.
- example.ts
- Param Types
- Return Type
const callDataWithApproval = Simple7702Account.prependTokenPaymasterApproveToCallDataStatic(
"0x...", // existing call data
"0xa0b86a33e6b3e96bb24b8e4b28e80e0fb3a4f4b6", // USDC token address
"0x...", // paymaster address
1000000n // approve amount (1 USDC)
);
key | type | description |
---|---|---|
callData | string | Existing call data to prepend the approval to |
tokenAddress | string | Address of the ERC-20 token to approve |
paymasterAddress | string | Address of the paymaster contract |
approveAmount | bigint | Amount of tokens to approve for the paymaster |
key | type | description |
---|---|---|
callData | string | Call data with token approval prepended |
prependTokenPaymasterApproveToCallData
Instance method to prepend token approval to call data for paymaster usage.
- example.ts
- Param Types
- Return Type
const callDataWithApproval = smartAccount.prependTokenPaymasterApproveToCallData(
"0x...", // existing call data
"0xa0b86a33e6b3e96bb24b8e4b28e80e0fb3a4f4b6", // USDC token address
"0x...", // paymaster address
1000000n // approve amount
);
key | type | description |
---|---|---|
callData | string | Existing call data to prepend the approval to |
tokenAddress | string | Address of the ERC-20 token to approve |
paymasterAddress | string | Address of the paymaster contract |
approveAmount | bigint | Amount of tokens to approve for the paymaster |
key | type | description |
---|---|---|
callData | string | Call data with token approval prepended |
estimateUserOperationGas
Estimates gas limits for a UserOperation using the bundler.
- example.ts
- Param Types
- Return Type
const [callGasLimit, verificationGasLimit, preVerificationGas] =
await smartAccount.estimateUserOperationGas(
userOperation,
"https://api.candide.dev/public/v3/sepolia",
{
// Optional overrides
stateOverrideSet: {...},
dummySignature: "0x...",
}
);
key | type | description | |||||||||||||||||||||||||||||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
userOperation |
| The user operation to estimate gas for | |||||||||||||||||||||||||||||||||||||||||||||||||||
bundlerRpc | string | Bundler RPC URL for gas estimation | |||||||||||||||||||||||||||||||||||||||||||||||||||
overrides? |
| Optional overrides for gas estimation |
key | type | description |
---|---|---|
gasLimits | [bigint, bigint, bigint] | Tuple of [callGasLimit, verificationGasLimit, preVerificationGas] |
Error Handling & Common Issues
Common Errors
- Authorization Errors
- Gas Estimation Issues
- Network Mismatches
// ❌ 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
}
);
// ❌ Insufficient gas prices
const userOperation = await smartAccount.createUserOperation(
transactions,
providerRpc,
bundlerRpc,
{
eip7702Auth: { chainId: 11155111n },
maxFeePerGas: 1000000000n, // Too low for current network conditions
maxPriorityFeePerGas: 100000000n, // Too low for current network conditions
}
);
// ✅ add multipliers to the node
const userOperation = await smartAccount.createUserOperation(
transactions,
providerRpc,
bundlerRpc,
{
eip7702Auth: { chainId: 11155111n },
// Use higher gas prices
maxFeePerGasMultiplier: 120, // 20% higher than current network conditions
maxPriorityFeePerGasMultiplier: 150, // 50% higher than current network conditions
}
);
// ❌ ChainId mismatch
const userOperation = await smartAccount.createUserOperation(
transactions,
"https://ethereum-sepolia-rpc.publicnode.com", // Sepolia RPC
"https://api.candide.dev/public/v3/11155111", // Sepolia bundler
{
eip7702Auth: { chainId: 1n }, // Mainnet chainId
}
);
// ✅ Matching network configuration
const userOperation = await smartAccount.createUserOperation(
transactions,
"https://ethereum-sepolia-rpc.publicnode.com", // Sepolia RPC
"https://api.candide.dev/public/v3/11155111", // Sepolia bundler
{
eip7702Auth: { chainId: 11155111n }, // Sepolia chainId
}
);
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;
}
}