Skip to main content
Sigvex

AA Storage Access Violations

Detects banned opcodes and storage access violations in ERC-4337 validation phase that cause bundler rejection.

AA Storage Access Violations

Overview

Remediation Guide: How to Fix AA Storage Access Violations

The AA storage access detector identifies opcodes and storage access patterns in ERC-4337 validateUserOp and validatePaymasterUserOp functions that violate the ERC-4337 validation rules. Bundlers simulate these functions off-chain before including user operations; violations cause the operation to be rejected from the mempool.

Why This Is an Issue

ERC-4337 restricts the validation phase to prevent denial-of-service attacks against bundlers. Banned opcodes include environment-dependent values that can change between simulation and execution:

  • TIMESTAMP, BLOCKHASH, COINBASE, DIFFICULTY, GASLIMIT, GASPRICE, BASEFEE, BLOBBASEFEE
  • BALANCE, SELFBALANCE (of non-associated addresses)
  • CREATE, CREATE2 (except for account deployment)

Storage access is limited to “associated storage”: the account’s own slots and the account’s deposit slot in the EntryPoint. Accessing any other contract’s storage during validation is forbidden.

How to Resolve

// Before: Uses banned opcodes in validation
function validateUserOp(PackedUserOperation calldata op, bytes32 hash, uint256 funds)
    external returns (uint256)
{
    require(block.timestamp < op.deadline); // BANNED: TIMESTAMP
    require(address(this).balance > 1 ether); // BANNED: SELFBALANCE
    // ...
}

// After: Use validationData time bounds instead of block.timestamp
function validateUserOp(PackedUserOperation calldata op, bytes32 hash, uint256 funds)
    external returns (uint256)
{
    bool sigValid = _checkSig(op, hash);
    // Return validAfter/validUntil in packed format -- no banned opcodes
    return _packValidationData(!sigValid, op.deadline, 0);
}

Examples

Sample Sigvex Output

{
  "detector_id": "aa-storage-access",
  "severity": "high",
  "confidence": 0.92,
  "description": "validateUserOp() uses TIMESTAMP opcode at offset 0x34 and accesses non-associated storage (external contract SLOAD at offset 0x58). Both violations will cause bundler rejection.",
  "location": { "function": "validateUserOp()", "offset": 52 }
}

Detection Methodology

  1. Validation function identification: Locates validateUserOp and validatePaymasterUserOp by selector.
  2. Opcode scan: Scans all reachable basic blocks within the validation function for banned opcodes.
  3. Storage access tracing: Tracks SLOAD/SSTORE targets and classifies them as associated (own slots, EntryPoint deposit) or non-associated.
  4. CREATE/CREATE2 context: Allows CREATE2 in the initCode phase (account deployment) but flags it in validation.

Limitations

  • Storage association rules involving mapping keys with the account address are complex to verify statically.
  • Nested calls from validation (e.g., calling a library) may use banned opcodes that are not directly visible.

References