LayerZeroFault
ERC-4337 & Safe CODE: AA25 Reviewed & Verified:

ERC-4337 Error AA25: Invalid Account Nonce 2D Sequence Fix

Verified by Victor Vance • Lead Technical Analyst & Systems Researcher
Quick Diagnostic Answer (Executive Summary) GSC Snippet Verified

ERC-4337 error AA25 "invalid account nonce" occurs when the nonce submitted in a UserOperation does not match the sequential nonce recorded by the EntryPoint contract for that account key. Unlike standard EVM transactions, ERC-4337 utilizes 2D nonces: an upper 192-bit key allows parallel execution channels, while the lower 64 bits must increment sequentially. Query EntryPoint.getNonce(sender, key) to fetch the accurate nonce before submitting, and clear any conflicting mempool transactions.

# Root Cause & Technical Architecture

The ERC-4337 EntryPoint manages nonces as a mapping `mapping(address => mapping(uint192 => uint64)) nonceSequenceNumber`. When a UserOp arrives, EntryPoint extracts `key = nonce >> 64` and `seq = uint64(nonce)`. If `seq` does not match the current stored sequence number for that `(sender, key)` pair, EntryPoint reverts with `AA25 invalid account nonce`. This commonly occurs when client applications broadcast multiple parallel userOps on key 0 without waiting for receipt.

# 4-Step Actionable Diagnostic Protocol

Step-by-Step Resolution
01

Fetch Current 2D Nonce from EntryPoint Contract

Call entryPoint.getNonce(senderAddress, key) via eth_call directly against the RPC to fetch the accurate sequential counter.

02

Leverage 2D Nonce Keys for Parallel Transactions

To send concurrent UserOperations without waiting for confirmation, allocate distinct 192-bit keys (e.g. key 1 for session keys, key 0 for main).

03

Clear Stale Bundler Mempool Queues

If a prior UserOp with the same nonce is pending or underpriced in the bundler mempool, replace it by bumping maxPriorityFeePerGas.

04

Audit Multi-Tab Session Synchronization

If the user has multiple dApp tabs open, synchronize nonce increments across browser tabs using BroadcastChannel or shared state stores.

# Diagnostic Verification Code / Command

typescript
fetch-2d-nonce.ts
// Fetch 2D Nonce from EntryPoint v0.7 Contract
import { createPublicClient, http, parseAbi } from 'viem';

const entryPointAbi = parseAbi([
  'function getNonce(address sender, uint192 key) view returns (uint256 nonce)'
]);

async function getAccountNonce(client: any, entryPoint: `0x${string}`, sender: `0x${string}`, key: bigint = 0n) {
  const nonce = await client.readContract({
    address: entryPoint,
    abi: entryPointAbi,
    functionName: 'getNonce',
    args: [sender, key]
  });
  // Upper 192 bits: Key | Lower 64 bits: Sequential counter
  return nonce;
}
Zero-Secrets Client Sandbox

Launch ERC-4337 UserOp Decoder

Execute client-side cryptographic simulation and parameter checks safely in your browser via native WebCrypto without sending private keys or mnemonics over the wire.

Open Sandbox →
Comprehensive In-Depth Guide

Read Full Investigation & Recovery Workflow

Explore complete architectural diagrams, edge-case failure trees, and detailed post-mortem analysis in our verified deep guide.

Read Guide →

# Related Diagnostic Codes in ERC-4337 & Safe

Related Hex Statuses

# Frequently Asked Questions

FAQ Schema

What is a 2D nonce in ERC-4337?

A 2D nonce is a uint256 where the first 192 bits represent a key (independent lane) and the last 64 bits represent a strict sequential counter for that lane.

Can I send parallel transactions with ERC-4337?

Yes! By using different 192-bit keys, you can execute transactions in parallel without sequential blocking, unlike traditional Ethereum accounts.

Why did my transaction get AA25 if I only clicked once?

A retry mechanism in your dApp or bundler may have submitted the same operation twice, with the second attempt colliding with the newly incremented on-chain nonce.