Skip to content
Executive summary

The Gas Station Service automatically funds transaction fees for sponsored accounts.

  • Eliminates the need for end-user accounts to hold native tokens for gas fees.
  • Supports account-level and domain-level sponsorship with subdomain inheritance.
  • Works with Ethereum and EVM-compatible blockchains.
  • Uses Just-in-Time (JIT) funding to transfer exact fee amounts when needed.
  • Provides low-balance alerts to ensure sponsor accounts remain funded.
Why this matters

For operators: Gas Station removes friction from end-user transactions. Users don't need to acquire native tokens (e.g., ETH) just to pay fees—your organization sponsors those costs from designated accounts. This is essential for onboarding users who hold only stablecoins or other tokens.

For architects: The service integrates with existing Ripple Custody policies and intents. A dedicated bot user handles automated approvals, so you maintain full audit trails while eliminating manual fee-funding steps.

Current limitations
  • Chain support: Ethereum and EVM-compatible chains only. Support for additional chains (Solana, XRPL) will be added in the future.
  • Alert delivery: Low-balance alerts are delivered through your monitoring infrastructure. Configure alerts in your monitoring system (e.g., Grafana) to receive email or Slack notifications.
  • Cross-chain sponsorship: A sponsor account can only fund accounts on the same blockchain network.
  • Implementation approach: The current Gas Station implementation uses a mechanical funding approach: the service detects pending transactions and transfers gas fees from sponsor accounts to sponsored accounts as standard blockchain transactions. This release does not leverage native gas abstraction mechanisms such as ERC-4337 Paymasters. Support for native paymaster integration (including EIP-7701 Native Account Abstraction) will be added in the future.

Before you begin

Prerequisites: Familiarity with Ripple Custody accounts, domains, and transaction processing.

Further reading:


Overview

The Gas Station Service is a background service that monitors transaction events and automatically funds accounts that lack sufficient native tokens to cover gas fees. When a sponsored account initiates a transaction, the service:

  1. Detects the pending transaction
  2. Estimates the required fee using a dry-run API call
  3. Transfers the exact amount (plus a safety margin) from the sponsor account
  4. Allows the original transaction to proceed

Processing flow

The Gas Station Service continuously monitors Ripple Custody for transaction events and automatically funds accounts that need gas. The following state diagram shows the decision logic at each step:

Event detected

Has sufficient funds

Insufficient funds

Yes (account sponsored)

No

Yes (domain sponsored)

No sponsor found

Yes (sufficient balance)

No (low balance)

Yes

No

No sponsorship needed

Poll Events

Outbound Transaction Detected

Is Account Sponsored?

Is Domain Sponsored?

Estimate Fee via Dry-Run API

Create Funding Transaction Intent

Does Sponsor Have Sufficient Balance?

Funding Successful

Does Sponsor Still Have Sufficient Balance?

Account Has Sufficient Funds for Fees

Send Low Balance Alert

Do nothing

Event detected

Has sufficient funds

Insufficient funds

Yes (account sponsored)

No

Yes (domain sponsored)

No sponsor found

Yes (sufficient balance)

No (low balance)

Yes

No

No sponsorship needed

Poll Events

Outbound Transaction Detected

Is Account Sponsored?

Is Domain Sponsored?

Estimate Fee via Dry-Run API

Create Funding Transaction Intent

Does Sponsor Have Sufficient Balance?

Funding Successful

Does Sponsor Still Have Sufficient Balance?

Account Has Sufficient Funds for Fees

Send Low Balance Alert

Do nothing

Flow steps

1. Poll Events

The Gas Station Service continuously polls Ripple Custody for transaction events using the /v1/domains/{domainId}/events endpoint. The polling interval is configurable (default: 5 seconds).

2. Detect Transaction

When an event is received, the service identifies outbound transactions by checking the orderReference field. Inbound transactions (where orderReference is null) are ignored.

3. Check Balance

The service retrieves the account's native token balance using /v1/domains/{domainId}/accounts/{accountId}/balances. If the account already has sufficient funds for the estimated fee, no sponsorship is needed.

4. Check Sponsorship

For accounts with insufficient balance, the service looks up sponsorship configuration:

  • Account-level first: Check if the specific account has a dedicated sponsor
  • Domain-level second: Check if the account's domain has a sponsor (with optional subdomain inheritance)

If no sponsor is found, the transaction remains in "Preparing" state until funds are manually added.

5. Estimate Fee

The service uses Ripple Custody's dry-run API to calculate the exact gas amount required for the transaction. A configurable safety margin (default: 10%) is applied to account for fee volatility.

6. Create Funding Intent

The service generates a transaction order payload to transfer the required gas amount from the sponsor account to the sponsored account. This payload is signed by the bot user's private key.

7. Check Sponsor Balance

Before submitting, the service verifies the sponsor account has sufficient funds via a dry-run check. If the sponsor lacks funds, the funding transaction is not submitted.

8. Alert if Low

After successful funding (or if funding fails due to low balance), the service checks the sponsor's remaining balance against configured alert thresholds. If the balance falls below the threshold, a notification is sent to the monitoring system.


Detailed sequence

The following diagram shows the complete API interactions between the Gas Station Service and Ripple Custody, including the specific endpoints called at each step:

GasStationRCUSGasStationRCUSTransaction will stay in preparing if not enough fees/v1/domains/{domainId}/events/v1/domains/{domainId}/transactions/{transactionId}Inbound transaction, ignore it/v1/domains/{domainId}/transactions/orders/{transactionOrderId}/v1/domains/{domainId}/accounts/{accountId}/balances/v1/domains/{domainId}/intents?entityId={transactionOrderId}&details.payload.type="v0_CreateTransactionOrder"Get estimated transaction feeAccount has sufficient balanceNo sponsorship neededNo sponsor foundTransaction remains in preparing stateFund the sponsored account with gasAlert user to refill sponsor accountalt[sponsorBalance < configuredAlertLimit]alt[dryRunResult is success (Enough funds in sponsor)]alt[sponsorAccountId is null][sponsor found]alt[accountNativeBalance >= estimate.fee][accountNativeBalance < estimate.fee]alt[orderReference is null][orderReference is not null]UsercreateTransactionOrderIntent()pollTransactionCreatedEvents(): { transactionId }getTransactionDetails(transactionId): { orderReference.id }getTransactionOrderDetails(orderReference.id): { accountSourceId, ... }getAccountNativeBalance(accountSourceId): accountNativeBalancegetIntentForTransactionOrder(orderReference.id, "v0_CreateTransactionOrder"): intentrunDryRunForIntent(intent.id): { estimate.fee }findSponsoringAccount(accountSourceId): sponsorAccountIdcreateTransactionOrderPayload(sponsorAccountId, accountSourceId, estimate.fee)runDryRun(payload): dryRunResultsignIntent(payload)submitIntent(signedPayload)getSponsorBalance(sponsorAccountId): sponsorBalancesendNotification("Sponsor low balance")User
GasStationRCUSGasStationRCUSTransaction will stay in preparing if not enough fees/v1/domains/{domainId}/events/v1/domains/{domainId}/transactions/{transactionId}Inbound transaction, ignore it/v1/domains/{domainId}/transactions/orders/{transactionOrderId}/v1/domains/{domainId}/accounts/{accountId}/balances/v1/domains/{domainId}/intents?entityId={transactionOrderId}&details.payload.type="v0_CreateTransactionOrder"Get estimated transaction feeAccount has sufficient balanceNo sponsorship neededNo sponsor foundTransaction remains in preparing stateFund the sponsored account with gasAlert user to refill sponsor accountalt[sponsorBalance < configuredAlertLimit]alt[dryRunResult is success (Enough funds in sponsor)]alt[sponsorAccountId is null][sponsor found]alt[accountNativeBalance >= estimate.fee][accountNativeBalance < estimate.fee]alt[orderReference is null][orderReference is not null]UsercreateTransactionOrderIntent()pollTransactionCreatedEvents(): { transactionId }getTransactionDetails(transactionId): { orderReference.id }getTransactionOrderDetails(orderReference.id): { accountSourceId, ... }getAccountNativeBalance(accountSourceId): accountNativeBalancegetIntentForTransactionOrder(orderReference.id, "v0_CreateTransactionOrder"): intentrunDryRunForIntent(intent.id): { estimate.fee }findSponsoringAccount(accountSourceId): sponsorAccountIdcreateTransactionOrderPayload(sponsorAccountId, accountSourceId, estimate.fee)runDryRun(payload): dryRunResultsignIntent(payload)submitIntent(signedPayload)getSponsorBalance(sponsorAccountId): sponsorBalancesendNotification("Sponsor low balance")User

Sponsorship hierarchy

The Gas Station Service supports flexible sponsorship configurations:

LevelDescription
Account-levelA sponsor account funds a specific list of accounts
Domain-levelA sponsor account funds all accounts within a domain
Subdomain inheritanceWhen includeSubDomains is enabled, sponsorship extends to all child domains

Lookup algorithm

When determining which sponsor to use, the service follows this hierarchy:

  1. Direct account sponsor: Check if the account has a dedicated sponsor
  2. Domain sponsor: Check if the account's domain has a sponsor
  3. Parent domain sponsor: If includeSubDomains is enabled, walk up the domain hierarchy

Yes

No

Yes

No

Yes

No

Transaction detected

Account has direct sponsor?

Use account sponsor

Domain has sponsor?

Use domain sponsor

Parent domain with includeSubDomains?

Use parent domain sponsor

No sponsorship - transaction waits

Yes

No

Yes

No

Yes

No

Transaction detected

Account has direct sponsor?

Use account sponsor

Domain has sponsor?

Use domain sponsor

Parent domain with includeSubDomains?

Use parent domain sponsor

No sponsorship - transaction waits

Each account can have only one sponsor. If you configure both account-level and domain-level sponsorship, the account-level sponsor takes precedence.


Supported chains

The Gas Station Service currently supports Ethereum and EVM-compatible blockchains:

Chain typeNetworksFee token
EVM-compatibleEthereum, Polygon, Avalanche, BSCETH, MATIC, AVAX, BNB

Support for additional chains (Solana, XRPL) will be added in the future.

The service uses Ripple Custody's dry-run API to estimate fees. All chain-specific fee calculations are handled automatically.


Bot user and automation

The Gas Station Service uses a dedicated bot user to sign and submit funding transactions automatically:

  • No manual approval required: Once you configure the bot user with auto-approval policies, gas funding transactions are approved automatically without human intervention
  • Full audit trail: All bot user actions are logged in the Ripple Custody intent system
  • Secure key storage: The bot user's private key is stored in a secure vault (Kubernetes Secret or HashiCorp Vault)

If your organization adds additional approval requirements to the bot user's transactions, automatic sponsorship will be blocked. Funding transactions will require manual approval, defeating the purpose of the Gas Station.


Low-balance alerts

Configure alert thresholds to receive notifications when sponsor account balances fall below specified levels.

Alert configuration

When you configure a sponsor, you can set alert thresholds for each native token the sponsor holds:

FieldDescription
tickerIdThe UUID of the native token to monitor (e.g., ETH, MATIC, AVAX)
amountThe balance threshold—alerts trigger when the balance falls to or below this amount

You can configure multiple alert thresholds per sponsor, one for each token type.

How alerts work

The Gas Station Service checks the sponsor account balance after each funding transaction:

  1. After successfully funding a sponsored account, the service retrieves the sponsor's current balance
  2. For each configured alert threshold, it compares the current balance to the threshold amount
  3. If the balance is at or below the threshold, the service emits an alert event

Alert delivery

Alerts are delivered through your monitoring infrastructure:

  • Grafana integration: All alerts are sent to Grafana as log events and metrics
  • Configure notifications: Set up Grafana alerting rules to receive notifications via email, Slack, PagerDuty, or other channels
  • Monitor the metric: gas_station_sponsor_low_balance indicates when a sponsor balance is below threshold

Configure Grafana alerts to notify your operations team before sponsor accounts run out of funds. This ensures uninterrupted sponsorship for your users.


Fee estimation and safety margin

The service estimates transaction fees using the Ripple Custody dry-run API:

  1. Retrieve the original transaction intent
  2. Execute a dry-run to simulate the transaction
  3. Apply a configurable safety margin (default: 10%)
  4. Transfer the total amount to the sponsored account

The safety margin accounts for fee volatility between estimation and actual transaction broadcast.


Retry and fault tolerance

The Gas Station Service implements a two-tier retry mechanism to handle transient failures:

Tier 1: Immediate retries

For transient failures during event processing, the service performs immediate in-memory retries:

ParameterValue
Max attempts3 retries per operation
Backoff strategyExponential [1s, 2s, 4s]
Timeout10 seconds per attempt
Total time~17 seconds worst case

Tier 2: Queue-based retries

When immediate retries are exhausted, jobs are persisted to a database queue for background processing:

ParameterValue
Retry intervalFixed 5 minutes between cycles
Maximum age24 hours from job creation
Maximum retry count20 attempts

Jobs exceeding these limits are moved to a dead letter queue for manual investigation.

The two-tier retry mechanism ensures that temporary failures (network issues, API timeouts) don't cause permanent funding failures while preventing infinite retry loops.


Performance

The Gas Station Service is designed to meet strict performance requirements:

MetricTarget
End-to-end funding time< 2 minutes
Polling interval5 seconds (configurable)
Happy path~35 seconds (including blockchain confirmation)
Worst case with retries~72 seconds (well within SLA)

SLA breakdown

  • Event polling interval: 5 seconds
  • Dry-run API call: 1-3 seconds
  • Funding transaction submission: 1-2 seconds
  • Blockchain confirmation: varies by chain (EVM: 12-15s)

Next steps

TopicDescription
Gas Station referenceConfiguration parameters and deployment options
Configure bot usersSet up bot users for automated operations
Configure gas sponsorshipSet up sponsor accounts and configure sponsorship rules