{
  "tool_id": "art-613-erc4337-userop-math",
  "tool_version": "1.0.0",
  "display_name": "ERC-4337 UserOperation Math",
  "mcp_name": "recompute_erc4337_userop_math",
  "mandate_type": "payment_policy",
  "wave": 99,
  "gpu": false,
  "url": "https://ainumbers.co/chaingraph/art-613-erc4337-userop-math.html",
  "description": "Recomputes the ERC-4337 account-abstraction userOpHash from a caller-supplied UserOperation, computes the EntryPoint's required prefund from caller-supplied gas limits, and reconciles a declared paymaster charge against a charge recomputed from declared inputs. The EntryPoint version is a mandatory declared parameter and is never inferred: v0.6 hashes a 10-word UserOperation pack while v0.7 hashes an 8-word PackedUserOperation in which verificationGasLimit and callGasLimit pack into accountGasLimits and maxPriorityFeePerGas and maxFeePerGas pack into gasFees, so guessing the version would silently produce a wrong hash. The two versions also differ in the prefund formula: v0.6 multiplies verificationGasLimit by three when a paymaster is present, because that same limit also caps postOp, while v0.7 instead adds the paymaster's own verification and postOp gas limits, parsed from the fixed offsets inside paymasterAndData. Both are supported and an unrecognised version is refused rather than approximated. L1 data and blob fees are never derived: after EIP-4844 they depend on the inclusion-time L1 basefee and blob basefee, which are not derivable offline, so an L1 data fee enters reconciliation only when the caller declares it and its absence is reported as a named gap rather than absorbed into a residual. block.basefee is likewise never fetched, so when the two fee caps differ the effective gas price is reported as null with the reason unless a basefee is declared; when the caps are equal the EntryPoint's own legacy shortcut makes the price derivable with no basefee at all. keccak256 comes from the already-vendored, pinned noble-hashes bundle, copied byte-identically from the sibling x402 digest node, and the ABI encoding scheme is implemented directly as public-spec arithmetic on top of it. Zero network calls and zero chain reads: deposits, stakes, nonce-sequence validity and prior spend are never consulted, and every field is caller-declared and echoed back. This node recomputes and reconciles; it makes no claim that any operation was settled, accepted, included, or final, and no claim about signature validity, since the ERC-4337 spec excludes the signature from the hashed struct. Golden vectors are cross-checked against an independent from-spec Keccak-256 and ABI encoder, itself anchored on externally published Keccak-256 constants, not round-trip self-tests alone.",
  "input_schema_ref": "chaingraph/art-613-erc4337-userop-math.html#manifest",
  "consumes": [],
  "feeds": [],
  "status": "live",
  "conformance_fixtures": true,
  "compute_capability": "server",
  "compute_images": [
    {
      "system": "sha256-source",
      "image_id": "sha256:5590e940c1c036d108e0bfb8662b88bdfec6c275cc55843ac2a9f14cd0c78ba9",
      "valid_from": "2026-08-13"
    },
    {
      "system": "risc0",
      "image_id": "sha256:a1a0bc89b5b1febaeda3519f6dbade0fa5ac16beeb143c4e1b01689573567bc6",
      "valid_from": "2026-08-14"
    }
  ],
  "export_capability": [
    "json"
  ],
  "compute_proof_ready": "ready",
  "deferred_reason": "New shard; awaiting the async GPU proving queue (S18 steady-state).",
  "compute_proof": {
    "type": "ZkVmReceipt",
    "system": "risc0",
    "receiptFormat": "groth16-bn254",
    "imageId": "sha256:a1a0bc89b5b1febaeda3519f6dbade0fa5ac16beeb143c4e1b01689573567bc6",
    "seal": "EkUFKQ7Zelu/tv9T4LnWTWO9ogmfRe8tiIoKzjSIY0sihjZAtWEaU9Vc7kCq9cPXkFGZ46+JXt0dLe2OC97nWiFgJus7viYehYp+Tx74mte4kwwm2aSdPqpEm8QazSU+Hqyy+cd5n7vG8isnemK9z3f/WBt9hmjp3RBhLYZT0xMn9aVpShfA15qCYishSafo72Fhaa0HIr+IuKK8M0NdmgSi2cdUV8ib2BJQKlmTqDu3JdHPpt9HFSmq36H9w6wrI/xYsD0aFtEpxrxya6QKOmYRWPpJ2d8/k/rieedxHjEKcmGg8UlI1VqL4nOGO8t+h0D41yOCqD7+YkrgmneWMQ==",
    "journal": {
      "chaingraph_version": "0.4.0",
      "kernel_digest": "sha256:5590e940c1c036d108e0bfb8662b88bdfec6c275cc55843ac2a9f14cd0c78ba9",
      "output": {
        "chain_id": "1",
        "entry_point": {
          "address": "0x5ff137d4b0fdcd49dca30c7cf57e578a026d2789",
          "address_matches_canonical": true,
          "canonical_address_for_declared_version": "0x5ff137d4b0fdcd49dca30c7cf57e578a026d2789",
          "declared_version": "0.6"
        },
        "field_hashes": {
          "call_data_hash": "0x8f54361c53196a7fbccb94b6951e30560cd56ed2372519e43070080b38f6f453",
          "init_code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
          "paymaster_and_data_hash": "0x36d2122e1bfd3419690d0aeaf5131561065b8fe2c4eb07bad7c36e924076362d"
        },
        "gas_accounting": {
          "declared_base_fee_per_gas": null,
          "effective_gas_price_basis": "requires_declared_base_fee -- the fee caps differ, so the price depends on block.basefee, which this kernel never fetches. Supply declaredBaseFeePerGas.",
          "effective_gas_price_wei": null,
          "entry_point_version": "0.6",
          "paymaster_address": "0x1234567890abcdef1234567890abcdef12345678",
          "paymaster_fields_note": null,
          "paymaster_multiplier_applied": "3",
          "paymaster_post_op_gas_limit": null,
          "paymaster_present": true,
          "paymaster_verification_gas_limit": null,
          "prefund_formula": "v0.6: (callGasLimit + verificationGasLimit * paymasterMultiplier + preVerificationGas) * maxFeePerGas",
          "required_gas": "571000",
          "required_prefund_wei": "1142000000000000"
        },
        "never_fetched": [
          "L1 data fee / blob fee: never derived. Post-EIP-4844 it depends on the inclusion-time L1 basefee and blob basefee, neither of which is offline-derivable. Supply declaredL1DataFeeWei to include it in reconciliation.",
          "block.basefee: never fetched. Supply declaredBaseFeePerGas to derive an effective gas price when maxFeePerGas and maxPriorityFeePerGas differ.",
          "EntryPoint contract state: never read. Deposits, stakes, nonce-sequence validity, and prior spend are not consulted.",
          "Chain state of any kind: no RPC, no indexer, no receipt lookup. actualGasUsed and actualGasCost are reconciled only as caller-declared values."
        ],
        "packed_user_op_hash": "0x25d4eeb27d24d9b4899bb7a22ea8dddeca31d86ce7c8e916b63623dedc0329f1",
        "packed_words": {
          "account_gas_limits": null,
          "gas_fees": null,
          "layout": "v0.6 UserOperation -- abi.encode(address sender, uint256 nonce, bytes32 keccak(initCode), bytes32 keccak(callData), uint256 callGasLimit, uint256 verificationGasLimit, uint256 preVerificationGas, uint256 maxFeePerGas, uint256 maxPriorityFeePerGas, bytes32 keccak(paymasterAndData))",
          "word_count": 10
        },
        "paymaster_reconciliation": {
          "declared_actual_gas_cost_wei": null,
          "declared_actual_gas_used": null,
          "declared_l1_data_fee_wei": null,
          "missing_declared_inputs": [
            "declaredActualGasUsed",
            "declaredActualGasCostWei",
            "an effective gas price (supply declaredBaseFeePerGas)"
          ],
          "notes": [
            "Reconciliation was not attempted because the inputs above were not declared. This kernel never substitutes a fetched or assumed value for a missing declared one."
          ],
          "recomputed_execution_cost_wei": null,
          "recomputed_total_charge_wei": null,
          "residual_wei": null,
          "status": "NOT_ATTEMPTED",
          "tolerance_wei": "0"
        },
        "reasons": [],
        "scope_note": "Recomputes the ERC-4337 userOpHash from a caller-supplied UserOperation under a DECLARED EntryPoint version (v0.6 or v0.7), computes the required prefund from caller-supplied gas limits, and reconciles a declared paymaster charge against a charge recomputed from declared inputs. Zero network calls and zero chain reads: every field is caller-declared and echoed back, never independently resolved. L1 data and blob fees are NEVER derived -- post-EIP-4844 they depend on the inclusion-time L1 basefee, which is not offline-derivable, so they participate only when the caller declares them and their absence is reported as a named gap. block.basefee is likewise never fetched: absent a declared value the effective gas price is reported as null with the reason. This node recomputes and reconciles; it makes no claim that any operation was settled, accepted, included, or final, and no claim about signature validity (the signature field is excluded from the hashed struct by the ERC-4337 spec itself).",
        "user_op": {
          "call_data": "0xb61d27f60000000000000000000000005ff137d4b0fdcd49dca30c7cf57e578a026d2789",
          "call_gas_limit": "100000",
          "init_code": "0x",
          "max_fee_per_gas": "2000000000",
          "max_priority_fee_per_gas": "1000000000",
          "nonce": "0",
          "paymaster_and_data": "0x1234567890abcdef1234567890abcdef12345678000000000000000000000000000138800000000000000000000000000000c350deadbeef",
          "pre_verification_gas": "21000",
          "sender": "0x2a1530c4c41db0b0b2bb646cb5eb1a67b7158667",
          "verification_gas_limit": "150000"
        },
        "user_op_hash": "0x45ab83d646f4aaad28e0d2987bcdacd64d6b2ead0b56520d1d1119f2d942671b",
        "verdict": "USEROP_RECOMPUTED"
      }
    }
  }
}
