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

ERC-4337 Error AA50: Paymaster PostOp Reverted Diagnostic

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

ERC-4337 error AA50 "postOp reverted" occurs when a paymaster contract's postOp execution hook reverts after the main user call has completed. Paymasters utilize postOp to perform post-execution accounting, such as debiting ERC-20 tokens (e.g. USDC) from the user's smart account to reimburse gas costs. If the user spent all their tokens during the main call or if token allowance is insufficient, postOp reverts. Ensure sufficient token balance remains.

# Root Cause & Technical Architecture

In ERC-4337, if a paymaster requests post-execution execution by returning context from `validatePaymasterUserOp`, the EntryPoint calls `paymaster.postOp(mode, context, actualGasCost)`. In `mode == opSucceeded`, the paymaster typically executes `IERC20.transferFrom(sender, paymaster, tokenCost)`. If the main execution consumed the user's entire token balance or revoked the approval, `transferFrom` reverts, triggering `revert("AA50 postOp reverted")`.

# 4-Step Actionable Diagnostic Protocol

Step-by-Step Resolution
01

Check User ERC-20 Token Balance After Execution

Simulate the transaction and verify that the sender wallet maintains enough USDC/ERC-20 balance to pay actualGasCost at completion.

02

Verify Paymaster Token Allowance Setting

Ensure the smart account has granted sufficient token allowance to the paymaster contract so transferFrom does not revert during postOp.

03

Audit Paymaster postOp Gas Allocation

In EntryPoint v0.7, paymasterPostOpGasLimit governs the gas available to postOp. Ensure this limit is sufficient for ERC-20 transfer state updates.

04

Handle postOp Revert Fallback in Paymaster Logic

If building a custom paymaster, ensure postOp catches token transfer failures gracefully in mode postOpReverted to avoid blocking the bundler.

# Diagnostic Verification Code / Command

solidity
safe-postop-pattern.sol
// ERC-4337 Paymaster postOp Implementation Guard
function postOp(PostOpMode mode, bytes calldata context, uint256 actualGasCost) external override {
    (address sender, address token, uint256 maxCost) = abi.decode(context, (address, address, uint256));
    
    // Calculate actual token charge based on actualGasCost
    uint256 tokenAmount = (actualGasCost * tokenPrice) / 1e18;
    
    // Prevent AA50: Ensure token transfer succeeds or handles revert cleanly
    bool success = IERC20(token).transferFrom(sender, address(this), tokenAmount);
    require(success, "Token gas reimbursement failed");
}
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 the difference between AA33 and AA50?

AA33 is the v0.6 EntryPoint revert string for postOp failure, whereas AA50 is the modernized error code used in EntryPoint v0.7 specifications.

Why do ERC-20 gas paymasters require a postOp hook?

Actual gas cost is only known after the transaction finishes executing. The postOp hook calculates the exact fee and debits the user accordingly.

Does the user transaction still happen if postOp reverts?

No. If postOp reverts in standard execution, the entire UserOperation (including the user's primary call) is reverted by the EntryPoint.