사용자 정의 Paymaster
EntryPoint v0.7 호환 Paymaster를 배포해 정책을 충족하는 UserOperation의 Gas를 지불할 수 있습니다. 컨트랙트, 스폰서 서비스, 자금, 서명 정책, 위험 관리 및 가용성은 개발자가 관리합니다.

참조 구현:
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
| 파라미터 | 설명 |
|---|---|
userOp | 스폰서할 전체 PackedUserOperation |
userOpHash | EntryPoint와 chainId에 바인딩된 hash |
maxCost | Gas 한도와 가격으로 계산한 최대 비용 |
| 반환값 | 설명 |
|---|---|
context | postOp에 전달할 컨텍스트, 빈 bytes면 postOp 불필요 |
validationData | 서명 유효성 및 시간 범위 |
하위 160 bit: 0은 유효, 1은 서명 실패
다음 48 bit: validUntil, 0은 만료 없음
상위 48 bit: validAfter
Paymaster는 집계기 주소를 반환할 수 없습니다. 하위 160 bit가 0 또는 1이 아니면 검증에 실패합니다.
이 메서드는 다음을 충족해야 합니다.
- 연결된 EntryPoint의 호출만 허용합니다.
paymasterData, sender, 대상 호출, 한도 및 만료를 검증합니다.- 스폰서 정책을 위반하면 revert하거나 서명 실패를 반환합니다.
maxCost범위에서 예산과 할당량을 확인합니다.- Bundler의 ERC-7562 storage 접근 및 상태 변경 규칙을 준수합니다.
1.2 postOp
| 파라미터 | 설명 |
|---|---|
mode | UserOperation 실행 성공 또는 revert |
context | 검증 단계에서 반환한 컨텍스트 |
actualGasCost | postOp 호출 전 실제 Gas 비용 |
actualUserOpFeePerGas | 실제 지불한 Gas 단가 |
| 값 | 설명 |
|---|---|
opSucceeded | 비즈니스 호출 성공 |
opReverted | 비즈니스 호출 revert, Paymaster는 Gas를 지불 |
postOpReverted | EntryPoint 내부 정리 상태이며 호출 인자로 전달되지 않음 |
EntryPoint는 context가 비어 있지 않을 때만 postOp를 호출합니다. 컨텍스트를 반환하는 Paymaster는 신뢰할 수 있는 postOp를 구현해야 합니다. postOp revert 시 UserOperation은 실패하지만 이미 사용한 Gas는 지급됩니다.
2. BasePaymaster
BasePaymaster.sol은 EntryPoint 연결, 호출자 검증, deposit 및 stake 관리를 제공합니다.
2.1 하위 클래스 확장 인터페이스
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는 필수입니다. 비어 있지 않은 context를 반환하면 _postOp를 재정의합니다. BasePaymaster 기본 _postOp는 revert합니다.
2.2 자금 관리 인터페이스
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;
deposit을 제외한 인출 및 stake 관리 메서드는 Owner로 제한됩니다.
3. RPC UserOperation 필드
| 필드 | 타입 | 설명 |
|---|---|---|
paymaster | address | Paymaster 컨트랙트 주소 |
paymasterVerificationGasLimit | QUANTITY | Paymaster 검증 Gas 한도 |
paymasterPostOpGasLimit | QUANTITY | postOp Gas 한도 |
paymasterData | DATA | 사용자 정의 권한, 서명 또는 정책 데이터 |
최종 전송 객체에는 두 Gas 한도가 모두 필요합니다. paymasterData 형식은 구현과 스폰서 서비스가 정의합니다. Paymaster를 사용하지 않으면 네 필드를 모두 생략하고 0 주소를 넣지 마세요.
4. paymasterAndData 레이아웃
offset 0, 20 bytes: paymaster
offset 20, 16 bytes: paymasterVerificationGasLimit
offset 36, 16 bytes: paymasterPostOpGasLimit
offset 52 이후: paymasterData
Paymaster 사용 시 최소 52 bytes이며 미사용 시 빈 bytes입니다.
5. Deposit 및 stake
5.1 Deposit
Deposit은 실제 UserOperation Gas를 지급하며 EntryPoint는 검증 중 필요한 prefund를 확인하고 예약합니다.
| 인터페이스 | 설명 |
|---|---|
depositTo(paymaster) | Gas deposit 추가 |
balanceOf(paymaster) | 사용 가능한 deposit 조회 |
withdrawTo | Paymaster 자신의 deposit 인출 |
부족하면 AA31 paymaster deposit too low가 발생합니다.
5.2 Stake
Stake는 Bundler 평판과 서비스 거부 공격 방어에 사용되며 Gas를 직접 지급하지 않습니다.
| 인터페이스 | 설명 |
|---|---|
addStake | stake 추가 및 잠금 해제 지연 설정 |
unlockStake | 대기 기간 시작 |
withdrawStake | 대기 기간 후 인출 |
검증 중 관련 storage에 접근하거나 특정 상태를 변경하면 Bundler가 최소 stake와 unstake delay를 요구할 수 있습니다. 임계값은 Bundler 설정에 따릅니다.
6. 일반 오류
| 오류 | 의미 |
|---|---|
AA31 | Paymaster deposit 부족 |
AA32 | validationData 시간 범위 무효 |
AA33 | validatePaymasterUserOp revert |
AA34 | validationData 하위 160 bit가 0이 아님 |
AA36 | 검증 Gas 한도 초과 |
PostOpReverted | postOp revert, PostOpRevertReason도 확인 |
AA93 | paymasterAndData 길이 또는 레이아웃 무효 |