How to use the ERC-20 Paymaster | Pimlico Docs
Skip to content

How to use the ERC-20 Paymaster

This guide will show you how to use the prepareUserOperationForErc20Paymaster function in permissionless.

This function lets you approve only the required amount of tokens for your userOperation. The approval call will be injected into the userOperation's calldata before it is sent.

Steps

Define imports and create the clients

import { prepareUserOperationForErc20Paymaster } from "permissionless/experimental/pimlico"
import { createSmartAccountClient } from "permissionless"
import { toSafeSmartAccount } from "permissionless/accounts"
import { createPimlicoClient } from "permissionless/clients/pimlico"
import { createPublicClient, Hex, http } from "viem"
import { privateKeyToAccount } from "viem/accounts"
import { entryPoint07Address } from "viem/account-abstraction"
import { base } from "viem/chains"
 
const chain = base
 
export const publicClient = createPublicClient({
	chain,
	transport: http("https://mainnet.base.org"),
})
 
const pimlicoUrl = `https://api.pimlico.io/v2/${chain.id}/rpc?apikey=${process.env.PIMLICO_API_KEY}`
 
const pimlicoClient = createPimlicoClient({
	chain,
	transport: http(pimlicoUrl),
	entryPoint: {
		address: entryPoint07Address,
		version: "0.7",
	},
})
 
const account = await toSafeSmartAccount({
	client: publicClient,
	owners: [privateKeyToAccount(process.env.PRIVATE_KEY as Hex)],
	entryPoint: {
		address: entryPoint07Address,
		version: "0.7",
	},
	version: "1.4.1",
})

Add the prepareUserOperationForErc20Paymaster override to createSmartAccountClient

This override will replace viem's prepareUserOperation action.

const smartAccountClient = createSmartAccountClient({
	account,
	chain,
	bundlerTransport: http(pimlicoUrl),
	paymaster: pimlicoClient,
	userOperation: {
		estimateFeesPerGas: async () => {
			return (await pimlicoClient.getUserOperationGasPrice()).fast
		},
		prepareUserOperation: prepareUserOperationForErc20Paymaster(pimlicoClient),
	},
})

By default, prepareUserOperationForErc20Paymaster does not override the user's ERC-20 token balance when estimating.
If you want to estimate the operation without relying on the user's actual token balance (for example, when the user hasn't received tokens yet), you can pass the balanceOverride option as true like:

prepareUserOperation: prepareUserOperationForErc20Paymaster(pimlicoClient, { balanceOverride: true }),

Call sendTransaction

Calling sendTransaction will now automatically approve the required amount of tokens for your userOperation.

If the sender has a sufficient existing approval, then the additional approval call will not be added to the calldata.

const token = "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913"
 
const hash = await smartAccountClient.sendTransaction({
	calls: [
		{
			to: "0xd8da6bf26964af9d7eed9e03e53415d37aa96045",
			value: 0n,
			data: "0x1234",
		},
	],
	paymasterContext: {
		token,
	},
})