Skip to main content
Use third-party on-chain paymasters for ERC-20 gas payments. This approach gives you flexibility to use different paymaster providers while still benefiting from Gelato’s high-performance bundler.
On-chain paymasters are smart contracts that sponsor gas fees by accepting ERC-20 tokens from users. They handle the token-to-ETH conversion on-chain, allowing users to pay gas with tokens they hold.

Implementations

This example uses Pimlico’s ERC-20 Paymaster. You can substitute any compatible on-chain paymaster.
npm install permissionless viem
1

Create an API Key

Check out our How-To Guide for detailed instructions on generating a Gelato API key.You’ll also need an API key from your paymaster provider (e.g., Pimlico).
2

Create Smart Account

import { createSmartAccountClient } from "permissionless";
import { createPimlicoClient } from "permissionless/clients/pimlico";
import { prepareUserOperationForErc20Paymaster } from "permissionless/actions/erc20";
import { createPublicClient, http, type Hex } from "viem";
import { entryPoint07Address, toSoladySmartAccount } from "viem/account-abstraction";
import { privateKeyToAccount } from "viem/accounts";
import { baseSepolia } from "viem/chains";

const owner = privateKeyToAccount(process.env.PRIVATE_KEY as Hex);

const client = createPublicClient({
  chain: baseSepolia,
  transport: http(),
});

const account = await toSoladySmartAccount({
  client,
  owner,
});
3

Create Paymaster Client

Set up the on-chain paymaster client. This example uses Pimlico:
const pimlicoUrl = `https://api.pimlico.io/v2/${baseSepolia.id}/rpc?apikey=${process.env.PIMLICO_API_KEY}`;

const paymasterClient = createPimlicoClient({
  chain: baseSepolia,
  transport: http(pimlicoUrl),
  entryPoint: {
    address: entryPoint07Address,
    version: "0.7",
  },
});
4

Create Smart Account Client with Gelato Bundler

Combine Gelato’s bundler with the on-chain paymaster:
const bundlerUrl = `https://api.t.gelato.cloud/rpc/${baseSepolia.id}`;

const smartClient = createSmartAccountClient({
  account,
  chain: baseSepolia,
  bundlerTransport: http(bundlerUrl, {
    fetchOptions: {
      headers: {
        'X-API-Key': process.env.GELATO_API_KEY
      }
    }
  }),
  paymaster: paymasterClient,
  userOperation: {
    estimateFeesPerGas: async ({ bundlerClient }) => {
      const gasPrices = await bundlerClient.request({
        method: "eth_getUserOperationGasPrice",
        params: [],
      });
      return {
        maxFeePerGas: BigInt(gasPrices.maxFeePerGas),
        maxPriorityFeePerGas: BigInt(gasPrices.maxPriorityFeePerGas),
      };
    },
    prepareUserOperation: prepareUserOperationForErc20Paymaster(paymasterClient),
  },
});
5

Send Transaction

const USDC_ADDRESS = "0x036CbD53842c5426634e7929541eC2318f3dCF7e"; // USDC (Base Sepolia)

const txHash = await smartClient.sendTransaction({
  to: "0xE27C1359cf02B49acC6474311Bd79d1f10b1f8De",
  value: 0n,
  data: "0xd09de08a", // increment()
  paymasterContext: {
    token: USDC_ADDRESS,
  },
});

console.log(`Transaction hash: ${txHash}`);

How It Works

  1. Request Sponsorship - Your app requests paymaster data from the on-chain paymaster provider
  2. Build UserOperation - Include the paymaster fields (paymaster, paymasterData, gas limits)
  3. Submit to Bundler - Gelato validates and bundles the UserOperation
  4. On-Chain Execution - The paymaster validates the operation and charges ERC-20 tokens

Compatible Paymasters

Any ERC-4337 compatible paymaster works with Gelato’s bundler:
ProviderDocumentation
Pimlicodocs.pimlico.io
Alchemydocs.alchemy.com
Biconomydocs.biconomy.io
StackUpdocs.stackup.sh

Additional Resources