Paymaster: как оплатить газ за пользователя
Paymaster позволяет спонсировать газ за пользователя в Account Abstraction. Показываем на коде, как подключить gasless-транзакции.
Gasless без ETH на кошельке пользователя
Paymaster — контракт в ERC-4337, который берёт на себя оплату газа за UserOperation. Пользователь по-прежнему подписывает намерение; ETH на smart-аккаунте для комиссии не обязателен.
Это главный продуктовый кейс Account Abstraction: убрать «сначала купи ETH на газ» из онбординга. Без smart-аккаунта и EntryPoint Paymaster не работает — обычный EOA gasless не умеет.
Verifying Paymaster: как устроена спонсорская схема
Два частых типа:
| Тип | Идея |
|---|---|
| Verifying Paymaster | Off-chain сервис решает «спонсировать или нет», подписывает разрешение; on-chain контракт проверяет подпись |
| ERC-20 Paymaster | Пользователь платит газ стейблкоином / токеном приложения |
Pimlico Verifying Paymaster — готовый сервис: клиент запрашивает спонсорство (pm_sponsorUserOperation), получает поля paymaster / paymasterData (и gas-лимиты paymaster), вшивает их в UserOp и шлёт bundler'у.
Клиент собирает UserOp (без оплаты газа пользователем)
↓
Paymaster RPC: «готовы спонсировать?» → paymaster + paymasterData
↓
Подпись smart-аккаунта
↓
Bundler → EntryPoint → газ списывается с Paymaster / его депозитаПодключаем verifying paymaster через Pimlico
Нужны пакеты permissionless и viem, API-ключ Pimlico. Пример — Sepolia: Safe smart-аккаунт + gasless-вызов. Ключ и (опционально) PRIVATE_KEY — из окружения.
import { writeFileSync } from "node:fs";
import { createSmartAccountClient } from "permissionless";
import { toSafeSmartAccount } from "permissionless/accounts";
import { createPimlicoClient } from "permissionless/clients/pimlico";
import { entryPoint07Address } from "viem/account-abstraction";
import {
type Hex,
createPublicClient,
http,
} from "viem";
import { generatePrivateKey, privateKeyToAccount } from "viem/accounts";
import { sepolia } from "viem/chains";
const apiKey = process.env.PIMLICO_API_KEY;
if (!apiKey) {
throw new Error("Задайте PIMLICO_API_KEY из dashboard.pimlico.io");
}
// Владелец аккаунта: свой ключ или одноразовый для теста
const privateKey =
(process.env.PRIVATE_KEY as Hex | undefined) ??
(() => {
const pk = generatePrivateKey();
writeFileSync(".env", `PRIVATE_KEY=${pk}\n`, { flag: "a" });
return pk;
})();
const publicClient = createPublicClient({
chain: sepolia,
transport: http("https://ethereum-sepolia-rpc.publicnode.com"),
});
const pimlicoUrl = `https://api.pimlico.io/v2/${sepolia.id}/rpc?apikey=${apiKey}`;
// Bundler + verifying paymaster на одном endpoint у Pimlico
const pimlicoClient = createPimlicoClient({
transport: http(pimlicoUrl),
entryPoint: {
address: entryPoint07Address,
version: "0.7",
},
});
const account = await toSafeSmartAccount({
client: publicClient,
owners: [privateKeyToAccount(privateKey)],
entryPoint: {
address: entryPoint07Address,
version: "0.7",
},
version: "1.4.1",
});
console.log("Smart account:", account.address);
// До первого UserOp контракта на адресе может не быть — деплой counterfactual
const smartAccountClient = createSmartAccountClient({
account,
chain: sepolia,
bundlerTransport: http(pimlicoUrl),
// Главное: paymaster заполняет paymaster* поля UserOp
paymaster: pimlicoClient,
userOperation: {
estimateFeesPerGas: async () => {
return (await pimlicoClient.getUserOperationGasPrice()).fast;
},
},
});
// Пользователь не платит Sepolia ETH за газ — спонсор Pimlico (в рамках квоты ключа)
const txHash = await smartAccountClient.sendTransaction({
to: "0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045",
value: 0n,
data: "0x1234",
});
console.log("Bundled tx:", `https://sepolia.etherscan.io/tx/${txHash}`);Под капотом клиент: собирает UserOp → просит verifying paymaster спонсорство → подписывает → eth_sendUserOperation. В receipt бандла газ оплачен не балансом пользователя на аккаунте (для комиссии), а политикой Paymaster.
Как это работает
paymaster: pimlicoClient — middleware спонсорства. Без него UserOp должен оплачиваться депозитом smart-аккаунта в EntryPoint (нужен ETH на аккаунте / депозите).
pm_sponsorUserOperation (внутри SDK) — off-chain решение paymaster'а. В UserOp v0.7 появляются paymaster, paymasterData, paymasterVerificationGasLimit, paymasterPostOpGasLimit.
toSafeSmartAccount — counterfactual адрес: байткод появится при первом успешном UserOp (factory + factoryData). Paymaster обычно спонсирует и деплой, и вызов — иначе «пустой» аккаунт не стартует.
getUserOperationGasPrice().fast — комиссии bundler'а Pimlico; для их сети fees лучше брать с bundler RPC, а не с публичного eth_gasPrice.
Политика спонсорства (то, что решает продукт)
Verifying paymaster — не «бесплатный газ навсегда», а ваш бюджет + правила:
- кого спонсировать (только ваши
sender, только определённыйcallData); - лимиты на UserOp / день / пользователя;
- testnet vs mainnet (на mainnet без пополненного баланса paymaster'а спонсорства не будет).
На Pimlico это настраивается в dashboard и через sponsorship policies. В коде выше — дефолтная спонсорская квота API-ключа на Sepolia.
Альтернатива verifying — ERC-20 paymaster: пользователь платит USDC, UX всё ещё без «ETH на газ», но не полностью free.
Частые ошибки
Ждать gasless от обычного MetaMask EOA → Paymaster работает только в потоке UserOperation / EntryPoint. Без smart-аккаунта спонсировать нечего.
Забыть paymaster в createSmartAccountClient → bundler примет UserOp только если у аккаунта есть депозит ETH в EntryPoint. Ошибка будет про insufficient funds / prepaid gas, а не про «paymaster не подключён».
Собрать UserOp вручную и не вызвать sponsor → пустые paymaster* = пользователь платит сам. SDK с paymaster: pimlicoClient делает sponsor до подписи автоматически.
Крутить mainnet с testnet-ключом / нулевым балансом paymaster → Sepolia-квота не переносится. На mainnet сначала политика и депозит спонсора.
Что дальше
- Обзор провайдеров Account Abstraction — Safe, ZeroDev, Alchemy Account Kit и готовые paymaster'ы
- ERC-4337: как устроена транзакция — где именно в цепочке живут поля paymaster
- Частые ошибки при переходе на Account Abstraction — газ UserOp, initCode, nonce смарт-аккаунтов