Разработка Account Abstraction Paymaster
ERC-4337 Account Abstraction убирает один из главных барьеров входа в Web3: пользователь больше не обязан держать нативный токен (ETH, MATIC, BNB) для оплаты gas. Paymaster — контракт в ERC-4337 стеке, который берёт на себя оплату gas от имени пользователя. Это ключевой компонент для приложений, где gasless UX — конкурентное требование: onboarding новых пользователей, gaming, social apps.
Как Paymaster вписывается в ERC-4337
В стандартной транзакции: пользователь → подписывает транзакцию → платит gas в ETH. В ERC-4337 flow: пользователь подписывает UserOperation (не транзакцию) → Bundler собирает UserOps в батч → EntryPoint контракт вызывает validatePaymasterUserOp → если Paymaster одобряет — платит gas → postOp вызывается после исполнения.
UserOperation {
sender, // smart account пользователя
callData, // что выполнить
paymasterAndData, // адрес Paymaster + его данные
signature, // подпись пользователя
...gasFields
}
paymasterAndData — это address(paymaster) + bytes(paymasterSpecificData). Paymaster декодирует свои данные из этого поля.
Типы Paymaster и их архитектура
Verifying Paymaster (sponsored gas)
Наиболее распространённый паттерн: off-chain сервис решает, спонсировать ли конкретную UserOperation, и подписывает разрешение. Paymaster контракт верифицирует эту подпись.
contract VerifyingPaymaster is BasePaymaster {
address public verifyingSigner;
function _validatePaymasterUserOp(
UserOperation calldata userOp,
bytes32 userOpHash,
uint256 maxCost
) internal override returns (bytes memory context, uint256 validationData) {
// Декодируем данные: подпись backend-а + срок действия
(uint48 validUntil, uint48 validAfter, bytes calldata signature) =
abi.decode(userOp.paymasterAndData[20:], (uint48, uint48, bytes));
// Хэш для верификации = хэш UserOp + validUntil + validAfter
bytes32 hash = ECDSA.toEthSignedMessageHash(
keccak256(abi.encode(userOpHash, validUntil, validAfter))
);
// Если подпись от verifyingSigner — спонсируем
if (ECDSA.recover(hash, signature) != verifyingSigner) {
return ("", _packValidationData(true, validUntil, validAfter));
}
return ("", _packValidationData(false, validUntil, validAfter));
}
}
Backend получает UserOp от frontend, проверяет условия (пользователь в whitelist? достиг ли лимита бесплатных транзакций? тип операции разрешён?), подписывает и возвращает paymasterAndData. Frontend подставляет в UserOp и отправляет Bundler-у.
ERC-20 Paymaster (gas в токенах)
Пользователь платит gas в USDC/USDT вместо ETH. Paymaster принимает ERC-20 и пополняет свой ETH депозит в EntryPoint из собственных средств.
function _validatePaymasterUserOp(...)
internal override returns (bytes memory context, uint256 validationData) {
(address token, uint256 exchangeRate) =
abi.decode(userOp.paymasterAndData[20:], (address, uint256));
uint256 tokenCost = (maxCost * exchangeRate) / 1e18;
// Проверяем allowance пользователя
require(
IERC20(token).allowance(userOp.sender, address(this)) >= tokenCost,
"Insufficient allowance"
);
// context передаём в postOp для реального списания
return (abi.encode(userOp.sender, token, tokenCost), 0);
}
function _postOp(PostOpMode mode, bytes calldata context, uint256 actualGasCost)
internal override {
(address sender, address token, uint256 maxTokenCost) =
abi.decode(context, (address, address, uint256));
// Реальная стоимость может быть меньше maxCost
uint256 actualTokenCost = (actualGasCost * exchangeRate) / 1e18;
IERC20(token).transferFrom(sender, address(this), actualTokenCost);
}
Ключевая сложность ERC-20 Paymaster — exchange rate. Нужен актуальный курс ETH/token на момент транзакции. Варианты: Chainlink oracle, TWAP из Uniswap V3, или централизованный price feed от backend.
Депозит и управление балансом
Paymaster должен держать ETH депозит в EntryPoint контракте. EntryPoint списывает gas из этого депозита после каждой спонсированной UserOperation.
// Пополнение депозита
entryPoint.depositTo{value: 1 ether}(address(paymaster));
// Просмотр баланса
uint256 balance = entryPoint.balanceOf(address(paymaster));
// Вывод (unstake period для staked Paymaster)
entryPoint.withdrawTo(payable(owner), amount);
Для production нужен мониторинг баланса и автоматическое пополнение. Если депозит иссякнет — все UserOp через этот Paymaster начнут ревертиться. Рекомендуем: alert при балансе ниже порога + auto-topup из treasury через Chainlink Automation или кастомный keeper.
Rate limiting и защита от abuse
Без ограничений один пользователь может дренировать весь бюджет Paymaster через spam транзакций. Стратегии защиты:
Per-user spending limit. Off-chain в Verifying Paymaster backend: каждый адрес имеет месячный лимит в USD. Backend отказывает в подписи при превышении.
Cooldown период. Не более N транзакций в час на адрес. Хранится в Redis с TTL.
Transaction type whitelist. Backend проверяет callData userOp: спонсируются только вызовы конкретных контрактов (ваше приложение), не произвольные транзакции.
Reputation system. Новые аккаунты получают минимальный лимит, который растёт со временем или после верификации (Worldcoin Proof of Humanity, Sign In With Ethereum + email).
Стек и инфраструктура
| Компонент | Технологии |
|---|---|
| Paymaster контракт | Solidity + eth-infinitism/account-abstraction |
| Backend signer | Node.js + viem + собственный signer wallet |
| Bundler | Stackup / Alchemy Bundler / собственный (go-bundler) |
| Rate limiting | Redis + BullMQ |
| Мониторинг депозита | Chainlink Automation / кастомный keeper |
| SDK для frontend | permissionless.js / ZeroDev SDK / Biconomy SDK |
| Тестирование | Foundry + hardhat-deploy для fork-тестов |
Выбор Bundler провайдера
Bundler — сервис, принимающий UserOperations и включающий их в блок. Варианты:
- Alchemy — простейший старт, хорошая документация, платный при масштабе
- Stackup — open-source bundler, можно self-host
- Pimlico — специализируется на AA, удобный Paymaster API
- Self-hosted (go-bundler) — полный контроль, нужна инфраструктура
Процесс разработки
Аналитика (2-3 дня). Тип Paymaster (sponsored vs ERC-20), целевые сети, лимиты и политики спонсирования, выбор Bundler провайдера.
Разработка контракта (1-2 недели). Verifying или ERC-20 Paymaster, тесты на EntryPoint v0.6/v0.7, deposit management.
Backend signer сервис (1 неделя). API для подписи UserOp, rate limiting, rate oracle (для ERC-20).
Интеграция с frontend (3-5 дней). SDK подключение, UserOperation построение, мониторинг статуса.
Мониторинг и операции (3-5 дней). Алерты на баланс, auto-topup, dashboard расходов.
Базовый Verifying Paymaster с rate limiting — 3-4 недели. ERC-20 Paymaster с oracle и full мониторингом — 5-7 недель.







