Development of Account Abstraction Paymaster
ERC-4337 Account Abstraction removes one of the main barriers to Web3 entry: user is no longer required to hold native token (ETH, MATIC, BNB) to pay gas. Paymaster — contract in ERC-4337 stack, takes on paying gas for user. This is key component for applications where gasless UX is competitive requirement: onboarding new users, gaming, social apps.
How Paymaster Fits into ERC-4337
In standard transaction: user → signs transaction → pays gas in ETH. In ERC-4337 flow: user signs UserOperation (not transaction) → Bundler collects UserOps in batch → EntryPoint contract calls validatePaymasterUserOp → if Paymaster approves — pays gas → postOp is called after execution.
UserOperation {
sender, // user's smart account
callData, // what to execute
paymasterAndData, // Paymaster address + its data
signature, // user's signature
...gasFields
}
paymasterAndData — this is address(paymaster) + bytes(paymasterSpecificData). Paymaster decodes its data from this field.
Types of Paymasters and Their Architecture
Verifying Paymaster (Sponsored Gas)
Most common pattern: off-chain service decides whether to sponsor specific UserOperation, and signs permission. Paymaster contract verifies this signature.
contract VerifyingPaymaster is BasePaymaster {
address public verifyingSigner;
function _validatePaymasterUserOp(
UserOperation calldata userOp,
bytes32 userOpHash,
uint256 maxCost
) internal override returns (bytes memory context, uint256 validationData) {
// Decode data: backend signature + validity period
(uint48 validUntil, uint48 validAfter, bytes calldata signature) =
abi.decode(userOp.paymasterAndData[20:], (uint48, uint48, bytes));
// Hash for verification = UserOp hash + validUntil + validAfter
bytes32 hash = ECDSA.toEthSignedMessageHash(
keccak256(abi.encode(userOpHash, validUntil, validAfter))
);
// If signature from verifyingSigner — sponsor
if (ECDSA.recover(hash, signature) != verifyingSigner) {
return ("", _packValidationData(true, validUntil, validAfter));
}
return ("", _packValidationData(false, validUntil, validAfter));
}
}
Backend receives UserOp from frontend, checks conditions (user in whitelist? reached free transaction limit? operation type allowed?), signs and returns paymasterAndData. Frontend puts in UserOp and sends to Bundler.
ERC-20 Paymaster (Gas in Tokens)
User pays gas in USDC/USDT instead of ETH. Paymaster accepts ERC-20 and tops up its ETH deposit in EntryPoint from own funds.
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;
// Check user's allowance
require(
IERC20(token).allowance(userOp.sender, address(this)) >= tokenCost,
"Insufficient allowance"
);
// Pass context to postOp for actual deduction
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));
// Actual cost might be less than maxCost
uint256 actualTokenCost = (actualGasCost * exchangeRate) / 1e18;
IERC20(token).transferFrom(sender, address(this), actualTokenCost);
}
Key complexity of ERC-20 Paymaster — exchange rate. Need current ETH/token rate at transaction time. Options: Chainlink oracle, TWAP from Uniswap V3, or centralized price feed from backend.
Deposit and Balance Management
Paymaster must hold ETH deposit in EntryPoint contract. EntryPoint deducts gas from this deposit after each sponsored UserOperation.
// Topping up deposit
entryPoint.depositTo{value: 1 ether}(address(paymaster));
// Checking balance
uint256 balance = entryPoint.balanceOf(address(paymaster));
// Withdrawing (unstake period for staked Paymaster)
entryPoint.withdrawTo(payable(owner), amount);
For production, need balance monitoring and auto-topup. If deposit runs out — all UserOps through this Paymaster start reverting. Recommend: alert at balance below threshold + auto-topup from treasury via Chainlink Automation or custom keeper.
Rate Limiting and Abuse Protection
Without restrictions, one user can drain entire Paymaster budget through spam transactions. Protection strategies:
Per-user spending limit. Off-chain in Verifying Paymaster backend: each address has monthly limit in USD. Backend refuses signature on exceeding.
Cooldown period. No more than N transactions per hour per address. Stored in Redis with TTL.
Transaction type whitelist. Backend checks UserOp callData: only specific contract calls sponsored (your application), not arbitrary transactions.
Reputation system. New accounts get minimal limit, growing over time or after verification (Worldcoin Proof of Humanity, Sign In With Ethereum + email).
Stack and Infrastructure
| Component | Technologies |
|---|---|
| Paymaster contract | Solidity + eth-infinitism/account-abstraction |
| Backend signer | Node.js + viem + own signer wallet |
| Bundler | Stackup / Alchemy Bundler / own (go-bundler) |
| Rate limiting | Redis + BullMQ |
| Deposit monitoring | Chainlink Automation / custom keeper |
| Frontend SDK | permissionless.js / ZeroDev SDK / Biconomy SDK |
| Testing | Foundry + hardhat-deploy for fork-tests |
Choosing Bundler Provider
Bundler — service accepting UserOperations and including them in block. Options:
- Alchemy — simplest start, good documentation, paid at scale
- Stackup — open-source bundler, can self-host
- Pimlico — specializes in AA, convenient Paymaster API
- Self-hosted (go-bundler) — full control, need infrastructure
Development Process
Analytics (2-3 days). Paymaster type (sponsored vs ERC-20), target networks, limits and sponsorship policies, Bundler provider selection.
Contract development (1-2 weeks). Verifying or ERC-20 Paymaster, tests on EntryPoint v0.6/v0.7, deposit management.
Backend signer service (1 week). UserOp signature API, rate limiting, rate oracle (for ERC-20).
Frontend integration (3-5 days). SDK connection, UserOperation building, status monitoring.
Monitoring and operations (3-5 days). Balance alerts, auto-topup, spending dashboard.
Basic Verifying Paymaster with rate limiting — 3-4 weeks. ERC-20 Paymaster with oracle and full monitoring — 5-7 weeks.







