Skip to main content

Sponsored UserOperations

Every on-chain action a Sumvin user takes — deploying a Safe, sending a token, executing a Purchase Intent — happens as an ERC-4337 UserOperation, not as a regular Ethereum transaction. Sumvin acts as the paymaster: we sign for gas and forward the operation to a bundler so users never need to hold native gas tokens. This page explains the moving parts and, importantly, the status vocabulary you will see when polling GET /v0/safe/rpc/{user_op_hash}/status.

What is an ERC-4337 UserOperation?

ERC-4337 is the account-abstraction standard. Instead of submitting a signed transaction directly to a node, an account-abstracted application submits a UserOperation — a signed payload describing what the user’s smart account should do — to a bundler. The bundler aggregates UserOperations from many users into a single bundle transaction and sends it to the on-chain EntryPoint contract, which validates each signature and dispatches each call. Two consequences matter for integrators:
  • The user’s smart account (a Safe, in Sumvin’s case) is the sender. The user’s signing key signs the UserOperation; no externally owned account ever needs to hold a balance.
  • A paymaster can volunteer to cover gas. Sumvin runs the paymaster — partners do not need to fund a relayer wallet.

Why Sumvin sponsors gas

Partner integrations want a frictionless first session. Asking a user to acquire native ETH on Optimism, or SEI on Sei mainnet, before they can do anything is a non-starter for partner experiences. Sumvin sponsors all UserOperations originated through the Platform API. The user signs, Sumvin pays, the bundler delivers.

Status vocabulary

A UserOperation passes through a small state machine. The status field on the polling endpoint takes one of seven values:
StatusMeaning
not_foundThe bundler has not seen this UserOperation hash. Either the hash is wrong, or the operation has not yet propagated.
not_submittedSumvin accepted and persisted the operation but has not yet pushed it to the bundler. Transient.
queuedThe bundler accepted the UserOperation and queued it for the next bundle.
submittedThe bundler has broadcast a bundle transaction containing this UserOperation to the network mempool.
includedThe bundle landed in a block and this UserOperation succeeded on-chain. Terminal.
rejectedThe bundler refused the UserOperation pre-submission (e.g., signature invalid, paymaster denied, simulation reverted). No transaction hash. Terminal.
failedThe bundle landed in a block but this UserOperation reverted on-chain. Has a transaction hash. Terminal.
included and failed are the only on-chain terminal states. rejected is a pre-submission terminal state.

rejected vs failed — failure-mode taxonomy

The most common confusion: the difference between rejected and failed.
rejected means the UserOperation never reached the chain. No bundle was broadcast. There is no transaction hash, no block number, no gas was burned. Typical causes: invalid signature, malformed callData that fails simulation, paymaster declined sponsorship.failed means the UserOperation reached the chain but reverted. A bundle transaction was mined and gas was paid. The transaction hash is populated and a receipt link is included in the response. Typical causes: a sub-call inside the operation reverted, an insufficient-balance check failed at execution time, a downstream contract enforced a constraint.
When you handle errors in your UI, treat the two cases differently:
  • For rejected: show the user that the request was not submitted and prompt them to retry or amend the signed payload.
  • For failed: show the on-chain failure with a link to the receipt, since gas was already burned and the user may have observable side effects from any sub-calls that succeeded before the revert.

Lifecycle flow

client                  Sumvin Platform API                bundler / chain
  │                              │                              │
  │  GET /v0/safe/config         │                              │
  │  ──────────────────────────▶ │                              │
  │  ◀── factory, factoryData ── │                              │
  │       predicted address      │                              │
  │                              │                              │
  │  sign UserOperation          │                              │
  │  (off-chain, client-side)    │                              │
  │                              │                              │
  │  POST /v0/safe/rpc           │                              │
  │  ──────────────────────────▶ │  paymaster sign + forward    │
  │                              │  ──────────────────────────▶ │
  │  ◀── 202 Accepted ─────────  │                              │
  │      user_op_hash            │                              │
  │                              │                              │
  │  GET /v0/safe/rpc/{hash}/    │                              │
  │      status                  │                              │
  │  ──────────────────────────▶ │  poll bundler for receipt    │
  │                              │  ──────────────────────────▶ │
  │  ◀── status: queued ──────── │  ◀── pending ──────────────  │
  │                              │                              │
  │  GET ... (poll again)        │                              │
  │  ──────────────────────────▶ │  ──────────────────────────▶ │
  │  ◀── status: included ────── │  ◀── receipt: success ─────  │
  │      txn_hash, block_number  │                              │
  │      _links.receipt          │                              │
  │                              │                              │
  │  GET _links.receipt.href     │                              │
  │  ──────────────────────────▶ │                              │
  │  ◀── full transaction ─────  │                              │
When the terminal status is included or failed, the response carries txn_hash and a _links.receipt href pointing at /v0/transactions/receipts/{txn_hash} so you can fetch the full on-chain transaction details. For rejected, neither field is present.

See also