Skip to main content

Custom Paymasters

Developers can deploy a Paymaster compatible with EntryPoint v0.7 to pay Gas for UserOperations that satisfy a custom policy. Developers are responsible for maintaining the custom Paymaster contract, sponsorship service, funds, signature policy, risk controls, and availability.

Paymaster validation and execution flow

Reference implementations:

1. IPaymaster API​

interface IPaymaster {
enum PostOpMode {
opSucceeded,
opReverted,
postOpReverted
}

function validatePaymasterUserOp(
PackedUserOperation calldata userOp,
bytes32 userOpHash,
uint256 maxCost
) external returns (
bytes memory context,
uint256 validationData
);

function postOp(
PostOpMode mode,
bytes calldata context,
uint256 actualGasCost,
uint256 actualUserOpFeePerGas
) external;
}

1.1 validatePaymasterUserOp​

ParameterDescription
userOpComplete PackedUserOperation to sponsor
userOpHashUserOperation hash bound to EntryPoint and chainId
maxCostMaximum cost calculated from the UserOperation Gas limits and prices

Return values:

FieldDescription
contextContext passed to postOp; empty bytes means that postOp is not required
validationDataSignature validity and time range

Paymaster validationData has the same layout as account validation data:

Low 160 bits: 0 for valid, 1 for signature failure
Next 48 bits: validUntil; 0 means no expiry
High 48 bits: validAfter

A Paymaster cannot return an aggregator address. A value other than 0 or 1 in the low 160 bits causes validation to fail.

This method must:

  • Accept calls only from the bound EntryPoint.
  • Validate paymasterData, sender, target call, limit, and expiry.
  • Revert or return signature failure for a UserOperation that violates the sponsorship policy.
  • Perform budget and quota checks within maxCost.
  • Comply with the Bundler's ERC-7562 storage-access and state-change rules.

1.2 postOp​

ParameterDescription
modeWhether UserOperation execution succeeded or reverted
contextContext returned by the validation stage
actualGasCostActual Gas cost incurred before postOp is called
actualUserOpFeePerGasActual Gas price paid by this UserOperation

PostOpMode values:

ValueDescription
opSucceededAccount business call succeeded
opRevertedAccount business call reverted; the Paymaster still pays the Gas
postOpRevertedInternal EntryPoint cleanup state; it is not passed to the Paymaster as a call argument

EntryPoint calls postOp only when context is non-empty. If validation returns a non-empty context, the Paymaster must provide a reliable postOp. A postOp revert causes the UserOperation to fail, but the Gas already consumed must still be paid.

2. BasePaymaster​

BasePaymaster.sol provides EntryPoint binding, caller validation, and deposit and stake management. A subclass only needs to implement sponsorship-policy logic.

2.1 Subclass extension interfaces​

function _validatePaymasterUserOp(
PackedUserOperation calldata userOp,
bytes32 userOpHash,
uint256 maxCost
) internal virtual returns (
bytes memory context,
uint256 validationData
);

function _postOp(
PostOpMode mode,
bytes calldata context,
uint256 actualGasCost,
uint256 actualUserOpFeePerGas
) internal virtual;

_validatePaymasterUserOp is required. Override _postOp when validation returns non-empty context; the default BasePaymaster _postOp reverts.

2.2 Fund-management interfaces​

function entryPoint() external view returns (address);

function deposit() external payable;

function getDeposit() external view returns (uint256);

function withdrawTo(
address payable withdrawAddress,
uint256 amount
) external;

function addStake(uint32 unstakeDelaySec) external payable;

function unlockStake() external;

function withdrawStake(
address payable withdrawAddress
) external;

Except for deposit, BasePaymaster restricts withdrawal and stake-management methods to the Owner.

3. RPC UserOperation fields​

When using a Paymaster, the RPC UserOperation contains:

FieldTypeDescription
paymasteraddressPaymaster contract address
paymasterVerificationGasLimitQUANTITYGas limit for Paymaster validation
paymasterPostOpGasLimitQUANTITYGas limit for Paymaster postOp
paymasterDataDATACustom authorization, signature, or policy data

Both Gas limits must be present in the final submitted object. The Paymaster implementation and sponsorship service define the paymasterData format.

Omit all four fields when no Paymaster is used. Do not provide the zero address.

4. paymasterAndData layout​

The RPC fields are packed into PackedUserOperation using this layout:

Offset 0, length 20 bytes: paymaster
Offset 20, length 16 bytes: paymasterVerificationGasLimit
Offset 36, length 16 bytes: paymasterPostOpGasLimit
Offset 52 to the end: paymasterData

When a Paymaster is used, this field is at least 52 bytes long. When no Paymaster is used, paymasterAndData is empty bytes.

5. Deposit and stake​

5.1 Deposit​

The deposit pays actual UserOperation Gas. EntryPoint checks and reserves the required prefund during validation.

InterfaceDescription
depositTo(paymaster)Adds to the Paymaster's Gas deposit
balanceOf(paymaster)Queries the available deposit
withdrawToWithdraws the Paymaster's own deposit

An insufficient deposit produces AA31 paymaster deposit too low.

5.2 Stake​

Stake supports the Bundler's reputation and denial-of-service protections; it does not directly pay Gas.

InterfaceDescription
addStakeAdds stake and sets the unlock delay
unlockStakeBegins the unlock waiting period
withdrawStakeWithdraws the stake after the waiting period

When a Paymaster accesses associated storage or changes certain state during validation, the Bundler may require a minimum stake and unstake delay. Exact thresholds depend on Bundler configuration.

6. Common errors​

ErrorMeaning
AA31Paymaster deposit is insufficient
AA32Paymaster validationData time range is invalid
AA33validatePaymasterUserOp reverted
AA34Low 160 bits of Paymaster validationData are not 0
AA36Paymaster validation exceeded its Gas limit
PostOpRevertedpostOp reverted; also inspect the PostOpRevertReason event
AA93paymasterAndData length or layout is invalid