Sponsored execution

For product and blockchain engineers.

In short

Your customers should not have to buy ether before they can use your product. With sponsored execution they act from accounts they own, with keys you never hold, and your company pays the gas. CryptoRail decides what you pay for under a policy you write, signs the sponsorship with a key that can live in your HSM, follows each operation to confirmation and records what it cost, per customer and per policy.

It works in two ways. A customer with their own wallet asks CryptoRail for sponsorship through the standard interface wallets already speak. Or your own application has CryptoRail build the operation and asks the customer only for a signature. Both use the same policy, the same paymaster and the same records.

Your end customers act without holding gas: CryptoRail sponsors their operations through ERC-4337 paymasters, and their keys stay in their own accounts.

The standards involved

CryptoRail implements the interface it exposes and relies on audited contracts for the rest; it writes no contract of its own for sponsorship.

StandardWhat it isIts role here
ERC-4337UserOperations, bundlers, the EntryPoint contract, paymastersThe execution model: the paymaster’s deposit in the EntryPoint pays the gas
ERC-7677The HTTP interface a wallet calls on a paymaster serviceWhat CryptoRail exposes to wallets
EIP-5792Lets an application ask a wallet to send calls with capabilitiesHow your application tells the wallet to use CryptoRail as its paymaster service
EIP-7702Lets an existing address delegate to smart-account codeHow a customer’s current address becomes a smart account, same address and same key

The paymaster is a verifying paymaster: the contract pays for an operation only if it carries a signature by the key the paymaster names, over the operation and a validity window. The chain checks that signature and that the deposit covers the cost; everything about what you are willing to pay for is decided by CryptoRail’s policy before it signs.

Paymaster data is signed by an ordinary signing identity, whose key can live in your HSM, and is valid only until a short deadline.

Wallet-driven: the customer’s wallet asks

Any wallet that implements EIP-5792 with the ERC-7677 paymaster capability works, without CryptoRail knowing how that wallet’s account is built. Your application gives the wallet the URL of your paymaster service; the wallet builds the operation, asks for sponsorship twice (once to estimate, once with the final gas), signs it and submits it to its bundler. CryptoRail decides, signs the paymaster data, then follows the operation through the bundler to confirmation.

sequenceDiagram
    participant A as Your application
    participant W as Customer's wallet
    participant CR as CryptoRail ERC-7677 endpoint
    participant B as Bundler
    A->>W: send these calls, paymaster service = your URL
    W->>CR: stub data, with the estimated cost
    CR->>CR: quotas, then policy: allow or refuse with a reason
    CR-->>W: stub data
    W->>B: estimate gas
    W->>CR: final data, with the final gas
    CR->>CR: policy again, paymaster data signed, valid until a deadline
    CR-->>W: paymaster data
    W->>W: customer signs
    W->>B: submit
    CR->>B: follow to inclusion and finality, record the cost

A wallet is given a URL and nothing else, so the credential travels in it: a key whose only role is to call this endpoint. Because the endpoint is public by nature, every request is made cheap to refuse before any policy runs: the key and its role, then quotas per sender and per tenant, then a cut-off for a sender collecting refusals. A refusal is a standard JSON-RPC error carrying the reason code and the policy version, and the refusal is recorded like every decision.

Wallets ask for sponsorship through the standard ERC-7677 interface, authenticated per application and held to quotas.

The ERC-7677 endpoint answers stub and final data within 500 ms at the 95th percentile, bundler round-trips excluded, measured in process by a test on every change.

Tested with a real wallet on a public test network, beyond the automated tests against a bundler.

CryptoRail-driven: your application asks

When your company builds the customer’s application (an embedded wallet, a mobile app), there is no external wallet to speak ERC-7677. Your system submits an intent like any other, in userOperation mode, naming the customer’s smart account as the actor and your paymaster as the payer. CryptoRail builds the operation for a pinned, audited account implementation, sponsors it, and sends its hash to the customer’s application as a signing request. The customer signs on their device; CryptoRail submits and tracks.

flowchart LR
    I["intent: actor = customer's account,<br/>payer = your paymaster"] --> P{policy}
    P -->|refuse| R[REJECTED_BY_POLICY, nothing built]
    P -->|allow| B[operation built and priced at the bundler]
    B --> S[sponsored twice, paymaster data signed]
    S --> Q[signing request: the operation hash]
    Q -->|customer signs in their app| U[submitted to the bundler]
    Q -->|customer refuses| X[SIGNING_REJECTED, with the reason]
    U --> C[CONFIRMED, cost recorded]

The customer’s key is an external identity: CryptoRail holds its address and sends it requests, never the key. This is the same asynchronous path an external custodian uses for your own transactions, described in the signing deep dive.

UserOperation nonces are not transaction nonces. The EntryPoint keeps them per account in independent lanes; CryptoRail reads them there and never mixes them with the nonces it allocates to your own sending addresses.

UserOperation nonces live in the EntryPoint's own lanes, apart from transaction nonces, so the two never block each other and pending approvals on one account wait in independent lanes.

How the customer’s account comes to exist

A customer usually starts with an ordinary address. How it becomes able to run sponsored operations depends on the network, and either way the sponsor pays.

flowchart TB
    A["customer's address and key"] --> Q{network supports EIP-7702?}
    Q -->|yes| S[customer signs a delegation authorization]
    S --> T[your onboarding identity sends and pays the type-4 transaction]
    T --> R1[same address, same key, now a smart account]
    Q -->|no| F[counterfactual smart account: address known before it exists]
    F --> D[the first sponsored operation deploys it]
    D --> R2[new address, owned by the customer's key]

In wallet-driven mode onboarding is the wallet’s business; CryptoRail only sponsors. In CryptoRail-driven mode CryptoRail does it, and the delegation transaction is an ordinary operation an operator sees in the list.

A customer's existing address becomes a smart account through EIP-7702 delegation, keeping its address and key, on networks that support it; elsewhere a smart account is deployed by its first operation. The sponsor pays for both.

What you pay for: policy and quotas

Sponsorship always goes through the policy engine, and twice: on the estimated cost and on the final gas, so a wallet cannot obtain an approval on a cheap estimate and spend more. A policy says:

  • On which networks, for which senders, for which contracts and which functions. What an operation calls is read from the account’s call data; a call CryptoRail cannot decode is treated as unknown and refused by any allow-list, never let through.
  • The maximum cost of one operation.
  • Cumulative limits per sponsored account or for the whole policy, per period: a number of operations, a total cost, or both.

A cumulative limit holds under concurrency: each sponsorship reserves its slice when it is granted, the slice is settled when the operation is included, and it is given back when the data expires unused or the operation fails before it is paid for. A process that dies in between cannot leave a slice taken forever.

Every sponsorship request goes through the policy engine twice, on the estimated cost and again on the final gas, and every decision, refusals included, is recorded with its reason and the policy version that took it.

Sponsorship budgets that are never exceeded, even under concurrent requests, with the cost attributed to each account and policy.

Sponsorship data a wallet never submits expires after its validity window and gives back the budget it had reserved.

The life of a sponsored operation

Sponsored operations share the transaction state machine and its vocabulary, with a few states of their own.

StateMeaning
SPONSOREDPaymaster data issued; waiting for the wallet or the customer to submit
SPONSORSHIP_EXPIREDThe validity window passed without submission; the reserved budget is released. Final
SUBMITTEDKnown to the bundler; the counterpart of BROADCAST
INCLUDEDIn a bundle transaction, with the cost the paymaster paid; the counterpart of MINED
CONFIRMED, REVERTEDAs for any transaction, after the network’s finality rule

A reorganisation that removes the bundle sends the operation back to SUBMITTED; a refused signature or a failure before submission ends with the failure report every operation carries. Every change of state reaches your systems through the same signed webhooks as any other event, described in events and integration.

Every failure comes with a report: the stage, a stable cause, whether a retry can work and on what condition, and the suggested action.

Every change of state of your own operations arrives through the same channel as the contract events.

Cost attribution and the deposit

When an operation is included, CryptoRail records what the paymaster actually paid, read from the chain, and attributes it to the paymaster, the sponsored account, the network and the policy version that sponsored it. Your finance team asks for a period and gets the sums; the export carries the detail of every operation.

What each sponsored operation actually cost is read from the chain and summed by period, by paymaster, by sponsored account, by network and by the policy version that sponsored it.

The complete history of any operation, exported in a machine-readable file for audit.

What actually pays is the paymaster’s deposit in the EntryPoint. CryptoRail reads it live, raises an alert when it falls below the threshold you set, and, only if you opt in, tops it up from a funded identity of yours. The top-up is an ordinary transaction under your policy, not a side channel.

The paymaster's deposit in the EntryPoint is watched: an alert when it falls below your threshold, and an opt-in top-up sent as an ordinary transaction under your policy.

Several calls, all or none

Some actions are two calls that must not happen apart: approve then pay, withdraw then repay. In userOperation mode one intent may carry two to sixteen calls, which the customer’s smart account executes in one operation: if any call reverts, they all revert.

flowchart LR
    I[intent with several calls] --> P{policy reads each call<br/>and the total}
    P -->|any call refused| R[whole operation refused, nothing built]
    P --> E{bundler simulation}
    E -->|a call would revert| F[PREPARATION_FAILED, nothing signed or paid]
    E --> U[one UserOperation, one signature]
    U -->|all succeed| C[CONFIRMED]
    U -->|state changed, one reverts on chain| X[REVERTED: none took effect, gas paid]

The policy checks every call on its own, so a forbidden call cannot hide among allowed ones, and applies per-operation caps and cumulative limits to the sum, so splitting a payment does not escape them. An approval covers every call in order. The operation has one cost: the chain does not measure gas per call, and CryptoRail does not invent a split. On a network with EIP-7702 a customer’s own address can run a multi-call once delegated; elsewhere it needs its smart account. An ordered batch of ordinary transactions is a different thing: ordered, not atomic.

Several calls that succeed or fail together, in one UserOperation of the customer's smart account: the policy reads every call and their sum, and a call that cannot succeed leaves none of them done.

Ordered batches from one identity, from the library: consecutive nonces, and the steps behind a failed one cancelled when you ask for it.

The contracts it stands on

RoleContractWhy
EntryPointThe canonical ERC-4337 EntryPoint v0.7The version audited accounts and bundlers support today
Account implementation (CryptoRail-driven mode)ZeroDev Kernel v3.3, an ERC-7579 accountThe most deployed ERC-7579 account, with first-party EIP-7702 support
Paymastereth-infinitism VerifyingPaymaster from account-abstraction v0.7.0Part of the audited reference repository; does exactly what the verifying scheme needs

Every one of them is pinned per network by address and code hash and checked when the process starts; a mismatch refuses to start. The paymaster is deployed once per deployment, with your owner and your signer, and pinned the same way.

Only the canonical EntryPoint and public account and paymaster contracts from audited lineages, pinned per network; no custom contract.

Sponsorship runs on the canonical EntryPoint v0.7; the version is a per-network setting, so moving to v0.8 is a configuration entry and a test run once an audited account implementation targets it.

Any bundler that speaks the standard ERC-4337 JSON-RPC, self-hosted or a provider's, checked for its network and EntryPoint at startup; tested on every change against a self-hosted Alto bundler.

Two reservations are written in the decision record rather than hidden. Kernel v3.3 stands on an audited lineage: the audits published with it name v3.0 and v3.1, no report naming v3.2 or v3.3 has been found, and the record keeps that open. The weighted validator used when the account itself enforces approvals is in the same position; the owner accepted its lineage for test networks and the journeys, and production use of that enforcement waits for a report naming its version or an internal review of the difference.

Worked example: customer programmes

The customer programmes pilot pack is the whole mechanism in one flow. A loyalty programme awards points to a customer; the customer redeems them for a reward from a smart account they own and that holds no ether; the programme’s paymaster pays, but only for redemptions, and only so many per customer per day.

sequenceDiagram
    participant P as Programme back office
    participant CR as CryptoRail
    participant C as Customer's app
    participant N as Network
    P->>CR: award 100 points to the customer, by name
    CR->>N: ordinary transaction, the programme pays
    C->>CR: redeem 30 points for a reward
    CR->>CR: policy: a redemption, within today's count? yes
    CR->>C: sign this operation hash
    C-->>CR: signature, with a key CryptoRail never holds
    CR->>N: one UserOperation: account deployed, points redeemed, paymaster pays
    CR->>P: signed webhooks: the award, the redemption, its cost
    C->>CR: transfer points to another customer
    CR-->>C: refused by policy before anything is signed or spent

The journey that proves it on every change also shows the refusals: a transfer to another customer (not sponsored), a redemption larger than the balance (fails in simulation, nothing paid, the day’s count given back), and a third redemption on the same day (over the count). The back office reads each redemption’s cost.

A ready-made customer programmes pilot pack: a loyalty points contract of our own on OpenZeppelin Contracts (points awarded with a reference, redeemed for a reward, never transferred between customers, pause, roles), compiled with pinned settings and checked on every change, an example sponsorship policy and a one-command setup that deploys it and registers it by name.

Proven on every change: a customer whose key never held ether redeems points from a smart account created by that first redemption, signing in their own application while the programme's paymaster pays; anything but a redemption, and more redemptions than the day allows, refused with their reason; the cost of each redemption reported and every event delivered to the back office as a signed webhook.

What it does not do

  • Custody of your end customers' keys. Not supported
  • Wallets and end-user interfaces. Not supported
  • End customers paying gas in ERC-20 tokens (token paymasters). Not supported
  • A paymaster or bundler configured on a free-gas network is refused at startup: there is no fee there to sponsor.
  • It implements no per-wallet logic. A wallet works if it speaks EIP-5792 with the ERC-7677 capability on EntryPoint v0.7. When the manual test was run, Coinbase Smart Wallet (EntryPoint v0.6) and MetaMask (without the paymaster capability) did not qualify.
  • It ships no custom contract. Introducing one would need a decision record and an audit budget.
  • It does not split the cost of a multi-call per call, and it does not make an ordered batch of ordinary transactions atomic.
  • It does not enforce sponsorship on chain beyond the paymaster’s signature. What you pay for is a rule in CryptoRail, enforced by refusing to sign; the chain checks only that the signature is valid, unexpired and covered by the deposit.
  • Operations CryptoRail builds accept only on-chain approval. An approval rule that asks for approvers’ off-chain signatures does not apply to them; the guarded smart account in the signing deep dive is the way.

Evidence

Every claim above links to its evidence on the evidence page. The main ones:

SubjectRequirements and decisionsJourneys
Non-custodial sponsorship, two modesFR-SPN-01, FR-SPN-02, FR-SPN-12J31, J32
Endpoint authentication, quotas, latencyFR-SPN-03, FR-SPN-17, NFR-SEC-08J31
Policy twice, records, budgets, expiryFR-SPN-04, FR-SPN-08, FR-SPN-11, NFR-REL-06J29, J31
Paymaster signing, depositFR-SPN-05, FR-SPN-07, FR-SIG-19J30, J31
Onboarding, nonce lanesFR-SPN-13, FR-SPN-14, FR-SIG-17J32, J33
Tracking and cost attributionFR-SPN-09, FR-SPN-10, FR-TX-23J31, J55
Contracts and bundlersFR-SPN-06, FR-SPN-15, FR-SPN-16, NFR-SEC-09, ADR-0003J30, J31
Several calls, all or noneFR-TX-30, ADR-0008J66
A real wallet on a public test networkNFR-INT-06J31 and the manual run of 2026-09-25
Customer programmes packFR-PLT-15, FR-PLT-16, FR-PLT-17, FR-PLT-19J55