Skip to main content

Overview

Gasless transactions let users pay network fees using ERC-20 tokens (USDC, USDT) instead of requiring native gas (ETH, MATIC). This eliminates a major friction point—users don’t need to hold the native token on every chain.
BenefitHow It Works
No native gas requiredUsers pay fees in stablecoins or other ERC-20 tokens
Better UXNo “insufficient gas” errors for users with only stablecoins
Permit signaturesEIP-2612 permits enable gasless token approvals
Flexible fee optionsSDK shows available fee token options automatically

How Gasless Works

Trails supports two approaches for gasless transactions:
  1. ERC-20 Fee Tokens (Default) — Users sign a permit, and Trails’ relayer submits the transaction. The fee is deducted from the user’s ERC-20 balance.
  2. 4337 Paymasters — For apps with their own paymaster infrastructure, Trails can route through ERC-4337 bundlers.

Basic Gasless Payment

When using the SDK, gasless fee options are automatically displayed if the user’s origin token supports permits:
import { TrailsWidget } from '0xtrails/widget'

export function GaslessPayment() {
  return (
    <TrailsWidget
      apiKey="YOUR_API_KEY"
      mode="pay"
      toAddress="0xMERCHANT_ADDRESS"
      toAmount="50"
      toChainId={137} // Polygon
      toToken="USDC"
      onCheckoutComplete={({ sessionId }) => {
        console.log('Payment complete:', sessionId)
      }}
    >
      <button>Pay $50</button>
    </TrailsWidget>
  )
}
When the user has USDC (a permit-compatible token), the SDK:
  1. Shows fee options including “Pay gas in USDC”
  2. Requests a permit signature (no approval transaction needed)
  3. Submits via relayer—user’s USDC covers the gas fee

USDC/USDT as Gas Fee Examples

Pay with USDC on Polygon

<TrailsWidget
  apiKey="YOUR_API_KEY"
  mode="pay"
  toAddress="0xMERCHANT_ADDRESS"
  toAmount="100"
  toChainId={137} // Polygon
  toToken="USDC"
  onCheckoutComplete={({ sessionId }) => {
    verifyPayment(sessionId)
  }}
>
  <button>Pay $100 (Gas in USDC)</button>
</TrailsWidget>
The user only needs USDC—no ETH required for gas.

Pay with USDT on Polygon

<TrailsWidget
  apiKey="YOUR_API_KEY"
  mode="pay"
  toAddress="0xMERCHANT_ADDRESS"
  toAmount="75"
  toChainId={137} // Polygon
  toToken="USDT"
  onCheckoutComplete={({ sessionId }) => {
    verifyPayment(sessionId)
  }}
>
  <button>Pay $75 (Gas in USDT)</button>
</TrailsWidget>

Cross-Chain Gasless

Even cross-chain payments can be gasless if the origin token supports permits:
<TrailsWidget
  apiKey="YOUR_API_KEY"
  mode="pay"
  toAddress="0xMERCHANT_ADDRESS"
  toAmount="200"
  toChainId={137} // Settle on Polygon
  toToken="USDC"
  onCheckoutComplete={({ sessionId }) => {
    verifyPayment(sessionId)
  }}
>
  <button>Pay $200</button>
</TrailsWidget>
User pays with USDC on Base → Trails bridges gaslessly → Merchant receives USDC on Polygon.

Permit-Compatible Tokens

Gasless transactions require tokens that implement EIP-2612 (permit):
TokenPermit SupportNotes
USDCNative Circle USDC on all supported chains
USDTMost chains (verify per-chain)
DAISupports permit on Ethereum, L2s
WETHWrapped ETH supports permit
Most ERC-20sVariesCheck if token has permit() function
Native tokens (ETH, MATIC, etc.) cannot be used for gasless since they don’t support permits. Users paying with native tokens will use standard gas.

How Fee Options Work

The SDK automatically fetches available fee options based on:
  • User’s token balances on the origin chain
  • Which tokens support permit signatures
  • Current gas prices and token exchange rates
Users see a “Gas Fee Options” dropdown with choices like:
  • ETH (native gas)
  • USDC ($0.12)
  • USDT ($0.12)
Selecting an ERC-20 option triggers the gasless flow.

Programmatic Fee Selection

You can listen to fee option events:
<TrailsWidget
  apiKey="YOUR_API_KEY"
  mode="pay"
  toAddress="0xMERCHANT_ADDRESS"
  toAmount="50"
  toChainId={137}
  toToken="USDC"
  onCheckoutStart={({ sessionId }) => {
    console.log('Checkout started:', sessionId)
  }}
  onCheckoutSignatureRequest={() => {
    console.log('Permit signature requested')
  }}
  onCheckoutSignatureConfirmed={() => {
    console.log('Permit signed—submitting to relayer')
  }}
  onCheckoutComplete={({ sessionId }) => {
    console.log('Gasless payment complete:', sessionId)
  }}
>
  <button>Pay</button>
</TrailsWidget>

4337 Paymaster Integration

For apps with existing paymaster infrastructure (Alchemy, Pimlico, ZeroDev, Thirdweb), configure per-chain paymaster URLs:
<TrailsWidget
  apiKey="YOUR_API_KEY"
  mode="pay"
  paymasterUrls={[
    { chainId: 137, url: 'https://your-paymaster.example.com/polygon' },
    { chainId: 8453, url: 'https://your-paymaster.example.com/base' },
  ]}
  toAddress="0xMERCHANT_ADDRESS"
  toAmount="100"
  toChainId={137}
  toToken="USDC"
>
  <button>Pay (Sponsored Gas)</button>
</TrailsWidget>

Supported Paymaster Providers

ProviderNotes
AlchemyUses bundler-only mode (no separate paymaster client)
PimlicoFull paymaster + bundler support
ZeroDevFull paymaster + bundler support
ThirdwebFull paymaster + bundler support
When using paymasterUrls, the paymaster sponsors the gas entirely. Users don’t pay any fee—the app/merchant absorbs it.

Gasless Flow Details

Without Paymaster (ERC-20 Fees)

  1. Quote Intent — SDK fetches quote including gasFeeOptions with available fee tokens
  2. User Selects Fee — User picks USDC, USDT, or native gas from dropdown
  3. Permit Signature — If ERC-20 fee selected, user signs EIP-2612 permit (no on-chain tx)
  4. Intent Signature — User signs the intent data
  5. Relayer Submits — Trails relayer executes the transaction, deducting fee from user’s balance
  6. Completion — User receives confirmation once destination transaction confirms

With Paymaster (4337)

  1. Prepare UserOp — SDK prepares ERC-4337 user operation
  2. Paymaster Sponsorship — Paymaster adds paymasterAndData to sponsor gas
  3. User Signs — User signs the user operation
  4. Bundler Submits — Bundler submits to entry point
  5. Completion — User receives confirmation

Limitations

Smart Contract Wallets: Gasless deposits via permit signatures require EOA (externally owned account) wallets. Smart contract wallets produce non-standard signatures that the current relayer doesn’t support.
// This will fail for smart contract wallets
<TrailsWidget
  mode="pay"
  // ... gasless will automatically fall back to native gas for SC wallets
>
The SDK automatically detects smart contract wallets and falls back to native gas flow. Native Token Payments: Sending ETH, MATIC, or other native tokens cannot be gasless—you need native gas to send native gas.

Best Practices

Don’t force gasless. Some users prefer paying native gas (often cheaper at low congestion). The SDK shows both options by default.
Users might reject the permit signature. Handle this gracefully:
onCheckoutSignatureRejected={(error) => {
  console.log('User rejected signature:', error)
  // Show retry option or native gas alternative
}}
Not all ERC-20 tokens support permits. The SDK automatically filters to show only valid fee options, but for API integrations, check token contracts.
If using custom paymasters:
  • Validate paymaster URLs are HTTPS
  • Use separate paymaster URLs per environment (dev/prod)
  • Monitor paymaster spending and set limits
  • Consider allowlisting user operations by contract/method

Troubleshooting

IssueCauseSolution
No ERC-20 fee options shownToken doesn’t support permitUser must pay native gas
”Smart contract wallets not supported”SC wallet detectedUse native gas flow
Permit signature failsToken permit implementation variesTry a different token or native gas
Paymaster rejects UserOpPaymaster policy/limitsCheck paymaster configuration

Next Steps